Compare commits

...

412 Commits

Author SHA1 Message Date
Asaf Gartner da80261202 Trying to lazy-load timeline images 2024-07-08 14:19:45 +03:00
Asaf Gartner 5fb6bf59f7 Reduced number of timeline items in featured/recent on landing page 2024-07-08 14:12:52 +03:00
Asaf Gartner 6bd3f682f4 Reduced number of news posts on landing page 2024-07-08 14:07:02 +03:00
Asaf Gartner 9537917a8e Accidentally broke old header 2024-07-07 13:39:58 +03:00
Asaf Gartner e06666a570 Probably fixed episode guide with redir to official HMH guide 2024-07-07 13:34:00 +03:00
Asaf Gartner 4be6e89298 Added admin approval queue to user dropdown for admins 2024-07-07 13:23:40 +03:00
Asaf Gartner 27deef56af Only embed youtube when the user hits play 2024-07-07 13:21:19 +03:00
Ben Visness 4b26a92018 Add an admin command for listing newsletter emails 2024-07-06 16:16:26 -05:00
Ben Visness 86b87b2ec8 Update minimum Go version to 1.21
This is the earliest officially-supported version of Go at this point.
2024-07-06 16:10:06 -05:00
Ben Visness 411fb66e40 Suppress forum posts on the featured feed 2024-07-06 12:15:23 -05:00
Ben Visness 7055b59087 Direct /jam to the right place 2024-07-06 11:00:54 -05:00
Asaf Gartner a9b8b284bf Fixed approval queue again 2024-07-06 18:52:39 +03:00
Asaf Gartner 5ea589dbfa Featured users 2024-07-06 18:47:46 +03:00
Asaf Gartner ed41600061 Fixed approval queue 2024-07-06 18:33:50 +03:00
Asaf Gartner a22b44eb07 Fixed link editor on new project creation 2024-07-06 13:04:08 +03:00
Asaf Gartner b6017fefff Used the common limit per tab on landing page 2024-07-06 12:54:39 +03:00
Asaf Gartner 1163640121 Added a limit to the number of items on the landing page following tab 2024-07-06 12:52:50 +03:00
Asaf Gartner 0497b262f4 Include credentials for follow link from subdomains 2024-07-06 12:47:52 +03:00
Asaf Gartner d4a17c8482 Made 'member since' dates fit the user profile's sidebar 2024-07-06 12:39:56 +03:00
Asaf Gartner 6489ff522e Added user's name to profile 2024-07-06 12:33:36 +03:00
Asaf Gartner df0e57f4cc Limit number of timeline items with SQL 2024-07-06 12:01:08 +03:00
Asaf Gartner 3a492059de Trying to speed up the query 2024-07-06 11:50:05 +03:00
Asaf Gartner 07154fb8b4 Only fetch post content when necessary 2024-07-06 11:31:42 +03:00
Asaf Gartner 966214d03f Deduplicate project_ids before querying projects for timeline 2024-07-06 11:23:44 +03:00
Asaf Gartner 43a3178b08 Slow query logging 2024-07-06 11:03:57 +03:00
Asaf Gartner 36aec19898 Actually correct grouping of ANDs and ORs in the SQL 2024-07-06 10:46:56 +03:00
Asaf Gartner f47a4617bc SQL-based project visibility and ownership test 2024-07-06 10:43:34 +03:00
Ben Visness 2b59b392a6 Get rid of the theme color (it was from the jam) 2024-07-05 16:20:29 -05:00
Ben Visness c7d8798248 catastropostrophe 2024-07-05 16:18:49 -05:00
Ben Visness a261cb3f7a Delete all scss 2024-07-05 16:12:10 -05:00
Ben Visness 9ab533dc32 Further blog post tweaks 2024-07-05 15:57:05 -05:00
Ben Visness 716014c607 Rework blog page, add latest news + unread 2024-07-05 15:50:11 -05:00
Ben Visness c624f722f7 Further tachyons breakpoint tweaks 2024-07-05 13:45:17 -05:00
Ben Visness 56028c78de Link tweaks? 2024-07-05 13:44:50 -05:00
Ben Visness e1ee5c6635 Project edit tweaks 2024-07-05 13:40:13 -05:00
Ben Visness b6ed35902d User profile tweaks 2024-07-05 13:10:52 -05:00
Ben Visness d16670360e Project homepage tweaks 2024-07-05 12:58:59 -05:00
Ben Visness ffcaf6c463 Tweaks to project index 2024-07-05 12:47:55 -05:00
Ben Visness ab545c1caf Visibility jam mobile tweaks 2024-07-05 12:42:09 -05:00
Ben Visness 1af2f57240 Remove wishlist command 2024-07-05 12:42:03 -05:00
Ben Visness b5a34e3ab1 Header tweaks, guidelines link 2024-07-05 12:35:01 -05:00
Ben Visness 352a102a6a Make navigation mobile-friendly 2024-07-05 12:15:32 -05:00
Ben Visness 5f2df52e1d Add opengraph / twitter images 2024-07-05 10:55:15 -05:00
Ben Visness e011ec4553 New jam logo 2024-07-05 10:28:22 -05:00
Ben Visness c49a5e0bb3 Add banner and maybe other things, I do not remember 2024-07-04 17:26:36 -05:00
Ben Visness bcc27b06d9 Visibility jam landing page 2024-07-04 16:45:37 -05:00
Asaf Gartner b591e5f6bd Project edit - editing owners with preview 2024-07-04 06:32:15 +03:00
Asaf Gartner f706709c34 Removed whenisit 2024-07-04 05:22:50 +03:00
Asaf Gartner c5c773e82a Image selector errors 2024-07-03 10:59:40 +03:00
Asaf Gartner a9918cc2fb Slightly nicer admin panel in user_profile 2024-07-03 10:14:36 +03:00
Asaf Gartner 280ccb3bcd Client-side timeline filters for projects 2024-07-03 10:09:55 +03:00
Ben Visness dffd1c94b5 Add a profile dropdown menu 2024-07-02 22:58:33 -05:00
Ben Visness a646dddec0 Put the follow link in a gooder spot 2024-07-02 22:22:38 -05:00
Ben Visness 22c70cda8e Add live preview of project card stuff 2024-07-02 22:11:41 -05:00
Ben Visness 51ad8d03d4 Add interactive link previews 2024-07-02 21:23:39 -05:00
Asaf Gartner bab955aaff Blog posts are useable 2024-07-02 13:20:05 +03:00
Asaf Gartner b11114b002 User settings tabs 2024-07-02 12:57:39 +03:00
Ben Visness a98cce4b4b wew edit link wew 2024-07-01 22:46:38 -05:00
Asaf Gartner 908c8b02f8 Link editor 2024-07-01 02:55:46 +03:00
Ben Visness ba86da3374 Make the home page remember what tab you were on 2024-06-29 15:52:58 -05:00
Asaf Gartner 4ae8f2c7b9 Truncate long user/project names on landing page sidebar 2024-06-29 23:36:22 +03:00
Ben Visness 46afc573f6 Add project authors, improve user profiles 2024-06-29 14:18:26 -05:00
Ben Visness 3b33565cd9 A little TODO maintenance 2024-06-29 11:40:38 -05:00
Ben Visness a6cfeb9c95 Various project and login improvements 2024-06-29 11:39:18 -05:00
Ben Visness 1b97bbb2d9 Remove post descriptions from timelines by default 2024-06-28 22:53:46 -05:00
Ben Visness 9093f38b47 Update project index a bit, track snippet updates for project recency 2024-06-28 22:37:05 -05:00
Ben Visness 06b270514c Overhaul CSS vars 2024-06-27 17:34:09 -05:00
Asaf Gartner a602e02c9c Fixed timeline query for user+project combo 2024-06-27 23:13:22 +03:00
Asaf Gartner f9ada49278 Unified timeline query 2024-06-27 22:45:23 +03:00
Asaf Gartner 410c94bb51 Merge branch 'nuke-scss' of git.handmade.network:hmn/hmn into nuke-scss 2024-06-25 22:50:51 +03:00
Asaf Gartner fd643114b6 User settings 2024-06-25 22:49:24 +03:00
Ben Visness 737b481ff0 Add construction banner to the old base 2024-06-24 18:48:37 -05:00
Ben Visness 38cda22be9 Fix following button when logged out 2024-06-24 13:56:35 -05:00
Ben Visness 163eba8475 Add all tabs to home page 2024-06-24 13:36:50 -05:00
Ben Visness fe051080a6 Random styles 2024-06-24 12:24:30 -05:00
Ben Visness f42990ef96 Improve appearance of snippets per new styles 2024-06-23 13:05:36 -05:00
Asaf Gartner 5cdaa4e393 Static pages 2024-06-23 17:26:28 +03:00
Asaf Gartner 497fda3251 Snippet page and edit 2024-06-23 17:12:20 +03:00
Asaf Gartner 5e7478fda7 Error page 2024-06-23 16:53:17 +03:00
Asaf Gartner f29f697841 404 page 2024-06-23 16:51:06 +03:00
Ben Visness 81cb17b6eb Man whatever 2024-06-23 08:40:50 -05:00
Ben Visness a0bd55f3d2 Add login widget when not logged in 2024-06-21 20:47:10 -05:00
Ben Visness 698a301c57 Make home page sidebar cards collapsible 2024-06-21 20:24:55 -05:00
Ben Visness ca02716023 Add little sidebar footer links 2024-06-21 20:16:32 -05:00
Ben Visness 86825f1c09 Add projects / following UI to home page 2024-06-21 20:13:20 -05:00
Ben Visness 7144db58ed Start scaffolding landing page 2024-06-21 17:40:18 -05:00
Ben Visness d242c71a2b Fix timeline bug with deleted users 2024-06-20 19:29:54 -05:00
Ben Visness 5427092708 Fix incorrect snippet queries (and generify some utilities) 2024-06-20 19:17:06 -05:00
Ben Visness 06781b3b16 Re-date a migration because sadness 2024-06-20 18:17:07 -05:00
Ben Visness 04bc4e5035 Remove light/dark theme settings entirely
There is simply no need any more; system light/dark preferences handle this fine.
2024-06-20 18:09:16 -05:00
Asaf Gartner d9073db5d0 Timeline/follow fetching done 2024-06-20 18:09:15 -05:00
Asaf Gartner 6a28660407 Follow infrastructure 2024-06-20 18:08:14 -05:00
Ben Visness 3ff6ba6563 Remove showcase, obliterate landing stuff 2024-06-20 18:04:39 -05:00
Asaf Gartner 8cd968a495 Some more screens 2024-06-20 22:01:11 +03:00
Asaf Gartner 02a41f56bd Updated a bunch of pages 2024-06-20 18:29:36 +03:00
Asaf Gartner f37635829d Replaced :invalid with :user-invalid so inputs won't be invalid on page load 2024-06-20 18:28:42 +03:00
Ben Visness 66805bc2b6 Don't completely die on template syntax errors 2024-06-17 20:01:52 -05:00
Ben Visness 9537fef995 Update a bunch of colors for light mode 2024-06-17 19:39:21 -05:00
Ben Visness 75e21ccbe9 Handle empty project links correctly 2024-06-07 10:35:57 -04:00
Asaf Gartner 7410fbcd4a EsBuild with on-request rebuild and hot-reloading 2024-06-07 10:30:02 -04:00
Ben Visness d0c7605029 Reworked project edit page (no preview yet) 2024-06-07 10:30:01 -04:00
Ben Visness be7440acce New project home pages (incomplete) 2024-06-07 10:27:40 -04:00
Ben Visness 1a0be1912e Implement new header / footer (mostly) 2024-06-07 10:27:20 -04:00
Ben Visness 19a8c6bf0d Mostly convert old styles to plain CSS
wow there is a lot of garbage in here
2024-06-07 10:27:20 -04:00
Ben Visness 6dd2a32780 Add Unwind URL 2024-05-24 19:15:18 -05:00
Ben Visness b681bacc16 Disable Freyabot 2024-05-21 15:56:32 -05:00
Ben Visness 9ecb65985e Don't show blog thing on project blogs 2024-05-20 17:02:06 -05:00
Ben Visness 04db4ad709 Add email newsletter signup to blogs 2024-05-20 17:00:03 -05:00
Asaf Gartner 1aab3b47b3 FreyaMode won't affect other message processing steps 2024-05-14 17:55:23 +03:00
Ben Visness 23b1b30d22 Less wrong Freya mode, I hope 2024-05-14 09:40:05 -05:00
Ben Visness ac54793fd0 Freya mode 2024-05-14 09:32:49 -05:00
Ben Visness 852ff7e53f Un-typo 2024-05-08 21:03:49 -05:00
Ben Visness 22265c9081 Add upcoming jam page 2024-05-08 21:01:04 -05:00
Asaf Gartner 7fd57f692b Handmade Cities banner 2024-05-01 07:15:28 +03:00
Asaf Gartner 71d236f1c2 Replaced twitch embed with youtube embed for the LJ2024 recap show. 2024-04-03 19:11:40 +03:00
Asaf Gartner 4568def378 Added a bunch of discord debugging 2024-03-28 21:24:46 +02:00
Ben Visness e8201a254e no the jam does not end now I refuse 2024-03-24 16:11:51 -05:00
Asaf Gartner 2065bad860 Added tooltip to project owners on the LJ page. 2024-03-14 02:31:59 +02:00
Ben Visness 5dd4880d4c heaaaghghghghg jam time yayaya 2024-03-12 23:20:35 -05:00
Ben Visness ee491c7696 Learning jam final design phase 1 2024-03-12 21:13:05 -05:00
Asaf Gartner f085858e9e Merge remote-tracking branch 'origin/beta' 2024-03-11 20:17:44 +02:00
Asaf Gartner 639ea17a88 Timeline and projects for learning jam 2024-03-11 20:15:32 +02:00
Asaf Gartner 2eb3288b2a LJ jam feed basics 2024-03-11 18:27:34 +02:00
Ben Visness 27dcdb4704 Also opengraph 2024-03-08 19:10:45 -06:00
Ben Visness 5aa9dde8a1 Soften language about "teaching" for the learning jam 2024-03-08 19:03:51 -06:00
Asaf Gartner cd36eb44eb Don't require url/asset for snippet creation from discord. 2024-03-04 21:19:56 +02:00
Asaf Gartner 444f43a195 Added !til for discord messages 2024-03-04 21:09:40 +02:00
Ben Visness 6fba490392 Add Twitter metadata 2024-02-14 12:13:59 -06:00
Asaf Gartner 7800cd9fe1 Added -webkit- prefix to mask and clip css props 2024-02-12 20:41:26 +02:00
Ben Visness 1e5c0c7b42 Icons, favicons, jam index fix 2024-02-11 10:15:13 -06:00
Ben Visness 032d6c435e Temporarily remove icons 2024-02-10 22:08:02 -06:00
Ben Visness 16e4b0327f Opengraph and banner 2024-02-10 22:06:43 -06:00
Ben Visness 97e6c74c52 Many change for great good yes 2024-02-10 20:54:13 -06:00
Ben Visness c5e458be8c Lay out top section 2024-02-09 15:02:58 -06:00
Asaf Gartner b5d4fe9ba2 Learning jam scaffolding 2024-02-08 22:21:01 +02:00
Ben Visness d896298117 go mod tidy 2024-02-04 10:49:53 -06:00
Asaf Gartner 845a2d377c Clear href when no calendars selected 2024-01-28 19:52:49 +02:00
Asaf Gartner 79dcef9b7f Changed url so thunderbird picks a better name for the calendar 2024-01-28 19:36:55 +02:00
Asaf Gartner d347b42e44 Added CALNAME prop 2024-01-28 19:27:25 +02:00
Asaf Gartner 8bc4b5a66c Added calendars 2024-01-28 19:12:59 +02:00
Ben Visness 76be9b668a Republish Discord announcements to Abner's Matrix server 2023-12-05 23:55:39 -06:00
Ben Visness 594860a080 Remove HMC banner (can reintroduce later when media is ready or whatever) 2023-11-20 17:48:01 -06:00
Ben Visness 0276e5228c Add jam recap stream 2023-10-16 11:49:15 -05:00
Asaf Gartner edeb519ddb Switch to correct twitch account for jam embed 2023-10-14 17:43:28 +03:00
Asaf Gartner 38acf4a904 Testing jam embed 2023-10-14 17:39:57 +03:00
Ben Visness c6893f3f3f Enswankinate the project page completely 2023-09-25 10:02:34 -05:00
Ben Visness 25cc5ef11b Rework structure of project index. Need new copy. 2023-09-25 02:40:45 -05:00
Ben Visness 45b4928d83 Convert db download script to Python 2023-09-24 17:25:12 -05:00
Ben Visness ca46c23d31 Add Lil UEFI to the jam page 2023-09-20 18:08:15 -05:00
Ben Visness 36753d2a45 Tweak confusing "in x days" language 2023-09-20 16:55:49 -05:00
Ben Visness 16020a5b30 Update jam page with motivational speech 2023-09-20 16:53:18 -05:00
Ben Visness 2e3cb658af Add banner image for emails 2023-09-16 16:26:07 -05:00
Ben Visness c83458fd30 Add a non-breaking
space
2023-09-05 18:44:04 -05:00
Ben Visness a9ef54b98b Video posters (and better Orca video) 2023-09-01 19:42:39 -05:00
Ben Visness b5ef12fa60 Update opengraph subtitle 2023-09-01 19:36:07 -05:00
Ben Visness cae9fecc7c oops 2023-09-01 19:34:45 -05:00
Ben Visness 6616e72ca6 Copy updates for WRJ2023 2023-09-01 19:33:18 -05:00
Asaf Gartner 4533e8ae66 WRJ banner colors 2023-09-01 17:46:44 +03:00
Asaf Gartner fdc7582701 Added WRJ2023 2023-09-01 17:35:40 +03:00
Ben Visness 74f438afad miscellaneous characters from my keyboard 2023-08-21 21:19:35 -04:00
Ben Visness ad62793262 Add Leonard 2023-07-21 21:55:58 -05:00
Ben Visness 922690244d Add Agustin's second submission (oops) 2023-07-19 21:13:20 -05:00
Ben Visness 368e657a79 Send an email if you sign up with an existing email 2023-07-19 17:36:00 -05:00
Ben Visness 7b2d016fe2 Add agus_dev's submission 2023-07-12 18:06:53 -05:00
Ben Visness 0895660972 Allow multiple videos per Time Machine submission 2023-06-28 16:03:56 -05:00
Ben Visness 8aa18901b2 Add NCommander Win98 submission 2023-06-19 14:20:44 -05:00
Ben Visness 5bc118d9e0 Add licensing info to Time Machine submission form 2023-06-16 14:29:16 -05:00
Asaf Gartner 633f8f1007 Updated adminmailer to separate FromAddress and ServerUsername 2023-06-15 17:46:43 +03:00
Ben Visness 54aa6682b1 Add link to submissions feed
sorry for spamming main
2023-06-09 15:58:04 -07:00
Ben Visness c8808e21bf Add Atom feed (not yet linked) 2023-06-09 13:01:51 -07:00
Ben Visness 8be575875d Add time machine submissions page 2023-06-06 13:23:54 -05:00
Ben Visness dd6e5e3b66 Add newsletter redirect link 2023-06-02 09:46:26 -05:00
Ben Visness 57782aba5f Fix dataimg path bug 2023-06-01 21:18:48 -05:00
Ben Visness 1ea9fbefbc Merge branch 'feature/time_machine_page' 2023-06-01 21:08:54 -05:00
Ben Visness ca28fe8063 Remove Visibility Jam banner 2023-06-01 21:08:37 -05:00
Ben Visness a6caf8e9bd Style submit and thank-you pages 2023-06-01 20:42:02 -05:00
Asaf Gartner dcdbc67b6c Time machine submission form 2023-06-02 00:42:46 +03:00
Ben Visness 2d61286831 Add OpenGraph assets 2023-06-01 13:56:35 -05:00
Ben Visness bb31644d6d Add submission dialog 2023-05-31 23:45:08 -05:00
Ben Visness f8b0d9ba85 Styles upon styles 2023-05-31 23:10:42 -05:00
Ben Visness be888a98f1 Style updates + splash 2023-05-31 20:35:09 -05:00
Ben Visness 88323ffbaa N U A N C E 2023-05-29 09:54:12 -05:00
Ben Visness 1166bb6cf3 Add testing fishbowl description 2023-05-29 09:51:44 -05:00
Ben Visness 96ea2e0268 No thank you, we are too N U A N C E D 2023-05-29 09:41:27 -05:00
Jake Mason 64d98c424f Update image embed border colors for the Time Machine 2023-05-28 14:14:10 -04:00
Jake Mason 03a08ad392 Cleaning up 2023-05-28 14:10:36 -04:00
Ilia Demianenko 43b9f993dc Add testing fishbowl 2023-05-28 00:51:52 -07:00
Jake Mason a1c5086190 Add work on the new Time Machine page 2023-05-28 01:16:12 -04:00
Ben Visness cace7fbcb1 Update conferences page 2023-05-25 21:38:39 -05:00
Ben Visness 95bd54b39e Ok but actually use jpegs maybe 2023-05-18 23:00:31 -05:00
Ben Visness cdacc5b3a0 Use new thumbnails 2023-05-18 22:07:14 -05:00
Asaf Gartner 65aab39432 Asset thumbnail backend 2023-05-17 22:34:55 +03:00
Ben Visness 8dc458da73 Cover all URL builders with tests 2023-05-06 15:41:51 -05:00
bvisness 0210a0784b Add Discord login (#106)
This leverages our existing Discord OAuth implementation. Any users with a linked Discord account will be able to log in immediately. When logging in, we request the `email` scope in addition to `identity`, so existing users will be prompted one time to accept the new permissions. On subsequent logins, Discord will skip the prompt.

When linking your Discord account to an existing HMN account, we continue to only request the `identity` scope, so we do not receive the user's Discord email.

Both login and linking go through the same Discord OAuth callback. All flows through the callback try to achieve the same end goal: a logged-in HMN user with a linked Discord account.

Linking works the same as it ever has. Login, however, is different because we do not have a session ID to use as the OAuth state. To account for this, I have added a `pending_login` table that stores a secure unique ID and the eventual destination URL. These pending logins expire after 10 minutes. When we receive the OAuth callback, we look up the pending login by the OAuth `state` and immediately delete it. The destination URL will be used to redirect the user to the right place.

If we have a `discord_user` entry for the OAuth'd Discord user, we immediately log the user into the associated HMN account. This is the typical login case. If we do not have a `discord_user`, but there is exactly one HMN user with the same email address as the Discord user, we will link the two accounts and log into the HMN account.

(It is possible for multiple HMN accounts to have the same email, because we don't have a uniqueness constraint there. We fail the login in this case rather than link to the wrong account.)

Finally, if no associated HMN user exists, a new one will be created. It will use the Discord user's username, email, and avatar. This user will have no password, but they can set or reset a password through the usual flows.

Co-authored-by: Ben Visness <bvisness@gmail.com>
Reviewed-on: hmn/hmn#106
2023-05-06 19:38:50 +00:00
Ben Visness 1b1c25da80 Fix CSS issue on jams page 2023-04-22 11:31:14 -05:00
Ben Visness e4dd15d248 Add all jams index 2023-04-22 11:26:07 -05:00
Ben Visness faac05a3a8 Put recap section on the main page 2023-04-22 09:18:34 -05:00
Ben Visness 79c4c14631 Add jam recap (not yet shown off properly) 2023-04-21 23:11:32 -05:00
Ben Visness fe1d99b7ab Style project descriptions better 2023-04-16 16:05:04 -05:00
Ben Visness 23e67638e4 Merge remote-tracking branch 'origin/beta' 2023-04-14 15:47:32 -05:00
Ben Visness 89dd2c52c7 Link back to the main jam page from the feed 2023-04-14 15:46:06 -05:00
Ben Visness b7d4883c6c Make news posts look a little nicer 2023-04-13 17:53:36 -05:00
Ben Visness 60a9ece643 News posts are BACK 2023-04-13 17:41:10 -05:00
Ben Visness 25f33451ca New manifesto?? 2023-04-12 19:10:29 -05:00
Asaf Gartner ef16a4f3e0 Fixed style and links for vis jam 2023-04-11 17:38:32 +03:00
Ben Visness 4651e8a477 &nbsp; 2023-04-08 13:09:28 -05:00
Ben Visness 44e055155e Redo the home page banner copy 2023-04-08 13:07:40 -05:00
Ben Visness 2cb367ba18 Update README to warn about wellington problems 2023-04-08 11:49:48 -05:00
Ben Visness fc6b979a46 Update implementation of utils.DirFS
It is now patterned after the Go 1.20 implementation, in order to better represent the current state of things in a proposal I am making.
2023-04-08 11:41:02 -05:00
Ben Visness 524cf8e27b Add ability to load templates live from the filesystem
See config.go.example.
2023-04-08 11:14:44 -05:00
Asaf Gartner 3a66b7a77d Restored jam dates 2023-04-07 01:13:41 +03:00
Asaf Gartner 4994cb7701 Testing postjam 2023-04-07 01:08:47 +03:00
Asaf Gartner c50d8f8ea4 Testing with different dates 2023-04-07 01:04:24 +03:00
Jake Mason 45b5c7f4d4 Updating Feed for VJ 2023 2023-04-06 14:54:14 -04:00
Jake Mason f9f0e1b119 Add VJ2023 to the AllJams list 2023-04-06 14:39:45 -04:00
Jake Mason 54c9af9c08 Hide counters until 30 days out 2023-03-24 21:22:17 -04:00
Jake Mason e616cc51fd One more mobile fix 2023-03-24 17:58:46 -04:00
Jake Mason c6cdc8a473 Some more mobile updates to the handmade cities banner 2023-03-24 17:52:42 -04:00
Jake Mason 20c4a277ff Update link for tickets, style adjustments 2023-03-24 17:46:40 -04:00
Jake Mason 0ccf3aba1a Add handmade cities banner v1 2023-03-24 17:38:24 -04:00
Ben Visness cf345ca592 Add a little more inspiration 2023-03-07 14:02:11 -06:00
Ben Visness 81b92d3aef Add special Twitter card 2023-03-07 12:09:22 -06:00
Ben Visness 5296e0a15a Fix jam opengraph 2023-03-07 11:57:44 -06:00
Ben Visness 55f56d8ae0 Vis jam landing page 2023-03-07 11:48:13 -06:00
Ben Visness bb38d0b759 Merge remote-tracking branch 'origin/feature/2023_frontend_updates' 2023-03-07 11:40:26 -06:00
Jake Mason 7a6cdbad0e Adding days of the week back - was looking at wrong year, doh! 2023-03-05 20:46:17 -05:00
Jake Mason 395ca8e765 Discord link added 2023-03-05 20:43:53 -05:00
Jake Mason 4bb562823e Opengraph images, and fix day-of-week references 2023-03-05 20:40:22 -05:00
Jake Mason 526a588a19 Visualization Jam 2023 template 2023-03-04 23:52:03 -05:00
Ben Visness 6d24738be6 Comment out the Handmade Seattle banner 2023-02-22 00:42:08 -06:00
Asaf Gartner a324af8a0c Updated example config 2023-01-29 08:53:57 +02:00
Asaf Gartner 859a78c079 Fixed excessive db conns in middleware and pgx race condition on init 2023-01-29 08:53:57 +02:00
Asaf Gartner aa6428f3a4 Removed remaining pgxv4 stuff and fixed twitch tags 2023-01-29 08:53:57 +02:00
Asaf Gartner 2af28d9f3f Update pgx v4 to pgx v5 2023-01-29 08:53:57 +02:00
Ben Visness 9e27835e51 Add /manifesto Discord command 2023-01-22 09:38:14 -06:00
Jake Mason 1825e93b04 Compile .scss assets 2023-01-16 23:02:54 -05:00
Jake Mason df253d0a33 Some more basic dropdown a11y considerations 2023-01-16 23:02:36 -05:00
Jake Mason ad904de16b Removing hrefs like this is breaks a11y entirely 2023-01-16 22:24:44 -05:00
Jake Mason 922d6283f8 Jump to content link for a11y 2023-01-16 22:22:23 -05:00
Jake Mason b2f8bb45cf Ignore session and tags files 2023-01-16 22:12:12 -05:00
Jake Mason 299bf5e065 Bump default mobile breakpoint, make login link cursor a pointer 2023-01-16 22:11:50 -05:00
Jake Mason 1db187e9d3 Note that the Postgres user needs to be created by the user 2023-01-16 21:19:36 -05:00
bvisness 348feff4cf Automatically handle HEAD requests (#104)
HEAD requests will be routed as GET requests, and Content-Type and Content-Length headers will always be sent for all requests.

Co-authored-by: Ben Visness <bvisness@gmail.com>
Reviewed-on: hmn/hmn#104
2023-01-13 18:52:31 +00:00
skytrias f3453355c4 allow #recent anchor 2023-01-12 02:42:57 +01:00
Asaf Gartner 620533784a Fixed showcase modal again 2023-01-03 00:20:43 +02:00
Asaf Gartner 77ac6d4200 Fixed timeline item css in jam page and showcase modal 2023-01-03 00:16:25 +02:00
Asaf Gartner 6d65785cef Changed the url for handmadedev show 2022-12-16 06:59:57 +02:00
Ben Visness cd31085c67 Nobody saw this 2022-12-14 19:23:32 -06:00
Ben Visness 9b3a972e37 Rework about page, finally
Start foundation / about page work

Add some job descriptions

Add Advocacy role

Make things look barely tolerable

Cloin'd

Better About intro

no fundo

Link from manifesto

swanky changes
2022-12-14 17:49:08 -06:00
Asaf Gartner 587ac7643f Merge branch 'master' into beta 2022-12-03 18:45:58 +02:00
Asaf Gartner badb845ab1 HMS banner goes to the 2022 guide, and the link on the conferences page
is fixed.
2022-12-03 18:44:52 +02:00
Ben Visness 5fe3e7560c A little more OpenGraph flavor 2022-11-05 16:27:55 -05:00
Ben Visness 084b13ae34 ...including the nav and stuff 2022-11-05 16:23:12 -05:00
Ben Visness f0597f3eb8 Open education up to all 2022-11-05 16:18:39 -05:00
Asaf Gartner bd1edb2077 Set education article's opengraph image to the first image in the
article
2022-11-05 18:25:01 +02:00
Ben Visness 5a983643a3 Exclude editor's notes from TOC 2022-11-02 22:40:44 -05:00
Ben Visness b75b59aad5 Add highlight to currently-selected education course 2022-10-31 17:39:19 -05:00
Ben Visness 2fbdf19f41 Fix the HTTP article slug 2022-10-31 16:01:42 -05:00
Ben Visness 48af5e650d Better edu home page 2022-10-27 00:20:59 -05:00
Ben Visness 4e44ba0b45 Make articles responsive 2022-10-26 13:26:01 -05:00
Ben Visness 8eee541ccc Scrap the "resource" tag, make figures nice 2022-10-26 12:32:39 -05:00
Asaf Gartner df194dd041 Fixed "add snippet" button text color in profile page. 2022-10-20 14:00:25 +03:00
Asaf Gartner 3abf4dd21b Probably fixed RSS issue in showcase feed. 2022-10-20 13:57:03 +03:00
Asaf Gartner 851f9e0f67 Fixed small logo css 2022-10-20 13:45:57 +03:00
Asaf Gartner a6ad01143a Twitch should work now hopefully. 2022-10-20 12:43:26 +03:00
Asaf Gartner d70f7d6b6d More twitch logs 2022-10-20 12:43:26 +03:00
Asaf Gartner 48451a49dd SQL fix 2022-10-20 12:43:26 +03:00
Asaf Gartner f548495813 Trying some debugging 2022-10-20 12:43:26 +03:00
Asaf Gartner 09d875a9f6 Trying another fix 2022-10-20 12:43:26 +03:00
Asaf Gartner d7f1325ace Better time truncation for stream notifications. 2022-10-20 12:43:26 +03:00
Asaf Gartner 56929e6e44 Fixed twitch history query 2022-10-20 12:43:26 +03:00
Asaf Gartner cf809a3cdc Twitch fixes 2022-10-20 12:43:26 +03:00
Asaf Gartner 0f58cfc2da Added support for db arrays and some twitch fixes. 2022-10-20 12:43:26 +03:00
Asaf Gartner 5cc920dc2f Better twitch tracking 2022-10-20 12:43:26 +03:00
Ben Visness 304371a9a9 The thing is at a place 2022-10-17 20:31:40 -05:00
Ben Visness 5aa5595115 Remove news posts 2022-10-17 20:20:50 -05:00
Ben Visness 968e859dde Show HMS banner 2022-10-17 20:13:58 -05:00
Ben Visness b5dac2f4d8 Add !!!figure tag to ggcode 2022-10-08 17:28:36 -05:00
Ben Visness 3d7c095c87 Add entrepreneurship fishbowl title/description 2022-10-03 15:31:17 -05:00
ilidemi 8189151a74 Add entrepereuship fishbowl (#99)
Code notes:
*  MathJax treats text between two dollar signs as math. Escaped those cases in html (`\$`) - is there a way to not run mathjax on fishbowls instead?
* Limited embed image sizes to match Discord
* Fixed replies to a quote wrapping on a new line

Content notes:
* Moved intros to the top, untangled the discussions (hopefully without significant loss), pulled in audience comments
* Most book links are to Amazon as the promo websites are shitty or non-functioning
* Demetri had interesting points in -audience afterwards but they tie to Allen and may be hard to pull in without a lot of context
* Catchy title and description are TBD as usual

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#99
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-10-03 20:30:03 +00:00
Ben Visness 0feeaada1b Update HMS media link 2022-09-20 10:19:49 -05:00
Ben Visness 8121830561 Remove resources from the table of contents 2022-09-19 20:26:43 -05:00
Asaf Gartner 4b9fe628e6 Merge branch 'master' of git.handmade.network:hmn/hmn 2022-09-18 22:25:09 +03:00
Asaf Gartner ca663d874b Allow separate mailer account and From address 2022-09-18 22:23:36 +03:00
Ben Visness bdb08dd14b Fix TOC width issue 2022-09-17 16:26:52 -05:00
Ben Visness b27ddd1e7f A few education improvements 2022-09-17 16:21:58 -05:00
Asaf Gartner c489d0ffa9 Consolidated shared editor-related params 2022-09-15 00:44:27 +03:00
Ben Visness c9ee420dbb Allow authors to hide editor notes 2022-09-12 22:55:51 -05:00
Ben Visness 045a2c2379 Add education toggle to user admin settings 2022-09-10 16:52:02 -05:00
Ben Visness 168b210c5b Restore the library since we're not actually rolling out education yet 2022-09-10 12:54:26 -05:00
Ben Visness 19d79a2a77 Fix nil user in education template 2022-09-10 12:28:32 -05:00
bvisness d2b34cb87d Initial version of education content (#90)
Co-authored-by: Ben Visness <bvisness@gmail.com>
Reviewed-on: hmn/hmn#90
2022-09-10 16:29:57 +00:00
Asaf Gartner 42e1ed95fb Added logs for twitch 2022-08-29 01:18:55 +03:00
Ben Visness 11c4dbe925 Jam starts now go go go 2022-08-15 06:58:24 -05:00
Ben Visness d7b43fdea0 Use the register destination when coming from the login page 2022-08-13 15:07:37 -05:00
Ben Visness 782db18cc3 dammit 2022-08-13 14:49:53 -05:00
Ben Visness 81d8d4559f Fix bug where Discord settings were cleared while disabled 2022-08-13 14:29:40 -05:00
Ben Visness a0cc2f5c66 Update auth flows 2022-08-13 14:15:00 -05:00
Ben Visness 4f1989f663 Add /wishlist command 2022-08-12 22:01:40 -05:00
giggs 9e786e132d New buttons with project colors + small bugfix (#80)
Following the discussion on [#74](hmn/hmn#74), here are changes to the submit buttons so that they match theme/project color.

Border colors are set to match the button background.

I've also included a "bugfix" where the `editor-toolbar-button-background` parameter in the dark theme.css and variables.scss were missing the # sign.

I wasn't sure whether to remove the `form button` values from theme.css and variables.scss and left them, as I'm not sure they're used anywhere now

Reviewed-on: hmn/hmn#80
Co-authored-by: giggs <darkgiggsxx@gmail.com>
Co-committed-by: giggs <darkgiggsxx@gmail.com>
2022-08-13 02:13:13 +00:00
Ben Visness bb48a77b9d Switch to the main Discord invite link, sigh 2022-08-12 18:15:59 -05:00
Asaf Gartner 319b1a05b9 Delete snippets when banning and prevent banned users from logging in 2022-08-09 12:57:12 +03:00
Asaf Gartner 822a489c09 Don't center file links in snippets. 2022-08-09 12:33:52 +03:00
Asaf Gartner b62954ba37 Remove discord link for showcase items when not relevant 2022-08-09 12:27:32 +03:00
Ben Visness 7ea11ebd51 Bam that's the rest of the todo list 2022-08-06 23:43:15 -05:00
Ben Visness 9f88ce1223 something something colors 2022-08-06 23:12:23 -05:00
Ben Visness 4289a1e27a Improvements to snippet edit 2022-08-06 22:32:29 -05:00
Ben Visness 48490d83a9 Some tweaks 2022-08-06 20:21:12 -05:00
Asaf Gartner 97ed892ce3 Added snippets to admin approval queue 2022-08-07 02:03:34 +03:00
Asaf Gartner 4c1daae5e1 Fixed pre-line issue in chrome 2022-08-07 01:04:45 +03:00
Asaf Gartner b995df4533 Added cancel button for snippet edit 2022-08-07 00:51:29 +03:00
Asaf Gartner dc94262bfb Snippets edited on a project page can't be disassociated from that
project on that page.
2022-08-07 00:45:07 +03:00
Asaf Gartner 841264de0f Fix element focus issue on project creation. 2022-08-07 00:40:05 +03:00
Asaf Gartner d2f44f8e5f No jam snippets if no jam projects! 2022-08-06 05:19:49 +03:00
Asaf Gartner a9b0606b79 Use new snippet-project association for jam index showcase 2022-08-06 00:48:56 +03:00
Asaf Gartner 89b1e48e69 Code review 2022-08-06 00:42:08 +03:00
Asaf Gartner 87a146dfa8 Fetch jam snippets by project id 2022-08-06 00:42:08 +03:00
Asaf Gartner efc7d76cb7 Snippet creation and editing 2022-08-06 00:41:37 +03:00
Ben Visness 41c2b6e111 Make slightly more prettier 2022-08-05 00:04:22 -05:00
Ben Visness 1b79f45d71 Make the feed page nicer 2022-08-04 23:22:30 -05:00
Ben Visness 92b175c84d Make good pretty jam wow much good 2022-08-04 21:00:15 -05:00
Ben Visness 62972ae35a Merge remote-tracking branch 'origin/master' into jam-2022 2022-08-04 18:37:51 -05:00
Ben Visness 09652c4146 Re-apply the avatar change
It was only made to CSS and we overwrote it...
2022-08-03 18:59:48 -05:00
Ben Visness 081186c8f0 Add automatic scrolling behavior to jam carousel 2022-08-02 15:14:29 -05:00
Ben Visness ba667f717e Fix overflow issues with new jam stuff 2022-08-02 15:03:48 -05:00
Ben Visness e84754eda0 Add last year's projects to the jam page 2022-08-02 14:56:47 -05:00
Ben Visness 6982503393 Fix fishbowl images 2022-08-01 22:09:23 -05:00
Ben Visness d164a58ba0 Fix issues with asset upload
It didn't work when creating a new project or editing personal projects,
due to routing issues. I also took this opportunity to make the script
support multiple form submit buttons, since in some cases we will have a
submit button on each tab, and I figured they all should respect the
fact that you have an upload in progress.
2022-08-01 21:59:42 -05:00
mark.dev a295d0ed52 Copy drag/drop from blog edit to project (#6) (#77)
I migrated the relevant parts of `editor.html` and `forums.go` (via `blogs.go`) into `project_edit.html` and `projects.go`.

Let me know if you would prefer pulling the shared javascript into a shared file. Only some variable names were changed.

I did not test the case where the upload fails.

Co-authored-by: mark.dev <mark@mark.dev>
Reviewed-on: hmn/hmn#77
Co-authored-by: mark.dev <mark.dev@noreply.localhost>
Co-committed-by: mark.dev <mark.dev@noreply.localhost>
2022-08-02 02:01:55 +00:00
Ben Visness 1806da0389 Polish up the latest fishbowl 2022-08-01 20:29:56 -05:00
ilidemi 25e13df04d Add code reuse fishbowl (#78)
Only needs someone with creative juices to write a description and good to go!

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#78
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-08-01 04:52:34 +00:00
Ben Visness c36ae9d91b Merge remote-tracking branch 'origin/live' 2022-07-29 11:09:23 -05:00
giggs 85c8c92a0c Non square avatars no more squeeshed (#76)
Avatars don't get squeeshed anymore

[#15](hmn/hmn#15)

Please ignore the commit history, still learning git

Reviewed-on: hmn/hmn#76
Co-authored-by: giggs <darkgiggsxx@gmail.com>
Co-committed-by: giggs <darkgiggsxx@gmail.com>
2022-07-29 16:05:42 +00:00
Ben Visness 1f731a17c5 time to get physical
https://www.youtube.com/watch?v=3S5ukw4YOSg
2022-07-26 13:34:23 -05:00
Ben Visness 608235ee29 ok that sentence was in fact bad 2022-07-26 13:28:54 -05:00
Ben Visness f8aa839353 Update conference page design / copy 2022-07-26 11:34:05 -05:00
AllanRegush cc731d77a6 Add Conferences Page (#75)
This PR implements the conferences page.

![image](/attachments/fe7b8df7-0833-4b5b-9f61-a9558b70a98f)

![image](/attachments/10f380d6-81ed-4850-87c4-70a84d31e26b)

closes #69

Co-authored-by: Allan Regush <17693494+AllanRegush@users.noreply.github.com>
Reviewed-on: hmn/hmn#75
Co-authored-by: AllanRegush <allan@allanregush.com>
Co-committed-by: AllanRegush <allan@allanregush.com>
2022-07-26 15:07:57 +00:00
giggs 12d2fab1b8 New project link changed to a bigger button (#73)
Changed the New project link in user profile into a bigger button

![preview](https://i.imgur.com/JHb9hyK.png)

Reviewed-on: hmn/hmn#73
Co-authored-by: giggs <darkgiggsxx@gmail.com>
Co-committed-by: giggs <darkgiggsxx@gmail.com>
2022-07-26 15:03:35 +00:00
AllanRegush 4b3e38ee02 Set meta tag theme color to project's theme color (#71)
This commit sets the discord/link embed theme to match handmade brand

closes #66

Co-authored-by: Allan Regush <17693494+AllanRegush@users.noreply.github.com>
Reviewed-on: hmn/hmn#71
Co-authored-by: AllanRegush <allan@allanregush.com>
Co-committed-by: AllanRegush <allan@allanregush.com>
2022-07-25 20:16:04 +00:00
Ben Visness d3f5057d41 Edit scripts too, oops 2022-07-22 20:56:16 -05:00
Ben Visness 726cd0fd43 Move main.go to the root so we can do `go run .` 2022-07-22 20:52:06 -05:00
ilidemi 7ba8df3942 Add fishbowl tools (#64)
Reducing the bus factor.

Top-level directory is likely not the best place for those, open to suggestions.

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#64
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-07-16 09:02:29 -05:00
Asaf Gartner d01731f4cd Fixed showcase issue
Cleaned up bad unicode and control characters from snippet description
2022-07-14 03:44:19 +03:00
Ben Visness faa582f6da Remove fishbowl backlog message 2022-07-06 21:47:17 -05:00
ilidemi 971123a519 Add internet-os fishbowl (#63)
#33 progress: 10/10 🎉

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#63
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-07-07 02:43:51 +00:00
ilidemi 72c9fa45fc Add metaprogramming fishbowl (#61)
#33 progress: 9/10

Pulled a couple of conversations from the audience

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#61
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-29 19:29:35 +00:00
ilidemi 3a39e81b67 Add lisp jam fishbowl (#60)
#33 progress: 8/10

Patched in nakst's account and references

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#60
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-27 12:38:21 +00:00
Asaf Gartner 316aba12b6 Ugly jam feed. Needs CSS work. 2022-06-25 16:24:04 +03:00
bvisness e9d4300100 Rework requests and middleware (#57)
o boy

Resolves #10 (hopefully!)

Co-authored-by: Ben Visness <bvisness@gmail.com>
Reviewed-on: hmn/hmn#57
2022-06-24 21:38:11 +00:00
ilidemi 32db9b1843 Add parallel programming fishbowl (#58)
#33 progress: 7/10

Oh boy, this one has a good amount of links
Also updated bumbo's discord id in skimmability fishbowl

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#58
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-24 21:31:31 +00:00
ilidemi ca555d8027 Add skimming fishbowl (#51)
#33 progress: 6/10

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#51
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-23 04:28:43 +00:00
ilidemi aa6ba1066f Add config fishbowl (#50)
#33 progress: 5/10, halfway through!

Also added/modified links from flexible-software fishbowl to the config one.

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#50
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-20 04:30:31 +00:00
Asaf Gartner 64f94bddbb Use correct start date for WRJ22 2022-06-20 01:39:24 +03:00
Asaf Gartner fee5331c22 Merge branch 'master' of git.handmade.network:hmn/hmn into jam-2022 2022-06-20 01:37:29 +03:00
Asaf Gartner 7dbd64f62a Merge branch 'jam-2022' of git.handmade.network:hmn/hmn into jam-2022 2022-06-20 01:37:16 +03:00
Asaf Gartner 9d1d249ec0 Added jam/project association. 2022-06-20 01:26:33 +03:00
Ben Visness dc33aade22 Add favicons to jam pages 2022-06-18 13:09:45 -05:00
Ben Visness 990fb5c778 Tweak jam wording 2022-06-18 12:39:56 -05:00
Ben Visness e871542725 Add jam banner on home page 2022-06-18 10:30:30 -05:00
Ben Visness f36df1f697 Add jam index for 2022
Start jam index for 2022

Tweak jam copy

Update OpenGraph content
2022-06-18 10:01:14 -05:00
ilidemi fe3b1d29db Add simplicity-performance fishbowl (#49)
#33 progress: 4/10

Replaced links to #fishbowl-audience comments with comments themselves

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#49
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-18 13:39:08 +00:00
Ben Visness 359354f2aa Start jam index for 2022 2022-06-17 17:30:18 -05:00
Asaf Gartner 141c279335 Merge branch 'master' of git.handmade.network:hmn/hmn 2022-06-16 00:34:48 +03:00
Asaf Gartner b165bf7c23 Added panic recovery to all of our background jobs
Fixes issue #32
2022-06-16 00:33:57 +03:00
ilidemi 86bcde4d49 Add teaching-software fishbowl (#45)
#33 progress: 3/10

Significant changes:
Moved pre-intro discussion after intros, cleaned up what I saw as noise
Pointed bumbo to his current discord id - if a different one is linked to the website, lmk

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#45
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-15 19:39:41 +00:00
Asaf Gartner 870a073e22 Added proper verification for forum urls
Fixes issue #12
2022-06-14 22:52:50 +03:00
Asaf Gartner 86a7128f25 Only show blog content preview in blog index when there are few posts
Partially resolves issue #30
2022-06-14 20:15:16 +03:00
Asaf Gartner 2012328436 Use hmndata helpers for project timeline on project homepage
Resolves issue #37
2022-06-14 19:14:38 +03:00
Asaf Gartner cb71abfdb3 Added createuser and usersetadmin commands
Resolves issue #38
2022-06-14 19:07:11 +03:00
Asaf Gartner 31f7bf5350 Treat fishbowl files like public files. Skip expensive middleware.
We don't really need to validate the project subdomain here.
Fetching the common data eats up a db connection, and we don't gain
anything from it.
2022-06-14 04:06:44 +03:00
ilidemi 58c09126a4 Add Flexible Software fishbowl (#43)
#33 progress: 2/10

Co-authored-by: Ilia Demianenko <ilia.demianenko@gmail.com>
Reviewed-on: hmn/hmn#43
Co-authored-by: ilidemi <belk94@gmail.com>
Co-committed-by: ilidemi <belk94@gmail.com>
2022-06-13 13:49:22 +00:00
Ben Visness dd3b889aaf Remove `pattern` from login input (#40)
it was just wrong! not helpful to anyone
2022-06-12 09:03:52 -05:00
Ben Visness 6fbaaf6992 Enable systemd units as part of server setup 2022-06-12 08:40:07 -05:00
Ben Visness 7dd4a1af31 Don't do clever hue-rotating trick with waterline image 2022-06-12 08:39:44 -05:00
bvisness d1e63f745b Add Fishbowl archive (#41)
Refs #33

Co-authored-by: Ben Visness <bvisness@gmail.com>
Co-authored-by: ilidemi <belk94@gmail.com>
Reviewed-on: hmn/hmn#41
2022-06-12 12:45:56 +00:00
Ben Visness 1cfb9e4033 Fix mailto on crash page 2022-06-01 20:49:19 -05:00
Ben Visness 13f5b2ee63 Tweak landing page wording 2022-06-01 20:40:16 -05:00
Ben Visness 6e0010e957 Fix querying possibly-nil scalars
Our db code for querying scalars didn't do anything to account for
pointer destinations (which you need if querying a field that may be
nil!)
2022-06-01 20:38:24 -05:00
Asaf Gartner ac2d00aca7 Logging bad discord resources 2022-05-30 21:56:09 +03:00
Asaf Gartner 2bb14c1794 Replaced panic with error 2022-05-30 21:52:13 +03:00
Asaf Gartner fe545ff0f3 Debugging twitch 2022-05-30 21:19:54 +03:00
Asaf Gartner 8c47590b99 Debugging twitch 2022-05-30 19:08:09 +03:00
Asaf Gartner 4c296c9ddd Soft failure for failing to delete discord message. 2022-05-30 18:55:10 +03:00
Asaf Gartner 9fcc2321ca Hopefully fixed desync with twitch 2022-05-30 18:49:30 +03:00
Asaf Gartner ca614a781b Updated Go version in serversetup.sh 2022-05-30 18:48:45 +03:00
Asaf Gartner 02d51a8bfe Merge branch 'streams_update' 2022-05-30 17:33:52 +03:00
Asaf Gartner 0d0773fd0e Reverse streamer sort and replaced green circle with red 2022-05-27 16:34:34 +03:00
Asaf Gartner 09c4561428 Slightly improved discord message formatting. 2022-05-27 11:55:57 +03:00
Asaf Gartner 8495982d3f Added persistent vars and improved stream tracking on discord. 2022-05-27 11:37:43 +03:00
Ben Visness 68a00c91db Rename the email override field for clarity 2022-05-25 17:39:57 -05:00
bvisness 2f19e6e1b8 Add note about Go version to the readme 2022-05-25 22:33:28 +00:00
Ben Visness 475716322f Fix up missing avatars 2022-05-21 16:44:39 -05:00
Ben Visness 6dd11aa970 Delete resetdb.sh 2022-05-16 10:26:56 -05:00
Ben Visness 491ae57590 Tweak Postgres help message on failed seed 2022-05-14 23:06:48 -05:00
Ben Visness c1fa6cae13 Integrate Nick's local S3 server
Works like a charm!

Small tweak for clarity
2022-05-14 00:48:19 -05:00
bvisness 4187a3b6ca Merge pull request 'handmade dummy S3 local dev server' (#4) from nick12/hmn:hmns3 into localdev-2022
Reviewed-on: hmn/hmn#4
2022-05-14 00:12:44 +00:00
Ben Visness 3aa16c6d12 Add owners to seeded projects 2022-05-11 23:39:43 -05:00
Ben Visness 196eda8185 Add README 2022-05-11 23:08:01 -05:00
Ben Visness a2ec57cf47 Seed projects 2022-05-11 22:24:05 -05:00
Ben Visness e4bb741a15 Automatically create the HMN user if necessary
This pretty much certainly won't work in real environments. If it does,
your db config is not secure :)
2022-05-11 19:50:51 -05:00
Ben Visness f4601198c9 Seed news posts 2022-05-07 14:45:21 -05:00
Ben Visness 3c4238994a Seed example forum threads 2022-05-07 14:31:37 -05:00
Ben Visness 3a93aa93e9 Seed users (and rework a lot of user access to use new helpers) 2022-05-07 13:58:00 -05:00
Ben Visness b46f5d8637 Add bare minimum seed 2022-05-07 11:37:15 -05:00
Ben Visness 1020039ea2 Fix up tests 2022-05-07 09:43:41 -05:00
Ben Visness 0e56f56372 Rename all the db tables 2022-05-07 08:11:05 -05:00
Ben Visness a147cfa325 Rework DB API
This takes advantage of generics, and generally clears up a lot of
inconsistencies and quality-of-life issues.

Start of db rework: clean up, start generics, improve tests

Write some nice aspirational package docs

Rework and document the db API

Tests still pass, at least...now for everything else

Update all callsites of db functions

Finish converting all callsites

Not too bad actually! Centralizing access into the helpers makes a big
difference.

wtf it works
2022-05-06 16:56:13 -05:00
unknown 69a44d1734 handmade dummy S3 local dev server 2022-05-01 02:41:58 -03:00
Ben Visness 6004149417 Fix zero-items bug with getPageInfo 2022-04-30 21:18:21 -05:00
Ben Visness f51b7e23da Shout out the community in the manifesto 2022-04-30 19:19:36 -05:00
Ben Visness f7d92a63b4 Update opengraph description for the manifesto 2022-04-30 19:08:25 -05:00
Ben Visness ad1bc875cc Rewrite the manifesto 2022-04-30 15:59:05 -05:00
1024 changed files with 173501 additions and 25026 deletions

10
.gitignore vendored
View File

@ -13,3 +13,13 @@ hmn.conf
adminmailer/config.go
adminmailer/adminmailer
local/backups
/tmp
*.exe
.DS_Store
__debug_bin*
# vim session saves
Session.vim
# tags files
tags

81
README.md Normal file
View File

@ -0,0 +1,81 @@
# Handmade Network
This is the codebase for the Handmade Network website, located online at https://handmade.network. The website is the home for all Handmade projects, the forums, the podcast, and other various initiatives.
The site is written in Go, and uses the standard library HTTP server with custom utilities for routing and middleware. It uses Postgres for its database, making heavy use of the excellent [pgx](https://github.com/jackc/pgx) library along with some custom wrappers. See the documentation in the `db` package for more details.
We want the website to be a great example of Handmade software on the web. We encourage you to read through the source, run it yourself, and learn from how we work. If you have questions about the code, or you're interested in contributing directly, reach out to us in #network-meta on the [Handmade Network Discord](https://discord.gg/hmn)!
## Prerequisites
You will need the following software installed:
- Go 1.21 or newer: https://go.dev/
You can download Go directly from the website, or install it through major package managers. If you already have Go installed, but are unsure of the version, you can check by running `go version`.
- Postgres: https://www.postgresql.org/
Any Postgres installation should work fine, although less common distributions may not work as nicely with our scripts out of the box. On Mac, [Postgres.app](https://postgresapp.com/) is recommended.
## First-time setup
- **Configure the site.** Copy `src/config/config.go.example` to `src/config/config.go`:
```
# On Windows
copy src\config\config.go.example src\config\config.go
# On Mac and Linux
cp src/config/config.go.example src/config/config.go
```
Depending on your installation of Postgres, you may need to modify the hostname and port in the Postgres section of the config.
- **Set up the database.** Run `go run . db seed` to initialize the database and fill it with sample data.
- **Update your hosts file.** The website uses subdomains for official projects, so the site cannot simply be run off `localhost`. Add the following
line to your hosts file:
```
127.0.0.1 handmade.local hero.handmade.local 4coder.handmade.local
```
You may need to edit the hosts file again in the future if you add more official projects.
On Windows, the hosts file is located at `C:\Windows\System32\Drivers\etc\hosts`. On Mac and Linux, the hosts file should be located at `/etc/hosts`. It can be edited using any plain text editor, but you will need superuser permissions.
## Running the site
Running the site is easy:
```
go run .
```
You should now be able to visit http://handmade.local:9001 to see the website!
There are also several other commands built into the website executable. You can see documentation for each of them by running `go run . help` or adding the `-h` flag to any command.
## Running tests
Also easy:
```
go test ./...
```
Note that we have a special coverage requirement for the `hmnurl` package. We use the tests in this package to ensure that our URL builder functions never go out of sync with the regexes used for routing. As a result, we mandate 100% coverage for all `Build` functions in `hmnurl`.
## Starter data
The `db seed` command pre-populates the site with realistic data. It also includes several user accounts that you may log into to test various situations:
| Username | Password |
| -------- | -------- |
| `admin` | `password` |
| `alice` | `password` |
| `bob` | `password` |
| `charlie` | `password` |
The `admin` user is a superuser on the site and will have access to all features, as well as the special admin UI for performing site maintenance and moderation. The other users are all normal users.

View File

@ -4,6 +4,7 @@ const RecvAddress = "admin@example.com"
const RecvName = "Admin"
const FromName = "From Name"
const FromAddress = "from@address.com"
const FromAddressPassword = "password"
const ServerUsername = "username"
const ServerPassword = "password"
const ServerAddress = "server.address"
const ServerPort = 587

View File

@ -46,7 +46,7 @@ func sendMail(toAddress, toName, subject, contentHtml string) error {
)
return smtp.SendMail(
fmt.Sprintf("%s:%d", ServerAddress, ServerPort),
smtp.PlainAuth("", FromAddress, FromAddressPassword, ServerAddress),
smtp.PlainAuth("", ServerUsername, ServerPassword, ServerAddress),
FromAddress,
[]string{toAddress},
contents,

1
fishbowl-tools/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
!.vscode

View File

@ -0,0 +1,10 @@
{
"Resource Link": {
"prefix": [
"hmn-link"
],
"body": [
"<a class=\"inserted-after\" href=\"$1\" target=\"_blank\">$TM_SELECTED_TEXT</a>"
]
}
}

65
fishbowl-tools/steps.md Normal file
View File

@ -0,0 +1,65 @@
- [ ] Export with [DiscordChatExporter](https://github.com/Tyrrrz/DiscordChatExporter) CLI 2.39.1
```
DiscordChatExporter.Cli.exe export -c [thread-id] -t [token] -o [fishbowl].html --media
```
- [ ] Rename `[fishbowl].html_Files` to `files`, replace links in html
- [ ] Add target="_blank" to links
```
(a href="[^"]+")>
$1 target="_blank">
```
- [ ] Add JQuery to `<head>`
```html
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.1/jquery-ui.js"></script>
<script>
$( function() {
$( ".chatlog" ).sortable();
} );
</script>
```
- [ ] Drag/delete noise/edit in the browser
- [ ] Save as `[fishbowl]-dragged.html` (devtools -> `<html>` -> copy outerHTML)
- [ ] Remove JQuery, sortable classes
```
ui-sortable
ui-sortable-handle
```
- [ ] Check `#fishbowl-audience` for highlights
- [ ] Fix audience avatar paths if anything copied
- [ ] Fix bad pictures (composite emojis 404)
- [ ] Fix links with extra braces at the end
```
href="[^"]+\)"
```
- [ ] Fill in resource links with vscode snippet (select phrase, Ctrl+Shift+P -> Insert Snippet -> hmn-link, paste the url)
- [ ] Download twemojies
```
go run twemoji.go [fishbowl]-dragged.html files [fishbowl]-twemojied.html
```
- [ ] Fix timestamps, validate they look correct
```
go run timestamps.go [fishbowl]-twemojied.html [fishbowl]-timestamped.html
```
- [ ] Create a branch off latest `hmn` master
- [ ] Create fishbowl folder under `hmn/src/templates/src/fishbowls/`
- [ ] Copy timestamped html and files, rename html
- [ ] Remove everything from html but chatlog
- [ ] Remove js, css and ggsans from files
- [ ] Add content path to `fishbowl.go`
- [ ] Test locally
- [ ] Submit a pull request

View File

@ -0,0 +1,45 @@
package main
import (
"fmt"
"os"
"regexp"
"strconv"
"time"
)
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: go run timestamps.go <fishbowl>.html <fishbowl>-timestamped.html")
os.Exit(1)
}
htmlPath := os.Args[1]
htmlOutPath := os.Args[2]
htmlBytes, err := os.ReadFile(htmlPath)
if err != nil {
panic(err)
}
html := string(htmlBytes)
regex := regexp.MustCompile(
`(<span class="?chatlog__timestamp"?><a href=[^>]+>)(\d+)/(\d+)/(\d+)( [^<]+</a></span>)`,
)
htmlOut := regex.ReplaceAllStringFunc(html, func(s string) string {
match := regex.FindStringSubmatch(s)
month, err := strconv.ParseInt(match[2], 10, 64)
if err != nil {
panic(err)
}
monthStr := time.Month(month).String()
return fmt.Sprintf("%s%s %s, %s%s", match[1], monthStr, match[3], match[4], match[5])
})
err = os.WriteFile(htmlOutPath, []byte(htmlOut), 0666)
if err != nil {
panic(err)
}
}

77
fishbowl-tools/twemoji.go Normal file
View File

@ -0,0 +1,77 @@
package main
import (
"fmt"
"io"
"net/http"
"os"
"path"
"strings"
)
func main() {
if len(os.Args) != 4 {
fmt.Println("Usage: go run twemoji.go [fishbowl].html files [fishbowl]-twemojied.html")
os.Exit(1)
}
htmlPath := os.Args[1]
filesDir := os.Args[2]
htmlOutPath := os.Args[3]
htmlBytes, err := os.ReadFile(htmlPath)
if err != nil {
panic(err)
}
html := string(htmlBytes)
for {
linkStart := strings.Index(html, "https://twemoji.maxcdn.com/")
if linkStart == -1 {
break
}
linkEnd := strings.Index(html[linkStart:], "\"") + linkStart
link := html[linkStart:linkEnd]
emojiFilenameStart := strings.LastIndex(link, "/") + 1
emojiFilename := "twemoji_" + link[emojiFilenameStart:]
emojiPath := path.Join(filesDir, emojiFilename)
emojiResponse, err := http.Get(link)
if err != nil {
panic(err)
}
defer emojiResponse.Body.Close()
if emojiResponse.StatusCode > 299 {
panic("Non-200 status code: " + fmt.Sprint(emojiResponse.StatusCode))
}
emojiFile, err := os.Create(emojiPath)
if err != nil {
panic(err)
}
defer emojiFile.Close()
_, err = io.Copy(emojiFile, emojiResponse.Body)
if err != nil {
panic(err)
}
html = strings.ReplaceAll(html, link, emojiPath)
fmt.Println(emojiFilename)
}
html = strings.ReplaceAll(
html,
"<div class=\"chatlog\">",
"<div class=\"chatlog\">\n<!-- Emojis by Twitter's Twemoji https://twemoji.twitter.com/ -->",
)
err = os.WriteFile(htmlOutPath, []byte(html), 0666)
if err != nil {
panic(err)
}
}

59
go.mod
View File

@ -1,10 +1,9 @@
module git.handmade.network/hmn/hmn
go 1.16
go 1.21
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/HandmadeNetwork/golorem v0.0.0-20220507185207-414965a3a817
github.com/Masterminds/sprig v2.22.0+incompatible
github.com/alecthomas/chroma v0.9.2
github.com/aws/aws-sdk-go-v2 v1.8.1
@ -12,27 +11,59 @@ require (
github.com/aws/aws-sdk-go-v2/credentials v1.3.3
github.com/aws/aws-sdk-go-v2/service/s3 v1.13.0
github.com/aws/smithy-go v1.7.0
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f
github.com/frustra/bbcode v0.0.0-20201127003707-6ef347fbe1c8
github.com/go-stack/stack v1.8.0
github.com/google/uuid v1.2.0
github.com/gorilla/websocket v1.4.2
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jackc/pgconn v1.8.0
github.com/jackc/pgtype v1.6.2
github.com/jackc/pgx/v4 v4.10.1
github.com/jackc/pgx-zerolog v0.0.0-20220923130014-7856b90a65ae
github.com/jackc/pgx/v5 v5.2.0
github.com/jpillora/backoff v1.0.0
github.com/mitchellh/copystructure v1.1.1 // indirect
github.com/rs/zerolog v1.21.0
github.com/rs/zerolog v1.28.0
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
github.com/stretchr/testify v1.8.1
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300
github.com/teacat/noire v1.1.0
github.com/wellington/go-libsass v0.9.2
github.com/yuin/goldmark v1.4.1
github.com/yuin/goldmark v1.4.13
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/crypto v0.6.0
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
mvdan.cc/xurls/v2 v2.4.0
)
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver v1.5.0 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.6.2 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/evanw/esbuild v0.21.4
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.1.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mitchellh/copystructure v1.1.1 // indirect
github.com/mitchellh/reflectwalk v1.0.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/teambition/rrule-go v1.7.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
replace (

206
go.sum
View File

@ -15,8 +15,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/HandmadeNetwork/bbcode v0.0.0-20210623031351-ec0e2e2e39d9 h1:5WhEr56CD1uWDPcDIIa+UtNPPlJCoNJ3u38Rk+4XIks=
github.com/HandmadeNetwork/bbcode v0.0.0-20210623031351-ec0e2e2e39d9/go.mod h1:vMiNHD8absjmnO60Do5KCaJBwdbaiI/AzhMmSipMme4=
github.com/HandmadeNetwork/goldmark v1.4.1-0.20210707024600-f7e596e26b5e h1:z0GlF2OMmy852mrcMVpjZIzEHYCbUweS8RaWRCPfL1g=
github.com/HandmadeNetwork/goldmark v1.4.1-0.20210707024600-f7e596e26b5e/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/HandmadeNetwork/golorem v0.0.0-20220507185207-414965a3a817 h1:cBqVP/sLiK7DPay7Aac1PRUwu3fCVyL5Wc+xLXzqwkE=
github.com/HandmadeNetwork/golorem v0.0.0-20220507185207-414965a3a817/go.mod h1:doKbGBIdiM1nkEfvAeP5hvUmERah9H6StTVfCverqdE=
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
@ -70,16 +70,13 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -91,6 +88,10 @@ github.com/dlclark/regexp2 v1.1.6/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55k
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f h1:feGUUxxvOtWVOhTko8Cbmp33a+tU0IMZxMEmnkoAISQ=
github.com/emersion/go-ical v0.0.0-20220601085725-0864dccc089f/go.mod h1:2MKFUgfNMULRxqZkadG1Vh44we3y5gJAtTBlVsx1BKQ=
github.com/evanw/esbuild v0.21.4 h1:pe4SEQMoR1maEjhgWPEPWmUy11Jp6nidxd1mOvMrFFU=
github.com/evanw/esbuild v0.21.4/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -100,8 +101,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -117,8 +117,9 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@ -159,59 +160,16 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA=
github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE=
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk=
github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI=
github.com/jackc/pgconn v1.8.0 h1:FmjZ0rOyXTr1wfWs45i4a9vjnjWUAGpMuQLD9OSs+lw=
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA=
github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE=
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A=
github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA=
github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg=
github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM=
github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8=
github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA=
github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg=
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E=
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0=
github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po=
github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ=
github.com/jackc/pgtype v1.6.2 h1:b3pDeuhbbzBYcg5kwNmNDun4pFUD/0AAr1kLXZLeNt8=
github.com/jackc/pgtype v1.6.2/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJsrdig=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA=
github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o=
github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg=
github.com/jackc/pgx/v4 v4.10.1 h1:/6Q3ye4myIj6AaplUm+eRcz4OhK9HAvFf4ePsG40LJY=
github.com/jackc/pgx/v4 v4.10.1/go.mod h1:QlrWebbs3kqEZPHCTGyxecvzG6tvIsYu+A5b1raylkA=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3 h1:JnPg/5Q9xVJGfjsO5CPUOjnJps1JaRUm8I9FXVCFK94=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
github.com/jackc/pgx-zerolog v0.0.0-20220923130014-7856b90a65ae h1:s/r/bBI1EUCZvGtoJ/Ow6WPUYe08V9VpQY3fv6eq99s=
github.com/jackc/pgx-zerolog v0.0.0-20220923130014-7856b90a65ae/go.mod h1:CRUuPsmIajLt3dZIlJ5+O8IDSib6y8yrst8DkCthTa4=
github.com/jackc/pgx/v5 v5.2.0 h1:NdPpngX0Y6z6XDFKqmFQaE+bCtkqzvQIOt1wvBlAqs8=
github.com/jackc/pgx/v5 v5.2.0/go.mod h1:Ptn7zmohNsWEsdxRawMzk3gaKma2obW+NWTnKa0S4nk=
github.com/jackc/puddle/v2 v2.1.2 h1:0f7vaaXINONKTsxYDn4otOAiJanX/BMeAtY//BXqzlg=
github.com/jackc/puddle/v2 v2.1.2/go.mod h1:2lpufsF5mRHO6SuZkm0fNYxM6SWHfvyFj62KwNzgels=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@ -224,32 +182,25 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@ -270,9 +221,9 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -288,24 +239,18 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
github.com/rs/zerolog v1.21.0 h1:Q3vdXlfLNT+OftyBHsU0Y445MD+8m8axjKgf2si0QcM=
github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY=
github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -321,57 +266,52 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300 h1:XQdibLKagjdevRB6vAjVY4qbSr8rQ610YzTkWcxzxSI=
github.com/tcolgate/mp3 v0.0.0-20170426193717-e79c5a46d300/go.mod h1:FNa/dfN95vAYCNFrIKRrlRo+MBLbwmR9Asa5f2ljmBI=
github.com/teacat/noire v1.1.0 h1:5IgJ1H8jodiSSYnrVadV2JjbAnEgCCjYUQxSUuaQ7Sg=
github.com/teacat/noire v1.1.0/go.mod h1:cetGlnqr+9yKJcFgRgYXOWJY66XIrrjUsGBwNlNNtAk=
github.com/teambition/rrule-go v1.7.2 h1:goEajFWYydfCgavn2m/3w5U+1b3PGqPUHx/fFSVfTy0=
github.com/teambition/rrule-go v1.7.2/go.mod h1:mBJ1Ht5uboJ6jexKdNUJg2NcwP8uUMNvStWXlJD3MvU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/wellington/go-libsass v0.9.2 h1:6Ims04UDdBs6/CGSVK5JC8FNikR5ssrsMMKE/uaO5Q8=
github.com/wellington/go-libsass v0.9.2/go.mod h1:mxgxgam0N0E+NAUMHLcu20Ccfc3mVpDkyrLDayqfiTs=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.6/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01 h1:0SJnXjE4jDClMW6grE0xpNhwpqbPwkBTn8zpVw5C0SI=
github.com/yuin/goldmark-highlighting v0.0.0-20210516132338-9216f9c5aa01/go.mod h1:TwKQPa5XkCCRC2GRZ5wtfNUTQ2+9/i19mGRijFeJ4BE=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY=
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs=
@ -387,7 +327,6 @@ golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -402,10 +341,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -414,7 +349,9 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -423,31 +360,27 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -459,27 +392,16 @@ golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@ -503,24 +425,26 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
mvdan.cc/xurls/v2 v2.4.0 h1:tzxjVAj+wSBmDcF6zBB7/myTy3gX9xvi8Tyr28AuQgc=
mvdan.cc/xurls/v2 v2.4.0/go.mod h1:+GEjq9uNjqs8LQfM9nVnM8rff0OQ5Iash5rzX+N1CSg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

20
local/download_database.py Executable file
View File

@ -0,0 +1,20 @@
#!/usr/bin/env python3
import boto3
# You must already have configured your "AWS" (DigitalOcean) credentials via the AWS CLI.
s3 = boto3.resource("s3")
bucket = s3.Bucket("hmn-backup")
for obj in bucket.objects.filter(Prefix="db"):
print(obj.key)
print()
print("Above is a list of all the available database backups.")
print("Enter the name of the one you would like to download (e.g. \"hmn_pg_dump_live_2023-09-24\"):")
filename = input()
s3 = boto3.client("s3")
s3.download_file("hmn-backup", f"db/{filename}", f"local/backups/{filename}")
print(f"Downloaded {filename} to local/backups.")

View File

@ -1,15 +0,0 @@
#!/bin/bash
set -euo pipefail
s3cmd ls s3://hmn-backup/db/
echo ""
echo "Above is a list of all the available database backups."
echo "Enter the name of the one you would like to download (e.g. \"hmn_pg_dump_live_2021-09-01\"):"
read filename
s3cmd get --force s3://hmn-backup/db/$filename ./local/backups/$filename
echo ""
echo "Downloaded $filename to local/backups."

1
local/requirements.txt Normal file
View File

@ -0,0 +1 @@
boto3

View File

@ -1,23 +0,0 @@
#!/bin/bash
set -euxo pipefail
# This script is for use in local development only. It wipes the existing db,
# creates a new empty one, runs the initial migration to create the schema,
# and then imports actual db content on top of that.
# TODO(opensource): We should adapt Asaf's seedfile command and then delete this.
THIS_PATH=$(pwd)
BETA_PATH='/mnt/c/Users/bvisn/Developer/handmade/handmade-beta'
# BETA_PATH='/Users/benvisness/Developer/handmade/handmade-beta'
pushd $BETA_PATH
docker-compose down -v
docker-compose up -d postgres s3
sleep 3
docker-compose exec postgres bash -c "psql -U postgres -c \"CREATE ROLE hmn CREATEDB LOGIN PASSWORD 'password';\""
popd
go run src/main.go seedfile local/backups/hmn_pg_dump_live_2021-11-14
# go run src/main.go seedfile local/backups/hmn_pg_dump_live_2021-10-23

15
main.go Normal file
View File

@ -0,0 +1,15 @@
package main
import (
_ "git.handmade.network/hmn/hmn/src/admintools"
_ "git.handmade.network/hmn/hmn/src/assets"
_ "git.handmade.network/hmn/hmn/src/buildcss/cmd"
_ "git.handmade.network/hmn/hmn/src/discord/cmd"
_ "git.handmade.network/hmn/hmn/src/initimage"
_ "git.handmade.network/hmn/hmn/src/migration"
"git.handmade.network/hmn/hmn/src/website"
)
func main() {
website.WebsiteCommand.Execute()
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
public/banner-email.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
public/cities/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

12
public/cities/banner.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 28 KiB

24
public/discord-login.svg Normal file
View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 256 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.402516,0,0,0.410256,60.3774,109.538)">
<rect x="-150" y="-267" width="636" height="117" style="fill:rgb(88,101,242);"/>
</g>
<g transform="matrix(0.266745,0,0,0.266745,60.1574,11.1482)">
<g id="图层_2">
<g id="Discord_Logos">
<g id="Discord_Logo_-_Large_-_White">
<path d="M170.85,20.2L198.15,20.2C204.73,20.2 210.297,21.227 214.85,23.28C219.042,25.042 222.602,28.034 225.06,31.86C227.361,35.639 228.54,39.996 228.46,44.42C228.511,48.864 227.285,53.231 224.93,57C222.303,60.982 218.545,64.088 214.14,65.92C209.313,68.12 203.33,69.217 196.19,69.21L170.85,69.21L170.85,20.2ZM195.91,56.74C200.343,56.74 203.75,55.633 206.13,53.42C208.57,51.054 209.873,47.745 209.7,44.35C209.85,41.202 208.699,38.127 206.52,35.85C204.387,33.73 201.177,32.667 196.89,32.66L188.35,32.66L188.35,56.74L195.91,56.74Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M269.34,69.13C265.738,68.228 262.293,66.788 259.12,64.86L259.12,53.24C261.89,55.255 265.009,56.74 268.32,57.62C271.942,58.725 275.704,59.301 279.49,59.33C280.797,59.4 282.102,59.174 283.31,58.67C284.17,58.23 284.6,57.67 284.6,57.09C284.619,56.435 284.365,55.801 283.9,55.34C283.101,54.726 282.164,54.317 281.17,54.15L272.77,52.26C267.957,51.14 264.54,49.59 262.52,47.61C260.471,45.543 259.381,42.707 259.52,39.8C259.486,37.194 260.437,34.668 262.18,32.73C264.248,30.543 266.855,28.939 269.74,28.08C273.452,26.913 277.329,26.356 281.22,26.43C284.852,26.396 288.474,26.819 292,27.69C294.848,28.365 297.583,29.449 300.12,30.91L300.12,41.91C297.741,40.53 295.184,39.483 292.52,38.8C289.634,38.026 286.658,37.636 283.67,37.64C279.283,37.64 277.09,38.387 277.09,39.88C277.075,40.559 277.47,41.183 278.09,41.46C279.289,41.97 280.544,42.332 281.83,42.54L288.83,43.8C293.377,44.6 296.767,46 299,48C301.233,50 302.353,52.927 302.36,56.78C302.432,60.898 300.308,64.758 296.79,66.9C293.103,69.373 287.84,70.607 281,70.6C277.067,70.606 273.149,70.112 269.34,69.13Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M318.9,67.66C315.158,65.941 312.003,63.158 309.83,59.66C307.803,56.23 306.764,52.304 306.83,48.32C306.77,44.338 307.864,40.423 309.98,37.05C312.235,33.607 315.447,30.896 319.22,29.25C323.807,27.251 328.778,26.282 333.78,26.41C340.78,26.41 346.59,27.88 351.21,30.82L351.21,43.65C349.452,42.468 347.532,41.549 345.51,40.92C343.246,40.205 340.884,39.851 338.51,39.87C334.17,39.87 330.773,40.663 328.32,42.25C326.06,43.511 324.655,45.905 324.655,48.493C324.655,51.041 326.016,53.403 328.22,54.68C330.6,56.287 334.053,57.09 338.58,57.09C340.916,57.096 343.241,56.759 345.48,56.09C347.522,55.504 349.484,54.668 351.32,53.6L351.32,66C345.91,69.154 339.731,70.754 333.47,70.62C328.451,70.757 323.467,69.744 318.9,67.66Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M368.64,67.66C364.856,65.932 361.645,63.155 359.39,59.66C357.265,56.238 356.161,52.278 356.21,48.25C356.142,44.27 357.248,40.356 359.39,37C361.657,33.594 364.854,30.907 368.6,29.26C377.799,25.528 388.101,25.528 397.3,29.26C401.031,30.894 404.215,33.568 406.47,36.96C408.597,40.328 409.693,44.247 409.62,48.23C409.67,52.254 408.577,56.211 406.47,59.64C404.239,63.138 401.044,65.917 397.27,67.64C388.133,71.558 377.777,71.558 368.64,67.64L368.64,67.66ZM389.91,55.24C391.657,53.436 392.584,50.989 392.47,48.48C392.592,45.994 391.662,43.568 389.91,41.8C388.01,40.058 385.483,39.159 382.91,39.31C380.339,39.175 377.818,40.072 375.91,41.8C374.164,43.571 373.239,45.996 373.36,48.48C373.247,50.987 374.169,53.433 375.91,55.24C377.8,57.004 380.328,57.925 382.91,57.79C385.494,57.94 388.028,57.017 389.91,55.24Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M451.69,29L451.69,44.14C449.6,42.893 447.191,42.285 444.76,42.39C441.03,42.39 438.15,43.53 436.15,45.79C434.15,48.05 433.15,51.56 433.15,56.32L433.15,69.2L416,69.2L416,28.25L432.8,28.25L432.8,41.25C433.733,36.49 435.24,32.98 437.32,30.72C439.36,28.472 442.286,27.228 445.32,27.32C447.56,27.259 449.771,27.842 451.69,29Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M508.67,18.8L508.67,69.2L491.52,69.2L491.52,60C490.227,63.275 487.903,66.041 484.9,67.88C481.585,69.769 477.814,70.71 474,70.6C470.411,70.684 466.878,69.698 463.85,67.77C460.918,65.865 458.581,63.172 457.11,60C455.504,56.499 454.705,52.681 454.77,48.83C454.657,44.837 455.508,40.875 457.25,37.28C458.851,33.988 461.351,31.214 464.46,29.28C467.656,27.344 471.334,26.349 475.07,26.41C483.23,26.41 488.713,29.957 491.52,37.05L491.52,18.8L508.67,18.8ZM489,55C490.766,53.261 491.722,50.857 491.63,48.38C491.705,45.976 490.747,43.652 489,42C484.971,38.719 479.139,38.719 475.11,42C473.368,43.69 472.425,46.045 472.52,48.47C472.431,50.918 473.384,53.292 475.14,55C476.995,56.725 479.47,57.63 482,57.51C484.575,57.652 487.102,56.746 489,55Z" style="fill:white;fill-rule:nonzero;"/>
<path d="M107.7,8.07C99.347,4.246 90.528,1.533 81.47,0C80.23,2.216 79.109,4.496 78.11,6.83C68.461,5.376 58.649,5.376 49,6.83C48.001,4.496 46.879,2.216 45.64,-0C36.576,1.546 27.752,4.265 19.39,8.09C2.79,32.65 -1.71,56.6 0.54,80.21C10.261,87.392 21.143,92.855 32.71,96.36C35.315,92.857 37.62,89.14 39.6,85.25C35.838,83.845 32.208,82.112 28.75,80.07C29.66,79.41 30.55,78.73 31.41,78.07C51.768,87.644 75.372,87.644 95.73,78.07C96.6,78.78 97.49,79.46 98.39,80.07C94.926,82.115 91.288,83.852 87.52,85.26C89.498,89.149 91.803,92.862 94.41,96.36C105.987,92.869 116.877,87.409 126.6,80.22C129.24,52.84 122.09,29.11 107.7,8.07ZM42.45,65.69C36.18,65.69 31,60 31,53C31,46 36,40.26 42.43,40.26C48.86,40.26 54,46 53.89,53C53.78,60 48.84,65.69 42.45,65.69ZM84.69,65.69C78.41,65.69 73.25,60 73.25,53C73.25,46 78.25,40.26 84.69,40.26C91.13,40.26 96.23,46 96.12,53C96.01,60 91.08,65.69 84.69,65.69Z" style="fill:white;fill-rule:nonzero;"/>
<ellipse cx="242.92" cy="24.93" rx="8.55" ry="7.68" style="fill:white;"/>
<path d="M234.36,37.9C239.829,40.199 246.001,40.199 251.47,37.9L251.47,69.42L234.36,69.42L234.36,37.9Z" style="fill:white;fill-rule:nonzero;"/>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
public/education/time.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

626
public/fishbowl-dark.css Normal file
View File

@ -0,0 +1,626 @@
.fishbowl {
background-color: #36393e;
color: #dcddde;
}
.fishbowl a {
color: #00aff4;
text-decoration: none;
}
.fishbowl a:hover {
text-decoration: underline;
}
.fishbowl img {
object-fit: contain;
image-rendering: high-quality;
image-rendering: -webkit-optimize-contrast;
}
.fishbowl .preamble {
display: grid;
grid-template-columns: auto 1fr;
max-width: 100%;
padding: 1rem;
}
.fishbowl .preamble__guild-icon-container {
grid-column: 1;
}
.fishbowl .preamble__guild-icon {
max-width: 88px;
max-height: 88px;
}
.fishbowl .preamble__entries-container {
grid-column: 2;
margin-left: 1rem;
}
.fishbowl .preamble__entry {
margin-bottom: 0.15rem;
color: #ffffff;
font-size: 1.4rem;
}
.fishbowl .preamble__entry--small {
font-size: 1rem;
}
.fishbowl .chatlog {
padding: 1rem 0;
width: 100%;
}
.fishbowl .chatlog__message-group {
margin-bottom: 1rem;
}
.fishbowl .chatlog__message-container {
background-color: transparent;
transition: background-color 1s ease;
}
.fishbowl .chatlog__message-container--highlighted {
background-color: rgba(114, 137, 218, 0.2);
}
.fishbowl .chatlog__message-container--pinned {
background-color: rgba(249, 168, 37, 0.05);
}
.fishbowl .chatlog__message {
display: grid;
grid-template-columns: auto 1fr;
padding: 0.15rem 0;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__message:hover {
background-color: #32353b;
}
.fishbowl .chatlog__message:hover .chatlog__short-timestamp {
display: block;
}
.fishbowl .chatlog__message-aside {
grid-column: 1;
width: 72px;
padding: 0.15rem 0.15rem 0 0.15rem;
text-align: center;
}
.fishbowl .chatlog__reference-symbol, .fishbowl .chatlog__reply-symbol {
height: 10px;
margin: 6px 4px 4px 36px;
border-left: 2px solid #4f545c;
border-top: 2px solid #4f545c;
border-radius: 8px 0 0 0;
}
.fishbowl .chatlog__avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
.fishbowl .chatlog__short-timestamp {
display: none;
color: #a3a6aa;
font-size: 0.7em;
line-height: 1.4em;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__message-primary {
grid-column: 2;
min-width: 0;
}
.fishbowl .chatlog__reference, .fishbowl .chatlog__reply {
display: flex;
margin-bottom: 0.15rem;
align-items: center;
color: #b5b6b8;
font-size: 0.85em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-avatar, .fishbowl .chatlog__reply-avatar {
width: 16px;
height: 16px;
margin-right: 0.25rem;
border-radius: 50%;
}
.fishbowl .chatlog__reference-author, .fishbowl .chatlog__reply-author {
margin-right: 0.3rem;
font-weight: 600;
}
.fishbowl .chatlog__reference-content, .fishbowl .chatlog__reply-content {
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-link, .fishbowl .chatlog__reply-link {
cursor: pointer;
}
.fishbowl .chatlog__reference-link *, .fishbowl .chatlog__reply-link * {
display: inline;
pointer-events: none;
}
.fishbowl .chatlog__reference-link .hljs, .fishbowl .chatlog__reply-link .hljs {
display: inline;
}
.fishbowl .chatlog__reference-link .chatlog__markdown-quote, .fishbowl .chatlog__reply-link .chatlog__markdown-quote {
display: inline
}
.fishbowl .chatlog__reference-link .chatlog__markdown-pre, .fishbowl .chatlog__reply-link .chatlog__markdown-pre {
display: inline
}
.fishbowl .chatlog__reference-link:hover, .fishbowl .chatlog__reply-link:hover {
color: #ffffff;
}
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler), .fishbowl .chatlog__reply-link:hover *:not(.chatlog__markdown-spoiler) {
color: inherit;
}
.fishbowl .chatlog__reference-edited-timestamp, .fishbowl .chatlog__reply-edited-timestamp {
margin-left: 0.25rem;
color: #a3a6aa;
font-size: 0.75rem;
font-weight: 500;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__header {
margin-bottom: 0.1rem;
}
.fishbowl .chatlog__author {
font-weight: 500;
color: #ffffff;
}
.fishbowl .chatlog__bot-label {
position: relative;
top: -0.1rem;
margin-left: 0.3rem;
padding: 0.05rem 0.3rem;
border-radius: 3px;
background-color: #5865F2;
color: #ffffff;
font-size: 0.625rem;
font-weight: 500;
line-height: 1.3;
}
.fishbowl .chatlog__timestamp {
margin-left: 0.3rem;
color: #a3a6aa;
font-size: 0.75rem;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__content {
padding-right: 1rem;
word-wrap: break-word;
}
.fishbowl .chatlog__edited-timestamp {
margin-left: 0.15rem;
color: #a3a6aa;
font-size: 0.7em;
}
.fishbowl .chatlog__attachment {
position: relative;
width: fit-content;
margin-top: 0.3rem;
border-radius: 3px;
overflow: hidden;
}
.fishbowl .chatlog__attachment--hidden {
cursor: pointer;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
}
.fishbowl .chatlog__attachment--hidden * {
pointer-events: none;
}
.fishbowl .chatlog__attachment-spoiler-caption {
display: none;
position: absolute;
left: 50%;
top: 50%;
z-index: 999;
padding: 0.4rem 0.8rem;
border-radius: 20px;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.9);
color: #dcddde;
font-size: 0.9rem;
font-weight: 600;
letter-spacing: 0.05rem;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-spoiler-caption {
display: block;
}
.fishbowl .chatlog__attachment--hidden:hover .chatlog__attachment-spoiler-caption {
color: #fff;
}
.fishbowl .chatlog__attachment-media {
max-width: 500px;
max-height: 400px;
vertical-align: top;
border-radius: 3px;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-media {
filter: blur(44px);
}
.fishbowl .chatlog__attachment-generic {
max-width: 520px;
width: 100%;
height: 40px;
padding: 10px;
border: 1px solid #292b2f;
border-radius: 3px;
background-color: #2f3136;
overflow: hidden;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-generic {
filter: blur(44px);
}
.fishbowl .chatlog__attachment-generic-icon {
float: left;
width: 30px;
height: 100%;
margin-right: 10px;
}
.fishbowl .chatlog__attachment-generic-size {
color: #72767d;
font-size: 12px;
}
.fishbowl .chatlog__attachment-generic-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fishbowl .chatlog__embed {
display: flex;
margin-top: 0.3rem;
max-width: 520px;
}
.fishbowl .chatlog__embed-color-pill {
flex-shrink: 0;
width: 0.25rem;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.fishbowl .chatlog__embed-color-pill--default {
background-color: #202225;
}
.fishbowl .chatlog__embed-content-container {
display: flex;
flex-direction: column;
padding: 0.5rem 0.6rem;
border: 1px solid rgba(46, 48, 54, 0.6);
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
background-color: rgba(46, 48, 54, 0.3);
}
.fishbowl .chatlog__embed-content {
display: flex;
width: 100%;
}
.fishbowl .chatlog__embed-text {
flex: 1;
}
.fishbowl .chatlog__embed-author-container {
display: flex;
margin-bottom: 0.5rem;
align-items: center;
}
.fishbowl .chatlog__embed-author-icon {
width: 20px;
height: 20px;
margin-right: 0.5rem;
border-radius: 50%;
}
.fishbowl .chatlog__embed-author {
color: #ffffff;
font-size: 0.875rem;
font-weight: 600;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__embed-author-link {
color: #ffffff;
}
.fishbowl .chatlog__embed-title {
margin-bottom: 0.5rem;
color: #ffffff;
font-size: 0.875rem;
font-weight: 600;
}
.fishbowl .chatlog__embed-description {
color: #dcddde;
font-weight: 500;
font-size: 0.85rem;
}
.fishbowl .chatlog__embed-fields {
display: flex;
flex-wrap: wrap;
gap: 0 0.5rem;
}
.fishbowl .chatlog__embed-field {
flex: 0;
min-width: 100%;
max-width: 506px;
padding-top: 0.6rem;
font-size: 0.875rem;
}
.fishbowl .chatlog__embed-field--inline {
flex: 1;
flex-basis: auto;
min-width: 50px;
}
.fishbowl .chatlog__embed-field-name {
margin-bottom: 0.2rem;
color: #ffffff;
font-weight: 600;
}
.fishbowl .chatlog__embed-field-value {
color: #dcddde;
font-weight: 500;
}
.fishbowl .chatlog__embed-thumbnail {
flex: 0;
max-width: 80px;
max-height: 80px;
margin-left: 1.2rem;
border-radius: 3px;
}
.fishbowl .chatlog__embed-image-container {
margin-top: 0.6rem;
}
.fishbowl .chatlog__embed-image {
max-width: 500px;
max-height: 400px;
border-radius: 3px;
}
.fishbowl .chatlog__embed-footer {
margin-top: 0.6rem;
color: #dcddde;
}
.fishbowl .chatlog__embed-footer-icon {
width: 20px;
height: 20px;
margin-right: 0.2rem;
border-radius: 50%;
vertical-align: middle;
}
.fishbowl .chatlog__embed-footer-text {
vertical-align: middle;
font-size: 0.75rem;
font-weight: 500;
}
.fishbowl .chatlog__embed-plainimage {
max-width: 45vw;
max-height: 500px;
vertical-align: top;
border-radius: 3px;
}
.fishbowl .chatlog__embed-spotify {
border: 0;
}
.fishbowl .chatlog__embed-youtube-container {
margin-top: 0.6rem;
}
.fishbowl .chatlog__embed-youtube {
border: 0;
border-radius: 3px;
}
.fishbowl .chatlog__sticker {
width: 180px;
height: 180px;
}
.fishbowl .chatlog__sticker--media {
max-width: 100%;
max-height: 100%;
}
.fishbowl .chatlog__reactions {
display: flex;
}
.fishbowl .chatlog__reaction {
display: flex;
margin: 0.35rem 0.1rem 0.1rem 0;
padding: 0.125rem 0.375rem;
border: 1px solid transparent;
border-radius: 8px;
background-color: #2f3136;
align-items: center;
}
.fishbowl .chatlog__reaction:hover {
border: 1px solid hsla(0,0%,100%,.2);
background-color: transparent;
}
.fishbowl .chatlog__reaction-count {
min-width: 9px;
margin-left: 0.35rem;
color: #b9bbbe;
font-size: 0.875rem;
}
.fishbowl .chatlog__reaction:hover .chatlog__reaction-count {
color: #dcddde;
}
.fishbowl .chatlog__markdown {
max-width: 100%;
line-height: 1.3;
overflow-wrap: break-word;
}
.fishbowl .chatlog__markdown-preserve {
white-space: pre-wrap;
}
.fishbowl .chatlog__markdown-spoiler {
background-color: rgba(255, 255, 255, 0.1);
border-radius: 3px;
}
.fishbowl .chatlog__markdown-spoiler--hidden {
cursor: pointer;
background-color: #202225;
color: rgba(0, 0, 0, 0);
}
.fishbowl .chatlog__markdown-spoiler--hidden:hover {
background-color: rgba(32, 34, 37, 0.8);
}
.fishbowl .chatlog__markdown-spoiler--hidden::selection {
color: rgba(0, 0, 0, 0);
}
.fishbowl .chatlog__markdown-quote {
display: flex;
margin: 0.05rem 0;
}
.fishbowl .chatlog__markdown-quote-border {
margin-right: 0.5rem;
border: 2px solid #4f545c;
border-radius: 3px;
background-color: #4f545c;
}
.fishbowl .chatlog__markdown-pre {
background-color: #2f3136;
font-family: "Consolas", "Courier New", Courier, monospace;
}
.fishbowl .chatlog__markdown-pre--multiline {
margin-top: 0.25rem;
padding: 0.5rem;
border: 2px solid #282b30;
border-radius: 5px;
color: #b9bbbe;
}
.fishbowl .chatlog__markdown-pre--multiline.hljs {
background-color: inherit;
color: inherit;
}
.fishbowl .chatlog__markdown-pre--inline {
padding: 2px;
border-radius: 3px;
font-size: 0.85rem;
}
.fishbowl .chatlog__markdown-mention {
border-radius: 3px;
padding: 0 2px;
background-color: rgba(88, 101, 242, .3);
color: #dee0fc;
font-weight: 500;
}
.fishbowl .chatlog__markdown-mention:hover {
background-color: #5865f2;
color: #ffffff
}
.fishbowl .chatlog__markdown-timestamp {
border-radius: 3px;
padding: 0 2px;
color: #a3a6aa;
}
.fishbowl .chatlog__emoji {
width: 1.325rem;
height: 1.325rem;
margin: 0 0.06rem;
vertical-align: -0.4rem;
}
.fishbowl .chatlog__emoji--small {
width: 1rem;
height: 1rem;
}
.fishbowl .chatlog__emoji--large {
width: 2.8rem;
height: 2.8rem;
}
.fishbowl .postamble {
padding: 1.25rem;
}
.fishbowl .postamble__entry {
color: #ffffff;
}

627
public/fishbowl-light.css Normal file
View File

@ -0,0 +1,627 @@
.fishbowl {
background-color: #ffffff;
color: #23262a;
border: 1px solid #ddd;
}
.fishbowl a {
color: #0068e0;
text-decoration: none;
}
.fishbowl a:hover {
text-decoration: underline;
}
.fishbowl img {
object-fit: contain;
image-rendering: high-quality;
image-rendering: -webkit-optimize-contrast;
}
.fishbowl .preamble {
display: grid;
grid-template-columns: auto 1fr;
max-width: 100%;
padding: 1rem;
}
.fishbowl .preamble__guild-icon-container {
grid-column: 1;
}
.fishbowl .preamble__guild-icon {
max-width: 88px;
max-height: 88px;
}
.fishbowl .preamble__entries-container {
grid-column: 2;
margin-left: 1rem;
}
.fishbowl .preamble__entry {
margin-bottom: 0.15rem;
color: #2f3136;
font-size: 1.4rem;
}
.fishbowl .preamble__entry--small {
font-size: 1rem;
}
.fishbowl .chatlog {
padding: 1rem 0;
width: 100%;
}
.fishbowl .chatlog__message-group {
margin-bottom: 1rem;
}
.fishbowl .chatlog__message-container {
background-color: transparent;
transition: background-color 1s ease;
}
.fishbowl .chatlog__message-container--highlighted {
background-color: rgba(114, 137, 218, 0.2);
}
.fishbowl .chatlog__message-container--pinned {
background-color: rgba(249, 168, 37, 0.05);
}
.fishbowl .chatlog__message {
display: grid;
grid-template-columns: auto 1fr;
padding: 0.15rem 0;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__message:hover {
background-color: #fafafa;
}
.fishbowl .chatlog__message:hover .chatlog__short-timestamp {
display: block;
}
.fishbowl .chatlog__message-aside {
grid-column: 1;
width: 72px;
padding: 0.15rem 0.15rem 0 0.15rem;
text-align: center;
}
.fishbowl .chatlog__reference-symbol, .fishbowl .chatlog__reply-symbol {
height: 10px;
margin: 6px 4px 4px 36px;
border-left: 2px solid #c7ccd1;
border-top: 2px solid #c7ccd1;
border-radius: 8px 0 0 0;
}
.fishbowl .chatlog__avatar {
width: 40px;
height: 40px;
border-radius: 50%;
}
.fishbowl .chatlog__short-timestamp {
display: none;
color: #5e6772;
font-size: 0.7em;
line-height: 1.4em;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__message-primary {
grid-column: 2;
min-width: 0;
}
.fishbowl .chatlog__reference, .fishbowl .chatlog__reply {
display: flex;
margin-bottom: 0.15rem;
align-items: center;
color: #5f5f60;
font-size: 0.85em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-avatar, .fishbowl .chatlog__reply-avatar {
width: 16px;
height: 16px;
margin-right: 0.25rem;
border-radius: 50%;
}
.fishbowl .chatlog__reference-author, .fishbowl .chatlog__reply-author {
margin-right: 0.3rem;
font-weight: 600;
}
.fishbowl .chatlog__reference-content, .fishbowl .chatlog__reply-content {
overflow: hidden;
text-overflow: ellipsis;
}
.fishbowl .chatlog__reference-link, .fishbowl .chatlog__reply-link {
cursor: pointer;
}
.fishbowl .chatlog__reference-link *, .fishbowl .chatlog__reply-link * {
display: inline;
pointer-events: none;
}
.fishbowl .chatlog__reference-link .hljs, .fishbowl .chatlog__reply-link .hljs {
display: inline;
}
.fishbowl .chatlog__reference-link .chatlog__markdown-quote, .fishbowl .chatlog__reply-link .chatlog__markdown-quote {
display: inline
}
.fishbowl .chatlog__reference-link .chatlog__markdown-pre, .fishbowl .chatlog__reply-link .chatlog__markdown-pre {
display: inline
}
.fishbowl .chatlog__reference-link:hover, .fishbowl .chatlog__reply-link:hover {
color: #2f3136;
}
.fishbowl .chatlog__reference-link:hover *:not(.chatlog__markdown-spoiler), .fishbowl .chatlog__reply-link:hover *:not(.chatlog__markdown-spoiler) {
color: inherit;
}
.fishbowl .chatlog__reference-edited-timestamp, .fishbowl .chatlog__reply-edited-timestamp {
margin-left: 0.25rem;
color: #5e6772;
font-size: 0.75rem;
font-weight: 500;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__header {
margin-bottom: 0.1rem;
}
.fishbowl .chatlog__author {
font-weight: 600;
color: #2f3136;
}
.fishbowl .chatlog__bot-label {
position: relative;
top: -0.1rem;
margin-left: 0.3rem;
padding: 0.05rem 0.3rem;
border-radius: 3px;
background-color: #5865F2;
color: #ffffff;
font-size: 0.625rem;
font-weight: 500;
line-height: 1.3;
}
.fishbowl .chatlog__timestamp {
margin-left: 0.3rem;
color: #5e6772;
font-size: 0.75rem;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__content {
padding-right: 1rem;
word-wrap: break-word;
}
.fishbowl .chatlog__edited-timestamp {
margin-left: 0.15rem;
color: #5e6772;
font-size: 0.7em;
}
.fishbowl .chatlog__attachment {
position: relative;
width: fit-content;
margin-top: 0.3rem;
border-radius: 3px;
overflow: hidden;
}
.fishbowl .chatlog__attachment--hidden {
cursor: pointer;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, 0.1);
}
.fishbowl .chatlog__attachment--hidden * {
pointer-events: none;
}
.fishbowl .chatlog__attachment-spoiler-caption {
display: none;
position: absolute;
left: 50%;
top: 50%;
z-index: 999;
padding: 0.4rem 0.8rem;
border-radius: 20px;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.9);
color: #dcddde;
font-size: 0.9rem;
font-weight: 600;
letter-spacing: 0.05rem;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-spoiler-caption {
display: block;
}
.fishbowl .chatlog__attachment--hidden:hover .chatlog__attachment-spoiler-caption {
color: #fff;
}
.fishbowl .chatlog__attachment-media {
max-width: 500px;
max-height: 400px;
vertical-align: top;
border-radius: 3px;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-media {
filter: blur(44px);
}
.fishbowl .chatlog__attachment-generic {
max-width: 520px;
width: 100%;
height: 40px;
padding: 10px;
border: 1px solid #ebedef;
border-radius: 3px;
background-color: #f2f3f5;
overflow: hidden;
}
.fishbowl .chatlog__attachment--hidden .chatlog__attachment-generic {
filter: blur(44px);
}
.fishbowl .chatlog__attachment-generic-icon {
float: left;
width: 30px;
height: 100%;
margin-right: 10px;
}
.fishbowl .chatlog__attachment-generic-size {
color: #72767d;
font-size: 12px;
}
.fishbowl .chatlog__attachment-generic-name {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fishbowl .chatlog__embed {
display: flex;
margin-top: 0.3rem;
max-width: 520px;
}
.fishbowl .chatlog__embed-color-pill {
flex-shrink: 0;
width: 0.25rem;
border-top-left-radius: 3px;
border-bottom-left-radius: 3px;
}
.fishbowl .chatlog__embed-color-pill--default {
background-color: rgba(227, 229, 232, 1);
}
.fishbowl .chatlog__embed-content-container {
display: flex;
flex-direction: column;
padding: 0.5rem 0.6rem;
border: 1px solid rgba(204, 204, 204, 0.3);
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
background-color: rgba(249, 249, 249, 0.3);
}
.fishbowl .chatlog__embed-content {
display: flex;
width: 100%;
}
.fishbowl .chatlog__embed-text {
flex: 1;
}
.fishbowl .chatlog__embed-author-container {
display: flex;
margin-bottom: 0.5rem;
align-items: center;
}
.fishbowl .chatlog__embed-author-icon {
width: 20px;
height: 20px;
margin-right: 0.5rem;
border-radius: 50%;
}
.fishbowl .chatlog__embed-author {
color: #4f545c;
font-size: 0.875rem;
font-weight: 600;
direction: ltr;
unicode-bidi: bidi-override;
}
.fishbowl .chatlog__embed-author-link {
color: #4f545c;
}
.fishbowl .chatlog__embed-title {
margin-bottom: 0.5rem;
color: #4f545c;
font-size: 0.875rem;
font-weight: 600;
}
.fishbowl .chatlog__embed-description {
color: #2e3338;
font-weight: 500;
font-size: 0.85rem;
}
.fishbowl .chatlog__embed-fields {
display: flex;
flex-wrap: wrap;
gap: 0 0.5rem;
}
.fishbowl .chatlog__embed-field {
flex: 0;
min-width: 100%;
max-width: 506px;
padding-top: 0.6rem;
font-size: 0.875rem;
}
.fishbowl .chatlog__embed-field--inline {
flex: 1;
flex-basis: auto;
min-width: 50px;
}
.fishbowl .chatlog__embed-field-name {
margin-bottom: 0.2rem;
color: #36393e;
font-weight: 600;
}
.fishbowl .chatlog__embed-field-value {
color: #2e3338;
font-weight: 500;
}
.fishbowl .chatlog__embed-thumbnail {
flex: 0;
max-width: 80px;
max-height: 80px;
margin-left: 1.2rem;
border-radius: 3px;
}
.fishbowl .chatlog__embed-image-container {
margin-top: 0.6rem;
}
.fishbowl .chatlog__embed-image {
max-width: 500px;
max-height: 400px;
border-radius: 3px;
}
.fishbowl .chatlog__embed-footer {
margin-top: 0.6rem;
color: #2e3338;
}
.fishbowl .chatlog__embed-footer-icon {
width: 20px;
height: 20px;
margin-right: 0.2rem;
border-radius: 50%;
vertical-align: middle;
}
.fishbowl .chatlog__embed-footer-text {
vertical-align: middle;
font-size: 0.75rem;
font-weight: 500;
}
.fishbowl .chatlog__embed-plainimage {
max-width: 45vw;
max-height: 500px;
vertical-align: top;
border-radius: 3px;
}
.fishbowl .chatlog__embed-spotify {
border: 0;
}
.fishbowl .chatlog__embed-youtube-container {
margin-top: 0.6rem;
}
.fishbowl .chatlog__embed-youtube {
border: 0;
border-radius: 3px;
}
.fishbowl .chatlog__sticker {
width: 180px;
height: 180px;
}
.fishbowl .chatlog__sticker--media {
max-width: 100%;
max-height: 100%;
}
.fishbowl .chatlog__reactions {
display: flex;
}
.fishbowl .chatlog__reaction {
display: flex;
margin: 0.35rem 0.1rem 0.1rem 0;
padding: 0.125rem 0.375rem;
border: 1px solid transparent;
border-radius: 8px;
background-color: #f2f3f5;
align-items: center;
}
.fishbowl .chatlog__reaction:hover {
border: 1px solid rgba(0, 0, 0, 0.2);
background-color: white;
}
.fishbowl .chatlog__reaction-count {
min-width: 9px;
margin-left: 0.35rem;
color: #4f5660;
font-size: 0.875rem;
}
.fishbowl .chatlog__reaction:hover .chatlog__reaction-count {
color: #2e3338;
}
.fishbowl .chatlog__markdown {
max-width: 100%;
line-height: 1.3;
overflow-wrap: break-word;
}
.fishbowl .chatlog__markdown-preserve {
white-space: pre-wrap;
}
.fishbowl .chatlog__markdown-spoiler {
background-color: rgba(0, 0, 0, 0.1);
border-radius: 3px;
}
.fishbowl .chatlog__markdown-spoiler--hidden {
cursor: pointer;
background-color: #b9bbbe;
color: rgba(0, 0, 0, 0);
}
.fishbowl .chatlog__markdown-spoiler--hidden:hover {
background-color: rgba(185, 187, 190, 0.8);
}
.fishbowl .chatlog__markdown-spoiler--hidden::selection {
color: rgba(0, 0, 0, 0);
}
.fishbowl .chatlog__markdown-quote {
display: flex;
margin: 0.05rem 0;
}
.fishbowl .chatlog__markdown-quote-border {
margin-right: 0.5rem;
border: 2px solid #c7ccd1;
border-radius: 3px;
background-color: #c7ccd1;
}
.fishbowl .chatlog__markdown-pre {
background-color: #f9f9f9;
font-family: "Consolas", "Courier New", Courier, monospace;
}
.fishbowl .chatlog__markdown-pre--multiline {
margin-top: 0.25rem;
padding: 0.5rem;
border: 2px solid #f3f3f3;
border-radius: 5px;
color: #657b83;
}
.fishbowl .chatlog__markdown-pre--multiline.hljs {
background-color: inherit;
color: inherit;
}
.fishbowl .chatlog__markdown-pre--inline {
padding: 2px;
border-radius: 3px;
font-size: 0.85rem;
}
.fishbowl .chatlog__markdown-mention {
border-radius: 3px;
padding: 0 2px;
background-color: rgba(88, 101, 242, .15);
color: #505cdc;
font-weight: 500;
}
.fishbowl .chatlog__markdown-mention:hover {
background-color: #5865f2;
color: #ffffff
}
.fishbowl .chatlog__markdown-timestamp {
border-radius: 3px;
padding: 0 2px;
color: #5e6772;
}
.fishbowl .chatlog__emoji {
width: 1.325rem;
height: 1.325rem;
margin: 0 0.06rem;
vertical-align: -0.4rem;
}
.fishbowl .chatlog__emoji--small {
width: 1rem;
height: 1rem;
}
.fishbowl .chatlog__emoji--large {
width: 2.8rem;
height: 2.8rem;
}
.fishbowl .postamble {
padding: 1.25rem;
}
.fishbowl .postamble__entry {
color: #2f3136;
}

View File

@ -2,47 +2,18 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
"use strict";
(() => {
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel
// - Webpack
if (typeof global !== "undefined") {
// global already exists
} else if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither global, window nor self is defined)");
}
if (!global.require && typeof require !== "undefined") {
global.require = require;
}
if (!global.fs && global.require) {
const fs = require("fs");
if (typeof fs === "object" && fs !== null && Object.keys(fs).length !== 0) {
global.fs = fs;
}
}
const enosys = () => {
const err = new Error("not implemented");
err.code = "ENOSYS";
return err;
};
if (!global.fs) {
if (!globalThis.fs) {
let outputBuf = "";
global.fs = {
globalThis.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
@ -87,8 +58,8 @@
};
}
if (!global.process) {
global.process = {
if (!globalThis.process) {
globalThis.process = {
getuid() { return -1; },
getgid() { return -1; },
geteuid() { return -1; },
@ -102,47 +73,26 @@
}
}
if (!global.crypto && global.require) {
const nodeCrypto = require("crypto");
global.crypto = {
getRandomValues(b) {
nodeCrypto.randomFillSync(b);
},
};
}
if (!global.crypto) {
throw new Error("global.crypto is not available, polyfill required (getRandomValues only)");
if (!globalThis.crypto) {
throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)");
}
if (!global.performance) {
global.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};
if (!globalThis.performance) {
throw new Error("globalThis.performance is not available, polyfill required (performance.now only)");
}
if (!global.TextEncoder && global.require) {
global.TextEncoder = require("util").TextEncoder;
}
if (!global.TextEncoder) {
throw new Error("global.TextEncoder is not available, polyfill required");
if (!globalThis.TextEncoder) {
throw new Error("globalThis.TextEncoder is not available, polyfill required");
}
if (!global.TextDecoder && global.require) {
global.TextDecoder = require("util").TextDecoder;
if (!globalThis.TextDecoder) {
throw new Error("globalThis.TextDecoder is not available, polyfill required");
}
if (!global.TextDecoder) {
throw new Error("global.TextDecoder is not available, polyfill required");
}
// End of polyfills for common API.
const encoder = new TextEncoder("utf-8");
const decoder = new TextDecoder("utf-8");
global.Go = class {
globalThis.Go = class {
constructor() {
this.argv = ["js"];
this.env = {};
@ -296,8 +246,8 @@
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
},
// func walltime1() (sec int64, nsec int32)
"runtime.walltime1": (sp) => {
// func walltime() (sec int64, nsec int32)
"runtime.walltime": (sp) => {
sp >>>= 0;
const msec = (new Date).getTime();
setInt64(sp + 8, msec / 1000);
@ -401,6 +351,7 @@
storeValue(sp + 56, result);
this.mem.setUint8(sp + 64, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 56, err);
this.mem.setUint8(sp + 64, 0);
}
@ -417,6 +368,7 @@
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}
@ -433,6 +385,7 @@
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}
@ -514,7 +467,7 @@
null,
true,
false,
global,
globalThis,
this,
];
this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
@ -523,7 +476,7 @@
[null, 2],
[true, 3],
[false, 4],
[global, 5],
[globalThis, 5],
[this, 6],
]);
this._idPool = []; // unused ids that have been garbage collected
@ -564,6 +517,13 @@
offset += 8;
});
// The linker guarantees global data starts from at least wasmMinDataAddr.
// Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr.
const wasmMinDataAddr = 4096 + 8192;
if (offset >= wasmMinDataAddr) {
throw new Error("total length of command line and environment variables exceeds limit");
}
this._inst.exports.run(argc, argv);
if (this.exited) {
this._resolveExitPromise();
@ -591,36 +551,4 @@
};
}
}
if (
typeof module !== "undefined" &&
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length < 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}
const go = new Go();
go.argv = process.argv.slice(2);
go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env);
go.exit = process.exit;
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
process.on("exit", (code) => { // Node.js exits if no event handler is pending
if (code === 0 && !go.exited) {
// deadlock, make Go print error and stack traces
go._pendingEvent = { id: 0 };
go._resume();
}
});
return go.run(result.instance);
}).catch((err) => {
console.error(err);
process.exit(1);
});
}
})();

BIN
public/hms/banner_tall.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 682 KiB

BIN
public/hms/handmadecon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB

0
public/icons.ttf Executable file → Normal file
View File

78
public/js/carousel.js Normal file
View File

@ -0,0 +1,78 @@
function initCarousel(container, options = {}) {
const durationMS = options.durationMS ?? 0;
const onChange = options.onChange ?? (() => {});
const numCarouselItems = container.querySelectorAll('.carousel-item').length;
const buttonContainer = container.querySelector('.carousel-buttons');
let current = 0;
function activateCarousel(i, silent = false) {
const items = document.querySelectorAll('.carousel-item');
for (const item of items) {
item.classList.remove('active');
}
items[i].classList.add('active');
const smallItems = document.querySelectorAll('.carousel-item-small');
if (smallItems.length > 0) {
for (const item of smallItems) {
item.classList.remove('active');
}
smallItems[i].classList.add('active');
}
const buttons = document.querySelectorAll('.carousel-button');
for (const button of buttons) {
button.classList.remove('active');
}
buttons[i].classList.add('active');
current = i;
if (!silent) {
onChange(current);
}
}
function activateNext() {
activateCarousel((current + numCarouselItems + 1) % numCarouselItems);
}
function activatePrev() {
activateCarousel((current + numCarouselItems - 1) % numCarouselItems);
}
const carouselTimer = durationMS > 0 && setInterval(() => {
if (numCarouselItems === 0) {
return;
}
activateNext();
}, durationMS);
function carouselButtonClick(i) {
activateCarousel(i);
if (carouselTimer) {
clearInterval(carouselTimer);
}
}
for (let i = 0; i < numCarouselItems; i++) {
const button = document.createElement('div');
button.classList.add('carousel-button', 'br-pill', 'w1', 'h1', 'mh2');
button.classList.toggle('active', i === 0);
const clickIndex = i;
button.addEventListener('click', () => {
carouselButtonClick(clickIndex);
});
buttonContainer.appendChild(button);
}
activateCarousel(0, true);
return {
next: activateNext,
prev: activatePrev,
};
}

33
public/js/countdown.js Normal file
View File

@ -0,0 +1,33 @@
document.addEventListener("DOMContentLoaded", () => {
for (const countdown of document.querySelectorAll(".countdown")) {
const deadline = countdown.getAttribute("data-deadline");
const deadlineDate = new Date(parseInt(deadline, 10) * 1000);
function updateCountdown() {
const remainingMs = deadlineDate.getTime() - new Date().getTime();
const remainingMinutes = remainingMs / 1000 / 60;
const remainingHours = remainingMinutes / 60;
const remainingDays = remainingHours / 24; // no daylight savings transitions during the jam mmkay
let str = "imminently";
if (remainingMinutes < 60) {
str = `in ${Math.ceil(remainingMinutes)} ${
remainingMinutes === 1 ? "minute" : "minutes"
}`;
} else if (remainingHours < 24) {
str = `in ${Math.ceil(remainingHours)} ${
remainingHours === 1 ? "hour" : "hours"
}`;
} else {
str = `in ${Math.ceil(remainingDays)} ${
remainingDays === 1 ? "day" : "days"
}`;
}
countdown.innerText = str;
}
updateCountdown();
setInterval(updateCountdown, 1000 * 60);
}
});

View File

@ -1,20 +1,28 @@
function ImageSelector(form, maxFileSize, container, defaultImageUrl) {
function ImageSelector(form, maxFileSize, container, {
defaultImageUrl = "",
onUpdate = (url) => {},
} = {}) {
this.form = form;
this.maxFileSize = maxFileSize;
this.fileInput = container.querySelector(".image_input");
this.removeImageInput = container.querySelector(".remove_input");
this.fileInput = container.querySelector(".imginput");
this.removeImageInput = container.querySelector(".imginput-remove");
this.imageEl = container.querySelector("img");
this.resetLink = container.querySelector(".reset");
this.removeLink = container.querySelector(".remove");
this.originalImageUrl = this.imageEl.getAttribute("data-original");
this.container = container.querySelector(".imginput-container");
this.resetLink = container.querySelector(".imginput-reset-link");
this.removeLink = container.querySelector(".imginput-remove-link");
this.filenameText = container.querySelector(".imginput-filename");
this.errorEl = container.querySelector(".error");
this.originalImageUrl = this.imageEl.getAttribute("data-imginput-original");
this.originalImageFilename = this.imageEl.getAttribute("data-imginput-original-filename");
this.currentImageUrl = this.originalImageUrl;
this.defaultImageUrl = defaultImageUrl || "";
this.defaultImageUrl = defaultImageUrl;
this.onUpdate = onUpdate;
this.fileInput.value = "";
this.removeImageInput.value = "";
this.setImageUrl(this.originalImageUrl);
this.updateButtons();
this.setImageUrl(this.originalImageUrl, true);
this.updatePreview();
this.fileInput.addEventListener("change", function(ev) {
if (this.fileInput.files.length > 0) {
@ -33,12 +41,16 @@ function ImageSelector(form, maxFileSize, container, defaultImageUrl) {
}
}
ImageSelector.prototype.openFileInput = function() {
this.fileInput.click();
}
ImageSelector.prototype.handleNewImageFile = function(file) {
if (file) {
this.updateSizeLimit(file.size);
this.removeImageInput.value = "";
this.setImageUrl(URL.createObjectURL(file));
this.updateButtons();
this.updatePreview(file);
}
};
@ -47,7 +59,7 @@ ImageSelector.prototype.removeImage = function() {
this.fileInput.value = "";
this.removeImageInput.value = "true";
this.setImageUrl(this.defaultImageUrl);
this.updateButtons();
this.updatePreview(null);
};
ImageSelector.prototype.resetImage = function() {
@ -55,7 +67,7 @@ ImageSelector.prototype.resetImage = function() {
this.fileInput.value = "";
this.removeImageInput.value = "";
this.setImageUrl(this.originalImageUrl);
this.updateButtons();
this.updatePreview(null);
};
ImageSelector.prototype.updateSizeLimit = function(size) {
@ -68,11 +80,13 @@ ImageSelector.prototype.updateSizeLimit = function(size) {
};
ImageSelector.prototype.setError = function(error) {
this.errorEl.textContent = error;
this.errorEl.hidden = !error;
this.fileInput.setCustomValidity(error);
this.fileInput.reportValidity();
}
ImageSelector.prototype.setImageUrl = function(url) {
ImageSelector.prototype.setImageUrl = function(url, initial = false) {
this.currentImageUrl = url;
this.imageEl.src = url;
if (url.length > 0) {
@ -80,21 +94,30 @@ ImageSelector.prototype.setImageUrl = function(url) {
} else {
this.imageEl.style.display = "none";
}
};
ImageSelector.prototype.updateButtons = function() {
if ((this.originalImageUrl.length > 0 && this.originalImageUrl != this.defaultImageUrl)
&& this.currentImageUrl != this.originalImageUrl) {
this.resetLink.style.display = "inline-block";
} else {
this.resetLink.style.display = "none";
}
if (!this.fileInput.required && this.currentImageUrl != this.defaultImageUrl) {
this.removeLink.style.display = "inline-block";
} else {
this.removeLink.style.display = "none";
this.url = url;
if (!initial) {
this.onUpdate(url);
}
};
ImageSelector.prototype.updatePreview = function(file) {
const showReset = (
this.originalImageUrl
&& this.originalImageUrl != this.defaultImageUrl
&& this.originalImageUrl != this.currentImageUrl
);
const showRemove = (
!this.fileInput.required
&& this.currentImageUrl != this.defaultImageUrl
);
this.resetLink.hidden = !showReset;
this.removeLink.hidden = !showRemove;
if (this.currentImageUrl == this.originalImageUrl) {
this.filenameText.innerText = this.originalImageFilename;
} else {
this.filenameText.innerText = file ? file.name : "";
}
this.container.hidden = !this.currentImageUrl;
};

View File

@ -0,0 +1,246 @@
// Requires base64.js
/**
* Sets up file / image uploading for Markdown content.
*
* @param eSubmits A list of elements of buttons to submit/save the page you're on. They
* will be disabled and tell users files are uploading while uploading is
* happening.
* @param eFileInput The `<input type="file">`
* @param eUploadBar Usually looks like
* ```
* <div class="upload_bar flex-grow-1">
* <div class="instructions">
* Upload files by dragging & dropping, pasting, or <label class="pointer link" for="file_input">selecting</label> them.
* </div>
* <div class="progress flex">
* <div class="progress_text mr3"></div>
* <div class="progress_bar flex-grow-1 flex-shrink-1 pa1"><div class=""></div></div>
* </div>
* </div>
* ```
* @param eText The text field that can be dropped into and is editing the markdown.
* @param doMarkdown The function returned by `initLiveMarkdown`.
* @param maxFileSize The max allowed file size in bytes.
* @param uploadUrl The URL to POST assets to (unique per project to avoid CORS issues).
*/
function setupMarkdownUpload(eSubmits, eFileInput, eUploadBar, eText, doMarkdown, maxFileSize, uploadUrl) {
const submitTexts = Array.from(eSubmits).map(e => e.value);
const uploadProgress = eUploadBar.querySelector('.progress');
const uploadProgressText = eUploadBar.querySelector('.progress_text');
const uploadProgressBar = eUploadBar.querySelector('.progress_bar');
const uploadProgressBarFill = eUploadBar.querySelector('.progress_bar > div');
let fileCounter = 0;
let enterCounter = 0;
let uploadQueue = [];
let currentUpload = null;
let currentXhr = null;
let currentBatchSize = 0;
let currentBatchDone = 0;
eFileInput.addEventListener("change", function(ev) {
if (eFileInput.files.length > 0) {
importUserFiles(eFileInput.files);
}
});
eText.addEventListener("dragover", function(ev) {
let effect = "none";
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
effect = "copy";
break;
}
}
ev.dataTransfer.dropEffect = effect;
ev.preventDefault();
});
eText.addEventListener("dragenter", function(ev) {
enterCounter++;
let droppable = false;
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
droppable = true;
break;
}
}
if (droppable) {
eText.classList.add("drop");
}
});
eText.addEventListener("dragleave", function(ev) {
enterCounter--;
if (enterCounter == 0) {
eText.classList.remove("drop");
}
});
function makeUploadString(uploadNumber, filename) {
return `Uploading file #${uploadNumber}: \`${filename}\`...`;
}
eText.addEventListener("drop", function(ev) {
enterCounter = 0;
eText.classList.remove("drop");
if (ev.dataTransfer && ev.dataTransfer.files) {
importUserFiles(ev.dataTransfer.files)
}
ev.preventDefault();
});
eText.addEventListener("paste", function(ev) {
const files = ev.clipboardData?.files ?? [];
if (files.length > 0) {
importUserFiles(files)
}
});
function importUserFiles(files) {
let items = [];
for (let i = 0; i < files.length; ++i) {
let f = files[i];
if (f.size < maxFileSize) {
items.push({ file: f, error: null });
} else {
items.push({ file: null, error: `\`${f.name}\` is too big! Max size is ${maxFileSize} but the file is ${f.size}.` });
}
}
let cursorStart = eText.selectionStart;
let cursorEnd = eText.selectionEnd;
let toInsert = "";
let linesToCursor = eText.value.substr(0, cursorStart).split("\n");
let cursorLine = linesToCursor[linesToCursor.length-1].trim();
if (cursorLine.length > 0) {
toInsert = "\n\n";
}
for (let i = 0; i < items.length; ++i) {
if (items[i].file) {
fileCounter++;
toInsert += makeUploadString(fileCounter, items[i].file.name) + "\n\n";
queueUpload(fileCounter, items[i].file);
} else {
toInsert += `${items[i].error}\n\n`;
}
}
eText.value = eText.value.substring(0, cursorStart) + toInsert + eText.value.substring(cursorEnd, eText.value.length);
doMarkdown();
uploadNext();
}
function replaceUploadString(upload, newString) {
let cursorStart = eText.selectionStart;
let cursorEnd = eText.selectionEnd;
let uploadString = makeUploadString(upload.uploadNumber, upload.file.name);
let insertIndex = eText.value.indexOf(uploadString)
eText.value = eText.value.replace(uploadString, newString);
if (cursorStart <= insertIndex + uploadString.length) {
eText.selectionStart = cursorStart;
} else {
eText.selectionStart = cursorStart - uploadString.length + newString.length;
}
if (cursorEnd <= insertIndex + uploadString.length) {
eText.selectionEnd = cursorEnd;
} else {
eText.selectionEnd = cursorEnd - uploadString.length + newString.length;
}
doMarkdown();
}
function replaceUploadStringError(upload) {
replaceUploadString(upload, `There was a problem uploading your file \`${upload.file.name}\`.`);
}
function queueUpload(uploadNumber, file) {
uploadQueue.push({
uploadNumber: uploadNumber,
file: file
});
currentBatchSize++;
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
}
function uploadDone(ev) {
try {
if (currentXhr.status == 200 && currentXhr.response) {
if (currentXhr.response.url) {
let url = currentXhr.response.url;
let newString = `[${currentUpload.file.name}](${url})`;
if (currentXhr.response.mime.startsWith("image")) {
newString = "!" + newString;
}
replaceUploadString(currentUpload, newString);
} else if (currentXhr.response.error) {
replaceUploadString(currentUpload, `Upload failed for \`${currentUpload.file.name}\`: ${currentXhr.response.error}.`);
} else {
replaceUploadStringError(currentUpload);
}
} else {
replaceUploadStringError(currentUpload);
}
} catch (err) {
console.error(err);
replaceUploadStringError(currentUpload);
}
currentUpload = null;
currentXhr = null;
currentBatchDone++;
uploadNext();
}
function updateUploadProgress(ev) {
if (ev.lengthComputable) {
let progress = ev.loaded / ev.total;
uploadProgressBarFill.style.width = Math.floor(progress * 100) + "%";
}
}
function uploadNext() {
if (currentUpload == null) {
next = uploadQueue.shift();
if (next) {
uploadProgressText.textContent = `Uploading files ${currentBatchDone+1}/${currentBatchSize}`;
eUploadBar.classList.add("uploading");
uploadProgressBarFill.style.width = "0%";
for (const e of eSubmits) {
e.disabled = true;
e.value = "Uploading files...";
}
try {
let utf8Filename = strToUTF8Arr(next.file.name);
let base64Filename = base64EncArr(utf8Filename);
// NOTE(asaf): We use XHR because fetch can't do upload progress reports. Womp womp. https://youtu.be/Pubd-spHN-0?t=2
currentXhr = new XMLHttpRequest();
currentXhr.upload.addEventListener("progress", updateUploadProgress);
currentXhr.open("POST", uploadUrl, true);
currentXhr.setRequestHeader("Hmn-Upload-Filename", base64Filename);
currentXhr.responseType = "json";
currentXhr.addEventListener("loadend", uploadDone);
currentXhr.send(next.file);
currentUpload = next;
} catch (err) {
replaceUploadStringError(next);
console.error(err);
uploadNext();
}
} else {
for (const [i, e] of eSubmits.entries()) {
e.disabled = false;
e.value = submitTexts[i];
}
eUploadBar.classList.remove("uploading");
currentBatchSize = 0;
currentBatchDone = 0;
}
}
}
}

3
public/js/script.js Normal file
View File

@ -0,0 +1,3 @@
function rem2px(rem) {
return rem * parseFloat(getComputedStyle(document.documentElement).fontSize);
}

View File

@ -8,7 +8,7 @@ const TimelineMediaTypes = {
const showcaseItemTemplate = makeTemplateCloner("showcase_item");
const modalTemplate = makeTemplateCloner("timeline_modal");
const tagTemplate = makeTemplateCloner("timeline_item_tag");
const projectLinkTemplate = makeTemplateCloner("project_link");
function showcaseTimestamp(rawDate) {
const date = new Date(rawDate*1000);
@ -25,6 +25,7 @@ function doOnce(f) {
}
}
// TODO(redesign): Fix snippet editing, given that snippets are now presented very differently.
function makeShowcaseItem(timelineItem) {
const timestamp = showcaseTimestamp(timelineItem.date);
@ -45,27 +46,38 @@ function makeShowcaseItem(timelineItem) {
createModalContentFunc = () => {
const modalImage = document.createElement('img');
modalImage.src = timelineItem.asset_url;
modalImage.classList.add('mw-100', 'mh-60vh');
modalImage.classList.add('mw-100', 'maxh-60vh');
return modalImage;
};
break;
case TimelineMediaTypes.VIDEO:
addThumbnailFunc = () => {
const video = document.createElement('video');
video.src = timelineItem.asset_url; // TODO: Use image thumbnails
video.controls = false;
video.classList.add('h-100');
video.preload = 'metadata';
itemEl.thumbnail.appendChild(video);
let thumbEl;
if (timelineItem.thumbnail_url) {
thumbEl = document.createElement('img');
thumbEl.src = timelineItem.thumbnail_url;
} else {
thumbEl = document.createElement('video');
thumbEl.src = timelineItem.asset_url;
thumbEl.controls = false;
thumbEl.preload = 'metadata';
}
thumbEl.classList.add('h-100');
itemEl.thumbnail.appendChild(thumbEl);
};
createModalContentFunc = () => {
const modalVideo = document.createElement('video');
modalVideo.src = timelineItem.asset_url;
modalVideo.controls = true;
if (timelineItem.thumbnail_url) {
modalVideo.poster = timelineItem.thumbnail_url;
modalVideo.preload = 'none';
} else {
modalVideo.preload = 'metadata';
modalVideo.classList.add('mw-100', 'mh-60vh');
}
modalVideo.controls = true;
modalVideo.classList.add('mw-100', 'maxh-60vh');
return modalVideo;
};
@ -97,18 +109,24 @@ function makeShowcaseItem(timelineItem) {
modalEl.date.textContent = timestamp;
modalEl.date.setAttribute("href", timelineItem.snippet_url);
if (timelineItem.tags.length === 0) {
modalEl.tags.remove();
if (timelineItem.projects.length === 0) {
modalEl.projects.remove();
} else {
for (const tag of timelineItem.tags) {
const tagItem = tagTemplate();
tagItem.tag.innerText = tag.text;
for (const proj of timelineItem.projects) {
const projectLink = projectLinkTemplate();
projectLink.root.href = proj.url;
projectLink.logo.src = proj.logo;
projectLink.name.textContent = proj.name;
modalEl.tags.appendChild(tagItem.root);
modalEl.projects.appendChild(projectLink.root);
}
}
if (timelineItem.discord_message_url != "") {
modalEl.discord_link.href = timelineItem.discord_message_url;
} else {
modalEl.discord_link.remove();
}
function close() {
modalEl.overlay.remove();

390
public/js/snippetedit.js Normal file
View File

@ -0,0 +1,390 @@
const snippetEditTemplate = makeTemplateCloner("snippet-edit");
const snippetEditProjectTemplate = makeTemplateCloner("snippet-edit-project");
function readableByteSize(numBytes) {
const scales = [
" bytes",
"kb",
"mb",
"gb"
];
let scale = 0;
while (numBytes > 1024 && scale < scales.length - 1) {
numBytes /= 1024;
scale++;
}
return new Intl.NumberFormat([], { maximumFractionDigits: (scale > 0 ? 2 : 0) }).format(numBytes) + scales[scale];
}
function makeSnippetEdit(ownerName, ownerAvatar, ownerUrl, date, text, attachmentElement, projectIds, stickyProjectId, snippetId, originalSnippetEl) {
let snippetEdit = snippetEditTemplate();
let projectSelector = null;
let originalAttachment = null;
let originalText = text;
let attachmentChanged = false;
let hasAttachment = false;
snippetEdit.redirect.value = location.href;
if (ownerAvatar) {
snippetEdit.avatarImg.src = ownerAvatar;
snippetEdit.avatarLink.href = ownerUrl;
snippetEdit.avatarImg.hidden = false;
} else {
snippetEdit.avatarImg.hidden = true;
}
snippetEdit.username.textContent = ownerName;
snippetEdit.username.href = ownerUrl;
snippetEdit.date.textContent = new Intl.DateTimeFormat([], { month: "2-digit", day: "2-digit", year: "numeric" }).format(date);
snippetEdit.text.value = text;
if (attachmentElement) {
originalAttachment = attachmentElement.cloneNode(true);
clearAttachment(true);
}
if (snippetId !== undefined && snippetId !== null) {
snippetEdit.snippetId.value = snippetId;
} else {
snippetEdit.deleteButton.remove();
}
for (let i = 0; i < projectIds.length; ++i) {
let proj = null;
for (let j = 0; j < availableProjects.length; ++j) {
if (projectIds[i] == availableProjects[j].id) {
proj = availableProjects[j];
break;
}
}
if (proj) {
addProject(proj);
}
}
updateProjectSelector();
if (originalSnippetEl) {
snippetEdit.cancelLink.addEventListener("click", function () {
cancel();
});
} else {
snippetEdit.cancelLink.remove();
}
function cancel() {
if (originalSnippetEl) {
snippetEdit.root.parentElement.insertBefore(originalSnippetEl, snippetEdit.root);
}
snippetEdit.root.remove();
}
function addProject(proj) {
let projEl = snippetEditProjectTemplate();
projEl.projectId.value = proj.id;
projEl.projectLogo.src = proj.logo;
projEl.projectName.textContent = proj.name;
if (proj.id == stickyProjectId) {
projEl.removeButton.remove();
} else {
projEl.removeButton.addEventListener("click", function (ev) {
projEl.root.remove();
updateProjectSelector();
});
}
snippetEdit.projectList.appendChild(projEl.root);
}
function updateProjectSelector() {
if (projectSelector) {
projectSelector.remove();
}
let remainingProjects = [];
let projInputs = snippetEdit.projectList.querySelectorAll("input[name=project_id]");
let assignedIds = [];
for (let i = 0; i < projInputs.length; ++i) {
let id = parseInt(projInputs[i].value, 10);
if (!isNaN(id)) {
assignedIds.push(id);
}
}
for (let i = 0; i < availableProjects.length; ++i) {
let found = false;
for (let j = 0; j < assignedIds.length; ++j) {
if (assignedIds[j] == availableProjects[i].id) {
found = true;
break;
}
}
if (!found) {
remainingProjects.push(availableProjects[i]);
}
}
if (remainingProjects.length > 0) {
projectSelector = document.createElement("SELECT");
let option = document.createElement("OPTION");
option.textContent = "Add to project...";
option.selected = true;
projectSelector.appendChild(option);
for (let i = 0; i < remainingProjects.length; ++i) {
option = document.createElement("OPTION");
option.value = remainingProjects[i].id;
option.selected = false;
option.textContent = remainingProjects[i].name;
projectSelector.appendChild(option);
}
projectSelector.addEventListener("change", function (ev) {
if (projectSelector.selectedOptions.length > 0) {
let selected = projectSelector.selectedOptions[0];
if (selected.value != "") {
let id = parseInt(selected.value, 10);
if (!isNaN(id)) {
for (let i = 0; i < availableProjects.length; ++i) {
if (availableProjects[i].id == id) {
addProject(availableProjects[i]);
break;
}
}
}
updateProjectSelector();
}
}
});
snippetEdit.projectList.appendChild(projectSelector);
}
}
function setFile(file) {
let dt = new DataTransfer();
dt.items.add(file);
snippetEdit.file.files = dt.files;
attachmentChanged = true;
snippetEdit.removeAttachment.value = "false";
hasAttachment = true;
let el = null;
if (file.type.startsWith("image/")) {
el = document.createElement("img");
el.src = URL.createObjectURL(file);
} else if (file.type.startsWith("video/")) {
el = document.createElement("video");
el.src = URL.createObjectURL(file);
el.controls = true;
} else if (file.type.startsWith("audio/")) {
el = document.createElement("audio");
el.src = URL.createObjectURL(file);
} else {
el = document.createElement("div");
el.classList.add("project-card", "br2", "pv1", "ph2");
let anchor = document.createElement("a");
anchor.href = URL.createObjectURL(file);
anchor.setAttribute("target", "_blank");
anchor.textContent = file.name + " (" + readableByteSize(file.size) + ")";
el.appendChild(anchor);
}
setPreview(el);
validate();
}
function clearAttachment(restoreOriginal) {
snippetEdit.file.value = "";
let el = null;
attachmentChanged = false;
hasAttachment = false;
snippetEdit.removeAttachment.value = "false";
if (originalAttachment) {
if (restoreOriginal) {
hasAttachment = true;
el = originalAttachment;
} else {
attachmentChanged = true;
snippetEdit.removeAttachment.value = "true";
}
}
setPreview(el);
validate();
}
function setPreview(el) {
if (el) {
snippetEdit.uploadBox.style.display = "none";
snippetEdit.previewBox.style.display = "block";
snippetEdit.uploadResetBox.style.display = "none";
snippetEdit.previewContent = emptyElement(snippetEdit.previewContent);
snippetEdit.previewContent.appendChild(el);
snippetEdit.resetLink.style.display = (!originalAttachment || el == originalAttachment) ? "none" : "inline-block";
} else {
snippetEdit.uploadBox.style.display = "block";
snippetEdit.previewBox.style.display = "none";
if (originalAttachment) {
snippetEdit.uploadResetBox.style.display = "block";
}
}
}
function validate() {
let sizeGood = true;
if (snippetEdit.file.files.length > 0 && snippetEdit.file.files[0].size > maxFilesize) {
// NOTE(asaf): Writing this out in bytes to make the limit exactly clear to the user.
let readableSize = new Intl.NumberFormat([], { useGrouping: "always" }).format(maxFilesize);
snippetEdit.errors.textContent = "File is too big! Max filesize is " + readableSize + " bytes.";
sizeGood = false;
} else {
snippetEdit.errors.textContent = "";
}
let hasText = snippetEdit.text.value.trim().length > 0;
if ((hasText || hasAttachment) && sizeGood) {
snippetEdit.saveButton.disabled = false;
} else {
snippetEdit.saveButton.disabled = true;
}
}
snippetEdit.uploadLink.addEventListener("click", function () {
snippetEdit.file.click();
});
snippetEdit.removeLink.addEventListener("click", function () {
clearAttachment(false);
});
snippetEdit.replaceLink.addEventListener("click", function () {
snippetEdit.file.click();
});
snippetEdit.resetLink.addEventListener("click", function () {
clearAttachment(true);
});
snippetEdit.uploadResetLink.addEventListener("click", function () {
clearAttachment(true);
});
snippetEdit.file.addEventListener("change", function () {
if (snippetEdit.file.files.length > 0) {
setFile(snippetEdit.file.files[0]);
}
});
snippetEdit.root.addEventListener("dragover", function (ev) {
let effect = "none";
for (let i = 0; i < ev.dataTransfer.items.length; ++i) {
if (ev.dataTransfer.items[i].kind.toLowerCase() == "file") {
effect = "copy";
break;
}
}
ev.dataTransfer.dropEffect = effect;
ev.preventDefault();
});
let enterCounter = 0;
snippetEdit.root.addEventListener("dragenter", function (ev) {
enterCounter++;
let droppable = Array.from(ev.dataTransfer.items).some(
item => item.kind.toLowerCase() === "file"
);
if (droppable) {
snippetEdit.root.classList.add("drop");
}
});
snippetEdit.root.addEventListener("dragleave", function (ev) {
enterCounter--;
if (enterCounter == 0) {
snippetEdit.root.classList.remove("drop");
}
});
snippetEdit.root.addEventListener("drop", function (ev) {
enterCounter = 0;
snippetEdit.root.classList.remove("drop");
if (ev.dataTransfer && ev.dataTransfer.files && ev.dataTransfer.files.length > 0) {
setFile(ev.dataTransfer.files[0]);
}
ev.preventDefault();
});
snippetEdit.text.addEventListener("paste", function (ev) {
const files = ev.clipboardData?.files ?? [];
if (files.length > 0) {
setFile(files[0]);
}
});
snippetEdit.text.addEventListener("input", function (ev) {
validate();
});
snippetEdit.saveButton.addEventListener("click", function (ev) {
let projectsChanged = false;
let projInputs = snippetEdit.projectList.querySelectorAll("input[name=project_id]");
let assignedIds = [];
for (let i = 0; i < projInputs.length; ++i) {
let id = parseInt(projInputs[i].value, 10);
if (!isNaN(id)) {
assignedIds.push(id);
}
}
if (projectIds.length != assignedIds.length) {
projectsChanged = true;
} else {
for (let i = 0; i < projectIds.length; ++i) {
let found = false;
for (let j = 0; j < assignedIds.length; ++j) {
if (projectIds[i] == assignedIds[j]) {
found = true;
}
}
if (!found) {
projectsChanged = true;
break;
}
}
}
if (originalSnippetEl && (!attachmentChanged && originalText == snippetEdit.text.value.trim() && !projectsChanged)) {
// NOTE(asaf): We're in edit mode and nothing changed, so no need to submit to the server.
ev.preventDefault();
cancel();
}
});
snippetEdit.deleteButton.addEventListener("click", function (ev) {
if (!window.confirm("Are you sure you want to delete this snippet?")) {
ev.preventDefault();
return;
}
snippetEdit.file.value = "";
});
validate();
return snippetEdit;
}
function editTimelineSnippet(timelineItemEl, stickyProjectId) {
let ownerName = timelineItemEl.querySelector(".user")?.textContent;
let ownerUrl = timelineItemEl.querySelector(".user")?.href;
let ownerAvatar = timelineItemEl.querySelector(".avatar")?.src;
let creationDate = new Date(timelineItemEl.querySelector("time").dateTime);
let rawDesc = timelineItemEl.querySelector(".rawdesc").textContent;
let attachment = timelineItemEl.querySelector(".timeline-media")?.children?.[0];
let projectIds = [];
let projectEls = timelineItemEl.querySelectorAll(".projects > a");
for (let i = 0; i < projectEls.length; ++i) {
let projid = projectEls[i].getAttribute("data-projid");
if (projid) {
projectIds.push(projid);
}
}
let snippetEdit = makeSnippetEdit(ownerName, ownerAvatar, ownerUrl, creationDate, rawDesc, attachment, projectIds, stickyProjectId, timelineItemEl.getAttribute("data-id"), timelineItemEl);
timelineItemEl.parentElement.insertBefore(snippetEdit.root, timelineItemEl);
timelineItemEl.remove();
}

View File

@ -1,106 +1,38 @@
function TabState(tabbed) {
this.container = tabbed;
this.tabs = tabbed.querySelector(".tab");
function initTabs(container, {
initialTab = null,
onSelect = (name) => {},
}) {
const buttons = Array.from(container.querySelectorAll("[data-tab-button]"));
const tabs = Array.from(container.querySelectorAll("[data-tab]"));
this.tabbar = document.createElement("div");
this.tabbar.classList.add("tab-bar");
this.container.insertBefore(this.tabbar, this.container.firstChild);
const firstTab = tabs[0].getAttribute("data-tab");
this.current_i = -1;
this.tab_buttons = [];
}
function switch_tab_old(state, tab_i) {
return function() {
if (state.current_i >= 0) {
state.tabs[state.current_i].classList.add("hidden");
state.tab_buttons[state.current_i].classList.remove("current");
function selectTab(name, { sendEvent = true } = {}) {
if (!document.querySelector(`[data-tab="${name}"]`)) {
console.warn("no tab found with name", name);
return selectTab(firstTab, initial);
}
state.tabs[tab_i].classList.remove("hidden");
state.tab_buttons[tab_i].classList.add("current");
var hash = "";
if (state.tabs[tab_i].hasAttribute("data-url-hash")) {
hash = state.tabs[tab_i].getAttribute("data-url-hash");
for (const tab of tabs) {
tab.hidden = tab.getAttribute("data-tab") !== name;
}
for (const button of buttons) {
button.classList.toggle("tab-button-active", button.getAttribute("data-tab-button") === name);
}
window.location.hash = hash;
state.current_i = tab_i;
if (sendEvent) {
onSelect(name);
}
}
selectTab(initialTab || firstTab, { sendEvent: false });
for (const button of buttons) {
button.addEventListener("click", () => {
selectTab(button.getAttribute("data-tab-button"));
});
}
return {
selectTab,
};
}
document.addEventListener("DOMContentLoaded", function() {
const tabContainers = document.getElementsByClassName("tabbed");
for (const container of tabContainers) {
const tabBar = document.createElement("div");
tabBar.classList.add("tab-bar");
container.insertAdjacentElement('afterbegin', tabBar);
const tabs = container.querySelectorAll(".tab");
for (let i = 0; i < tabs.length; i++) {
const tab = tabs[i];
tab.classList.toggle('dn', i > 0);
const slug = tab.getAttribute("data-slug");
// TODO: Should this element be a link?
const tabButton = document.createElement("div");
tabButton.classList.add("tab-button");
tabButton.classList.toggle("current", i === 0);
tabButton.innerText = tab.getAttribute("data-name");
tabButton.setAttribute("data-slug", slug);
tabButton.addEventListener("click", () => {
switchTab(container, slug);
});
tabBar.appendChild(tabButton);
}
const initialSlug = window.location.hash;
if (initialSlug) {
switchTab(container, initialSlug.substring(1));
}
}
});
function switchTab(container, slug) {
const tabs = container.querySelectorAll('.tab');
let didMatch = false;
for (const tab of tabs) {
const slugMatches = tab.getAttribute("data-slug") === slug;
tab.classList.toggle('dn', !slugMatches);
if (slugMatches) {
didMatch = true;
}
}
const tabButtons = document.querySelectorAll(".tab-button");
for (const tabButton of tabButtons) {
const buttonSlug = tabButton.getAttribute("data-slug");
tabButton.classList.toggle('current', slug === buttonSlug);
}
if (!didMatch) {
// switch to first tab as a fallback
tabs[0].classList.remove('dn');
tabButtons[0].classList.add('current');
}
window.location.hash = slug;
}
function switchToTabOfElement(container, el) {
const tabs = Array.from(container.querySelectorAll('.tab'));
let target = el.parentElement;
while (target) {
if (tabs.includes(target)) {
switchTab(container, target.getAttribute("data-slug"));
return;
}
target = target.parentElement;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 236 253" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="books" x="0" y="0" width="235.74" height="252.97" style="fill:none;"/><path d="M77.61,252.704l0,-230.569l80.52,-0l-0,230.569l-80.52,0Zm59.686,-188.853l0,-20.883l-38.853,-0l0,20.883l38.853,0Zm0,128.926l0,-108.092l-38.853,-0l0,108.092l38.853,-0Zm-38.853,20.833l0,18.261l38.853,-0l0,-18.261l-38.853,0Zm-98.032,39.094l-0,-252.438l70.429,-0l-0,252.438l-70.429,0Zm49.596,-206.372l-0,-25.233l-28.763,-0l0,25.233l28.763,0Zm-0,142.369l-0,-121.536l-28.763,0l0,121.536l28.763,-0Zm-28.763,20.833l0,22.337c0,-0 28.763,-0 28.763,-0l-0,-22.337l-28.763,-0Zm143.656,43.17l-0,-252.438l70.429,-0l-0,252.438l-70.429,0Zm49.596,-206.372l-0,-25.233l-28.763,-0l0,25.233l28.763,0Zm-0,142.369l-0,-121.536l-28.763,0l0,121.536l28.763,-0Zm-28.763,20.833l0,22.337l28.763,-0l-0,-22.337l-28.763,-0Z"/></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 336 233" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="lightbulb" x="0" y="0" width="335.159" height="232.656" style="fill:none;"/><path d="M197.613,202.015c0,16.576 -13.457,30.034 -30.034,30.034c-16.576,-0 -30.034,-13.458 -30.034,-30.034l60.068,-0Zm0.06,-9.97l-60.206,-0c-3.155,-16.04 -5.152,-23.793 -32.39,-57.373c-10.513,-12.96 -16.178,-29.812 -16.178,-47.773c0,-43.425 35.256,-78.68 78.68,-78.68c43.425,-0 78.68,34.8 78.68,78.224c0,17.961 -5.665,34.814 -16.177,47.774c-27.238,33.58 -29.254,41.788 -32.409,57.828Zm-16.343,-20.834c3.88,-11.276 11.569,-24.225 32.572,-50.118c7.611,-9.383 11.524,-21.647 11.524,-34.65c-0,-31.893 -25.954,-57.391 -57.847,-57.391c-31.926,0 -57.846,25.92 -57.846,57.847c-0,13.003 3.913,25.266 11.524,34.649c20.946,25.823 28.639,38.556 32.521,49.663l27.552,0Zm-160.921,-151.684c-4.694,-3.321 -5.808,-9.827 -2.488,-14.52c3.321,-4.693 9.827,-5.808 14.52,-2.488l31.239,22.101c4.694,3.321 5.808,9.827 2.488,14.52c-3.32,4.693 -9.827,5.808 -14.52,2.488l-31.239,-22.101Zm12.032,153.97c-4.693,3.32 -11.199,2.205 -14.52,-2.488c-3.32,-4.693 -2.206,-11.199 2.488,-14.52l31.239,-22.101c4.693,-3.32 11.2,-2.205 14.52,2.488c3.32,4.693 2.206,11.199 -2.488,14.52l-31.239,22.101Zm-21.856,-74.77c-5.749,-0 -10.416,-4.668 -10.416,-10.417c-0,-5.749 4.667,-10.417 10.416,-10.417l38.267,0c5.749,0 10.417,4.668 10.417,10.417c-0,5.749 -4.668,10.417 -10.417,10.417l-38.267,-0Zm292.133,-95.906c4.693,-3.32 11.199,-2.205 14.519,2.488c3.321,4.693 2.206,11.199 -2.487,14.52l-31.239,22.101c-4.694,3.32 -11.2,2.206 -14.52,-2.488c-3.321,-4.693 -2.206,-11.199 2.487,-14.52l31.24,-22.101Zm12.032,153.97c4.693,3.321 5.808,9.827 2.487,14.52c-3.32,4.694 -9.826,5.808 -14.519,2.488l-31.24,-22.101c-4.693,-3.321 -5.808,-9.827 -2.487,-14.52c3.32,-4.693 9.826,-5.808 14.52,-2.488l31.239,22.101Zm9.823,-78.595c5.75,-0 10.417,4.667 10.417,10.416c0,5.749 -4.667,10.417 -10.417,10.417l-38.266,-0c-5.75,-0 -10.417,-4.668 -10.417,-10.417c-0,-5.749 4.667,-10.416 10.417,-10.416l38.266,-0Z"/></svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 301 229" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><rect id="presentation" x="-0" y="0" width="300.716" height="228.578" style="fill:none;"/><path d="M124.979,14.95l175.159,0l0,152.429l-137.896,0c-1.49,-7.262 -3.898,-14.19 -7.097,-20.659l124.334,-0l-0,-111.11l-143.514,-0c-2.302,-7.632 -6.074,-14.628 -10.986,-20.66Zm-119.77,196.191c-2.997,-8.252 -4.631,-17.155 -4.631,-26.437c0,-42.797 34.745,-77.542 77.541,-77.542c42.796,0 77.541,34.745 77.541,77.542c0,9.282 -1.634,18.185 -4.631,26.437c-22.091,10.548 -46.816,16.455 -72.91,16.455c-26.094,0 -50.819,-5.907 -72.91,-16.455Zm15.522,-13.612c17.693,7.296 37.075,11.317 57.388,11.317c20.314,0 39.695,-4.021 57.389,-11.317c0.919,-4.129 1.402,-8.421 1.402,-12.825c0,-32.448 -26.343,-58.792 -58.791,-58.792c-32.448,0 -58.791,26.344 -58.791,58.792c0,4.404 0.484,8.696 1.403,12.825Zm57.388,-196.547c28.741,-0 52.075,23.334 52.075,52.074c-0,28.741 -23.334,52.075 -52.075,52.075c-28.74,-0 -52.074,-23.334 -52.074,-52.075c-0,-28.74 23.334,-52.074 52.074,-52.074Zm0,18.75c-18.392,-0 -33.324,14.932 -33.324,33.324c-0,18.392 14.932,33.325 33.324,33.325c18.392,-0 33.325,-14.933 33.325,-33.325c-0,-18.392 -14.933,-33.324 -33.325,-33.324Z"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,306 +0,0 @@
/*
Inserts a CSS expression with one or more custom variables.
You can provide an arbitrary number of strings in the second
argument, separated by spaces. Any strings corresponding to
variable names will be replaced by the correct values, while
other strings are left untouched.
Example usage:
@include usevar(border-color, dimmer-color);
@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")");
For clarity and to avoid syntax issues, you are encouraged to
use unquoted strings for variables and quoted strings for
everything else.
For convenience in common cases, if only a single argument
is provided and it does not match an existing variable, this
will throw an error.
*/
pre, code, .codeblock {
/* Comment */
/* Error */
/* Keyword */
/* Literal */
/* Name */
/* Operator */
/* Punctuation */
/* Comment.Multiline */
/* Comment.Preproc */
/* Comment.Single */
/* Comment.Special */
/* Generic.Emph */
/* Generic.Strong */
/* Keyword.Constant */
/* Keyword.Declaration */
/* Keyword.Namespace */
/* Keyword.Pseudo */
/* Keyword.Reserved */
/* Keyword.Type */
/* Literal.Date */
/* Literal.Number */
/* Literal.String */
/* Name.Attribute */
/* Name.Builtin */
/* Name.Class */
/* Name.Constant */
/* Name.Decorator */
/* Name.Entity */
/* Name.Exception */
/* Name.Function */
/* Name.Label */
/* Name.Namespace */
/* Name.Other */
/* Name.Property */
/* Name.Tag */
/* Name.Variable */
/* Operator.Word */
/* Text.Whitespace */
/* Literal.Number.Float */
/* Literal.Number.Hex */
/* Literal.Number.Integer */
/* Literal.Number.Oct */
/* Literal.String.Backtick */
/* Literal.String.Char */
/* Literal.String.Doc */
/* Literal.String.Double */
/* Literal.String.Escape */
/* Literal.String.Heredoc */
/* Literal.String.Interpol */
/* Literal.String.Other */
/* Literal.String.Regex */
/* Literal.String.Single */
/* Literal.String.Symbol */
/* Name.Builtin.Pseudo */
/* Name.Variable.Class */
/* Name.Variable.Global */
/* Name.Variable.Instance */
/* Literal.Number.Integer.Long */
/* Generic Heading & Diff Header */
/* Generic.Subheading & Diff Unified/Comment? */
/* Generic.Deleted & Diff Deleted */
/* Generic.Inserted & Diff Inserted */ }
pre .hll, code .hll, .codeblock .hll {
background-color: #49483e; }
pre .c, code .c, .codeblock .c {
color: #75715e; }
pre .err, code .err, .codeblock .err {
color: #ff0000; }
pre .k, code .k, .codeblock .k {
color: #66d9ef; }
pre .l, code .l, .codeblock .l {
color: #ae81ff; }
pre .n, code .n, .codeblock .n {
color: #f8f8f2; }
pre .o, code .o, .codeblock .o {
color: #f92672; }
pre .p, code .p, .codeblock .p {
color: #f8f8f2; }
pre .cm, code .cm, .codeblock .cm {
color: #75715e; }
pre .cp, code .cp, .codeblock .cp {
color: #75715e; }
pre .c1, code .c1, .codeblock .c1 {
color: #75715e; }
pre .cs, code .cs, .codeblock .cs {
color: #75715e; }
pre .ge, code .ge, .codeblock .ge {
font-style: italic; }
pre .gs, code .gs, .codeblock .gs {
font-weight: bold; }
pre .kc, code .kc, .codeblock .kc {
color: #66d9ef; }
pre .kd, code .kd, .codeblock .kd {
color: #66d9ef; }
pre .kn, code .kn, .codeblock .kn {
color: #f92672; }
pre .kp, code .kp, .codeblock .kp {
color: #66d9ef; }
pre .kr, code .kr, .codeblock .kr {
color: #66d9ef; }
pre .kt, code .kt, .codeblock .kt {
color: #66d9ef; }
pre .ld, code .ld, .codeblock .ld {
color: #e6db74; }
pre .m, code .m, .codeblock .m {
color: #ae81ff; }
pre .s, code .s, .codeblock .s {
color: #e6db74; }
pre .na, code .na, .codeblock .na {
color: #a6e22e; }
pre .nb, code .nb, .codeblock .nb {
color: #f8f8f2; }
pre .nc, code .nc, .codeblock .nc {
color: #a6e22e; }
pre .no, code .no, .codeblock .no {
color: #66d9ef; }
pre .nd, code .nd, .codeblock .nd {
color: #a6e22e; }
pre .ni, code .ni, .codeblock .ni {
color: #f8f8f2; }
pre .ne, code .ne, .codeblock .ne {
color: #a6e22e; }
pre .nf, code .nf, .codeblock .nf {
color: #a6e22e; }
pre .nl, code .nl, .codeblock .nl {
color: #f8f8f2; }
pre .nn, code .nn, .codeblock .nn {
color: #f8f8f2; }
pre .nx, code .nx, .codeblock .nx {
color: #a6e22e; }
pre .py, code .py, .codeblock .py {
color: #f8f8f2; }
pre .nt, code .nt, .codeblock .nt {
color: #f92672; }
pre .nv, code .nv, .codeblock .nv {
color: #f8f8f2; }
pre .ow, code .ow, .codeblock .ow {
color: #f92672; }
pre .w, code .w, .codeblock .w {
color: #f8f8f2; }
pre .mf, code .mf, .codeblock .mf {
color: #ae81ff; }
pre .mh, code .mh, .codeblock .mh {
color: #ae81ff; }
pre .mi, code .mi, .codeblock .mi {
color: #ae81ff; }
pre .mo, code .mo, .codeblock .mo {
color: #ae81ff; }
pre .sb, code .sb, .codeblock .sb {
color: #e6db74; }
pre .sc, code .sc, .codeblock .sc {
color: #e6db74; }
pre .sd, code .sd, .codeblock .sd {
color: #e6db74; }
pre .s2, code .s2, .codeblock .s2 {
color: #e6db74; }
pre .se, code .se, .codeblock .se {
color: #ae81ff; }
pre .sh, code .sh, .codeblock .sh {
color: #e6db74; }
pre .si, code .si, .codeblock .si {
color: #e6db74; }
pre .sx, code .sx, .codeblock .sx {
color: #e6db74; }
pre .sr, code .sr, .codeblock .sr {
color: #e6db74; }
pre .s1, code .s1, .codeblock .s1 {
color: #e6db74; }
pre .ss, code .ss, .codeblock .ss {
color: #e6db74; }
pre .bp, code .bp, .codeblock .bp {
color: #f8f8f2; }
pre .vc, code .vc, .codeblock .vc {
color: #f8f8f2; }
pre .vg, code .vg, .codeblock .vg {
color: #f8f8f2; }
pre .vi, code .vi, .codeblock .vi {
color: #f8f8f2; }
pre .il, code .il, .codeblock .il {
color: #ae81ff; }
pre .gu, code .gu, .codeblock .gu {
color: #75715e; }
pre .gd, code .gd, .codeblock .gd {
color: #f92672; }
pre .gi, code .gi, .codeblock .gi {
color: #a6e22e; }
.light {
background-color: #fff;
color: #000; }
:root {
--fg-font-color: #eee;
--theme-color: #666;
--theme-color-dim: #444;
--theme-color-dimmer: #383838;
--theme-color-dimmest: #333;
--link-color: #aaa;
--link-border-color: #aaa;
--hr-color: #aaa;
--main-background-color: #202020;
--main-color: #eee;
--dim-color: #bbb;
--dimmer-color: #999;
--dimmest-color: #777;
--menu-bottom-border-color: #444;
--login-popup-background: #181818;
--content-background: #202020;
--content-background-transparent: rgba(32, 32, 32, 0);
--dim-background: #252525;
--dim-background-transparent: rgba(37, 37, 37, 0);
--text-background: #181818;
--spoiler-border: #777;
--background-even-background: #242424;
--project-card-border-color: #333;
--project-user-suggestions-background: #222;
--project-user-suggestions-border-color: #444;
--notice-text-color: #eee;
--notice-unapproved-color: #7a2020;
--notice-hidden-color: #494949;
--notice-hiatus-color: #876327;
--notice-dead-color: #7a2020;
--notice-lts-color: #2a681d;
--notice-lts-reqd-color: #876327;
--notice-success-color: #2a681d;
--notice-warn-color: #876327;
--notice-failure-color: #7a2020;
--optionbar-border-color: #333;
--tab-background: #181818;
--tab-border-color: #3f3f3f;
--tab-button-background: #303030;
--tab-button-background-hover: #383838;
--tab-button-background-current: #181818;
--form-check-background: #252527;
--form-check-border-color: #666;
--form-check-border-color-hover: #084068;
--form-text-background: #181818;
--form-text-background-active: #252527;
--form-text-border-color: #444;
--form-text-border-color-active: #084068;
--form-button-color: #999;
--form-button-color-active: #4c9ed9;
--form-button-background: #383838;
--form-button-background-active: #303840;
--form-button-border-color: transparent;
--form-button-inline-border-color: transparent;
--form-error-color: #c61d24;
--landing-search-background: #282828;
--landing-search-background-hover: #181818;
--editor-toolbar-background: #282828;
--editor-toolbar-border-color: #333;
--editor-toolbar-button-background: 282828;
--editor-toolbar-button-background-hover: #333;
--editor-toolbar-button-border-color: #333;
--post-blockquote-border-color: #555;
--forum-even-background: #242424;
--forum-thread-read-color: #777;
--forum-thread-read-link-color: #999;
--forum-post-author-color: #999;
--forum-diff-source-background: #181818;
--forum-diff-source-border-color: #444;
--forum-diff-replace-background: #18283a;
--forum-diff-replace-border-color: #223d5b;
--forum-diff-delete-background: #3a1818;
--forum-diff-delete-border-color: #6b1e1c;
--forum-diff-insert-background: #233a18;
--forum-diff-insert-border-color: #30591b;
--card-background: #282828;
--card-background-hover: #333;
--irc-border-color: #333;
--irc-tab-current-shadow: 0px 0px 5px #000 inset;
--irc-tab-close-button-color: #bbb;
--irc-tab-close-button-background: #444;
--irc-nick-border-color: #444;
--irc-users-color: #aaa;
--irc-users-background: #181818;
--irc-users-border-color: transparent;
--irc-users-popout-background: #181818;
--irc-users-popout-border-color-left: #444;
--irc-users-popout-border-color-right: #333;
--code-line-number-color: #444;
--library-star-btn-background: #252525;
--library-star-btn-border-color: #bbb;
--library-star-btn-a-border-color: #999;
--library-star-btn-a-hover-background: #333; }

View File

@ -1,324 +0,0 @@
/*
Inserts a CSS expression with one or more custom variables.
You can provide an arbitrary number of strings in the second
argument, separated by spaces. Any strings corresponding to
variable names will be replaced by the correct values, while
other strings are left untouched.
Example usage:
@include usevar(border-color, dimmer-color);
@include usevar(background, "linear-gradient(" dim-background-transparent "," dim-background ")");
For clarity and to avoid syntax issues, you are encouraged to
use unquoted strings for variables and quoted strings for
everything else.
For convenience in common cases, if only a single argument
is provided and it does not match an existing variable, this
will throw an error.
*/
pre, code, .codeblock {
/* Comment */
/* Error */
/* Keyword */
/* Operator */
/* Comment.Multiline */
/* Comment.Preproc */
/* Comment.Single */
/* Comment.Special */
/* Generic.Deleted */
/* Generic.Emph */
/* Generic.Error */
/* Generic.Heading */
/* Generic.Inserted */
/* Generic.Output */
/* Generic.Prompt */
/* Generic.Strong */
/* Generic.Subheading */
/* Generic.Traceback */
/* Keyword.Constant */
/* Keyword.Declaration */
/* Keyword.Namespace */
/* Keyword.Pseudo */
/* Keyword.Reserved */
/* Keyword.Type */
/* Literal.Number */
/* Literal.String */
/* Name.Attribute */
/* Name.Builtin */
/* Name.Class */
/* Name.Constant */
/* Name.Decorator */
/* Name.Entity */
/* Name.Exception */
/* Name.Function */
/* Name.Label */
/* Name.Namespace */
/* Name.Tag */
/* Name.Variable */
/* Operator.Word */
/* Text.Whitespace */
/* Literal.Number.Float */
/* Literal.Number.Hex */
/* Literal.Number.Integer */
/* Literal.Number.Oct */
/* Literal.String.Backtick */
/* Literal.String.Char */
/* Literal.String.Doc */
/* Literal.String.Double */
/* Literal.String.Escape */
/* Literal.String.Heredoc */
/* Literal.String.Interpol */
/* Literal.String.Other */
/* Literal.String.Regex */
/* Literal.String.Single */
/* Literal.String.Symbol */
/* Name.Builtin.Pseudo */
/* Name.Variable.Class */
/* Name.Variable.Global */
/* Name.Variable.Instance */
/* Literal.Number.Integer.Long */ }
pre .hll, code .hll, .codeblock .hll {
background-color: #ffffcc; }
pre .c, code .c, .codeblock .c {
color: #60a0b0;
font-style: italic; }
pre .err, code .err, .codeblock .err {
color: #FF0000; }
pre .k, code .k, .codeblock .k {
color: #007020;
font-weight: bold; }
pre .o, code .o, .codeblock .o {
color: #666666; }
pre .cm, code .cm, .codeblock .cm {
color: #60a0b0;
font-style: italic; }
pre .cp, code .cp, .codeblock .cp {
color: #007020; }
pre .c1, code .c1, .codeblock .c1 {
color: #60a0b0;
font-style: italic; }
pre .cs, code .cs, .codeblock .cs {
color: #60a0b0;
background-color: #fff0f0; }
pre .gd, code .gd, .codeblock .gd {
color: #A00000; }
pre .ge, code .ge, .codeblock .ge {
font-style: italic; }
pre .gr, code .gr, .codeblock .gr {
color: #FF0000; }
pre .gh, code .gh, .codeblock .gh {
color: #000080;
font-weight: bold; }
pre .gi, code .gi, .codeblock .gi {
color: #00A000; }
pre .go, code .go, .codeblock .go {
color: #808080; }
pre .gp, code .gp, .codeblock .gp {
color: #c65d09;
font-weight: bold; }
pre .gs, code .gs, .codeblock .gs {
font-weight: bold; }
pre .gu, code .gu, .codeblock .gu {
color: #800080;
font-weight: bold; }
pre .gt, code .gt, .codeblock .gt {
color: #0040D0; }
pre .kc, code .kc, .codeblock .kc {
color: #007020;
font-weight: bold; }
pre .kd, code .kd, .codeblock .kd {
color: #007020;
font-weight: bold; }
pre .kn, code .kn, .codeblock .kn {
color: #007020;
font-weight: bold; }
pre .kp, code .kp, .codeblock .kp {
color: #007020; }
pre .kr, code .kr, .codeblock .kr {
color: #007020;
font-weight: bold; }
pre .kt, code .kt, .codeblock .kt {
color: #902000; }
pre .m, code .m, .codeblock .m {
color: #40a070; }
pre .s, code .s, .codeblock .s {
color: #4070a0; }
pre .na, code .na, .codeblock .na {
color: #4070a0; }
pre .nb, code .nb, .codeblock .nb {
color: #007020; }
pre .nc, code .nc, .codeblock .nc {
color: #0e84b5;
font-weight: bold; }
pre .no, code .no, .codeblock .no {
color: #60add5; }
pre .nd, code .nd, .codeblock .nd {
color: #555555;
font-weight: bold; }
pre .ni, code .ni, .codeblock .ni {
color: #d55537;
font-weight: bold; }
pre .ne, code .ne, .codeblock .ne {
color: #007020; }
pre .nf, code .nf, .codeblock .nf {
color: #06287e; }
pre .nl, code .nl, .codeblock .nl {
color: #002070;
font-weight: bold; }
pre .nn, code .nn, .codeblock .nn {
color: #0e84b5;
font-weight: bold; }
pre .nt, code .nt, .codeblock .nt {
color: #062873;
font-weight: bold; }
pre .nv, code .nv, .codeblock .nv {
color: #bb60d5; }
pre .ow, code .ow, .codeblock .ow {
color: #007020;
font-weight: bold; }
pre .w, code .w, .codeblock .w {
color: #bbbbbb; }
pre .mf, code .mf, .codeblock .mf {
color: #40a070; }
pre .mh, code .mh, .codeblock .mh {
color: #40a070; }
pre .mi, code .mi, .codeblock .mi {
color: #40a070; }
pre .mo, code .mo, .codeblock .mo {
color: #40a070; }
pre .sb, code .sb, .codeblock .sb {
color: #4070a0; }
pre .sc, code .sc, .codeblock .sc {
color: #4070a0; }
pre .sd, code .sd, .codeblock .sd {
color: #4070a0;
font-style: italic; }
pre .s2, code .s2, .codeblock .s2 {
color: #4070a0; }
pre .se, code .se, .codeblock .se {
color: #4070a0;
font-weight: bold; }
pre .sh, code .sh, .codeblock .sh {
color: #4070a0; }
pre .si, code .si, .codeblock .si {
color: #70a0d0;
font-style: italic; }
pre .sx, code .sx, .codeblock .sx {
color: #c65d09; }
pre .sr, code .sr, .codeblock .sr {
color: #235388; }
pre .s1, code .s1, .codeblock .s1 {
color: #4070a0; }
pre .ss, code .ss, .codeblock .ss {
color: #517918; }
pre .bp, code .bp, .codeblock .bp {
color: #007020; }
pre .vc, code .vc, .codeblock .vc {
color: #bb60d5; }
pre .vg, code .vg, .codeblock .vg {
color: #bb60d5; }
pre .vi, code .vi, .codeblock .vi {
color: #bb60d5; }
pre .il, code .il, .codeblock .il {
color: #40a070; }
.dark {
background-color: #222;
color: #bbb; }
:root {
--fg-font-color: black;
--theme-color: #666;
--theme-color-dim: #aaa;
--theme-color-dimmer: #bbb;
--theme-color-dimmest: #ccc;
--link-color: #666;
--link-border-color: #666;
--hr-color: #444;
--main-background-color: #fff;
--main-color: black;
--dim-color: #333;
--dimmer-color: #999;
--dimmest-color: #bbb;
--menu-bottom-border-color: black;
--login-popup-background: #fbfbfb;
--content-background: #f8f8f8;
--content-background-transparent: rgba(248, 248, 248, 0);
--dim-background: #f0f0f0;
--dim-background-transparent: rgba(240, 240, 240, 0);
--text-background: #f9f9f9;
--spoiler-border: #aaa;
--background-even-background: #f8f8f8;
--project-card-border-color: #aaa;
--project-user-suggestions-background: #fff;
--project-user-suggestions-border-color: #ddd;
--notice-text-color: #fff;
--notice-unapproved-color: #b42222;
--notice-hidden-color: #b6b6b6;
--notice-hiatus-color: #aa7d30;
--notice-dead-color: #b42222;
--notice-lts-color: #43a52f;
--notice-lts-reqd-color: #aa7d30;
--notice-success-color: #43a52f;
--notice-warn-color: #aa7d30;
--notice-failure-color: #b42222;
--optionbar-border-color: #ccc;
--tab-background: #fff;
--tab-border-color: #d8d8d8;
--tab-button-background: #dfdfdf;
--tab-button-background-hover: #efefef;
--tab-button-background-current: #fff;
--form-check-background: #fafafc;
--form-check-border-color: #999;
--form-check-border-color-hover: #4c9ed9;
--form-text-background: #fff;
--form-text-background-active: #fafafc;
--form-text-border-color: #999;
--form-text-border-color-active: #4c9ed9;
--form-button-color: black;
--form-button-color-active: #4c9ed9;
--form-button-background: #fff;
--form-button-background-active: #f2f2f2;
--form-button-border-color: #ccc;
--form-button-inline-border-color: #999;
--form-error-color: #c61d24;
--landing-search-background: #f8f8f8;
--landing-search-background-hover: #fefeff;
--editor-toolbar-background: #fff;
--editor-toolbar-border-color: transparent;
--editor-toolbar-button-background: transparent;
--editor-toolbar-button-background-hover: #ddd;
--editor-toolbar-button-border-color: #ccc;
--post-blockquote-border-color: #ddd;
--forum-even-background: #f0f0f0;
--forum-thread-read-color: #555;
--forum-thread-read-link-color: #888;
--forum-post-author-color: #333;
--forum-diff-source-background: #fff;
--forum-diff-source-border-color: #999;
--forum-diff-replace-background: #adcef4;
--forum-diff-replace-border-color: #4787d1;
--forum-diff-delete-background: #e57979;
--forum-diff-delete-border-color: #c12626;
--forum-diff-insert-background: #96e579;
--forum-diff-insert-border-color: #5baa3f;
--card-background: #e8e8e8;
--card-background-hover: #f0f0f0;
--irc-border-color: #ddd;
--irc-tab-current-shadow: 0px 0px 5px #bbb inset;
--irc-tab-close-button-color: #fff;
--irc-tab-close-button-background: #aaa;
--irc-nick-border-color: #ccc;
--irc-users-color: black;
--irc-users-background: #fff;
--irc-users-border-color: #ccc;
--irc-users-popout-background: #fff;
--irc-users-popout-border-color-left: #bbb;
--irc-users-popout-border-color-right: #ccc;
--code-line-number-color: #777;
--library-star-btn-background: #fff;
--library-star-btn-border-color: #999;
--library-star-btn-a-border-color: #aaa;
--library-star-btn-a-hover-background: #fafafa; }

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 423 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 461 280" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;">
<g id="Layer1">
</g>
<circle cx="56.5" cy="200.5" r="22.5" style="fill:white;"/>
<circle cx="101.5" cy="147.5" r="22.5" style="fill:white;"/>
<circle cx="183.5" cy="188.5" r="22.5" style="fill:white;"/>
<circle cx="183.5" cy="97.5" r="22.5" style="fill:white;"/>
<circle cx="83.5" cy="52.5" r="22.5" style="fill:white;"/>
<path d="M83.948,51.442L101.948,146.442" style="fill:none;fill-rule:nonzero;stroke:white;stroke-width:6px;"/>
<path d="M53.713,198.058L98.713,145.058" style="fill:none;fill-rule:nonzero;stroke:white;stroke-width:6px;"/>
<path d="M183.59,99.544L103.59,149.544" style="fill:none;fill-rule:nonzero;stroke:white;stroke-width:6px;"/>
<path d="M181.645,190.677L100.645,149.677" style="fill:none;fill-rule:nonzero;stroke:white;stroke-width:6px;"/>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,457,-385)">
<path d="M442,41C442,38.24 439.76,36 437,36L426,36C423.24,36 421,38.24 421,41L421,85C421,87.76 423.24,90 426,90L437,90C439.76,90 442,87.76 442,85L442,41Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,426,-296)">
<path d="M382,70C382,67.24 379.76,65 377,65L366,65C363.24,65 361,67.24 361,70L361,114C361,116.76 363.24,119 366,119L377,119C379.76,119 382,116.76 382,114L382,70Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,486,-356)">
<path d="M442,70C442,67.24 439.76,65 437,65L426,65C423.24,65 421,67.24 421,70L421,159C421,161.76 423.24,164 426,164L437,164C439.76,164 442,161.76 442,159L442,70Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,455,-267)">
<path d="M382,99C382,96.24 379.76,94 377,94L366,94C363.24,94 361,96.24 361,99L361,188C361,190.76 363.24,193 366,193L377,193C379.76,193 382,190.76 382,188L382,99Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,515,-327)">
<path d="M442,99C442,96.24 439.76,94 437,94L426,94C423.24,94 421,96.24 421,99L421,158C421,160.76 423.24,163 426,163L437,163C439.76,163 442,160.76 442,158L442,99Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,484,-238)">
<path d="M382,128C382,125.24 379.76,123 377,123L366,123C363.24,123 361,125.24 361,128L361,187C361,189.76 363.24,192 366,192L377,192C379.76,192 382,189.76 382,187L382,128Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,544,-298)">
<path d="M442,128C442,125.24 439.76,123 437,123L426,123C423.24,123 421,125.24 421,128L421,238C421,240.76 423.24,243 426,243L437,243C439.76,243 442,240.76 442,238L442,128Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,513,-209)">
<path d="M382,157C382,154.24 379.76,152 377,152L366,152C363.24,152 361,154.24 361,157L361,267C361,269.76 363.24,272 366,272L377,272C379.76,272 382,269.76 382,267L382,157Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,573,-269)">
<path d="M442,157C442,154.24 439.76,152 437,152L426,152C423.24,152 421,154.24 421,157L421,187C421,189.76 423.24,192 426,192L437,192C439.76,192 442,189.76 442,187L442,157Z" style="fill:white;"/>
</g>
<g transform="matrix(-3.82857e-16,1,-1,-3.82857e-16,542,-180)">
<path d="M382,186C382,183.24 379.76,181 377,181L366,181C363.24,181 361,183.24 361,186L361,216C361,218.76 363.24,221 366,221L377,221C379.76,221 382,218.76 382,216L382,186Z" style="fill:white;"/>
</g>
<path d="M461,21.739C461,9.741 451.259,0 439.261,0L21.739,0C9.741,0 0,9.741 0,21.739L0,258.261C0,270.259 9.741,280 21.739,280L439.261,280C451.259,280 461,270.259 461,258.261L461,21.739ZM447,21.739L447,258.261C447,262.532 443.532,266 439.261,266C439.261,266 21.739,266 21.739,266C17.468,266 14,262.532 14,258.261L14,21.739C14,17.468 17.468,14 21.739,14L439.261,14C443.532,14 447,17.468 447,21.739Z" style="fill:white;"/>
<g transform="matrix(2.90789,0,0,1.65,-31.7105,-153.4)">
<rect x="14" y="236" width="152" height="20" style="fill:white;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
public/visjam2023/memer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

BIN
public/visjam2023/npm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 200 KiB

BIN
public/visjam2023/rede.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

BIN
public/visjam2023/spall.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 KiB

Binary file not shown.

BIN
public/visjam2023/v8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

BIN
public/visjam2023/vmmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 KiB

163
public/visjam2024/logo.svg Normal file
View File

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="739.32581"
height="447.97736"
viewBox="0 0 195.61328 118.52734"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><g
id="layer2"
transform="translate(-6.5429683,-7.9628906)"><g
id="g88"><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 13.785156,7.9628906 c -3.9914079,0 -7.2421873,3.2507794 -7.2421873,7.2421874 V 119.24805 c 0,3.99141 3.2507794,7.24218 7.2421873,7.24218 H 194.91406 c 3.99141,0 7.24219,-3.25077 7.24219,-7.24218 V 15.205078 c 0,-3.991408 -3.25078,-7.2421874 -7.24219,-7.2421874 z m 0,2.3808594 H 194.91406 c 2.71339,0 4.86133,2.147942 4.86133,4.861328 V 119.24805 c 0,2.71338 -2.14794,4.86132 -4.86133,4.86133 H 13.785156 c -2.713386,0 -4.8613279,-2.14795 -4.8613279,-4.86133 V 15.205078 c 0,-2.713386 2.1479419,-4.861328 4.8613279,-4.861328 z"
id="rect1" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 8.1660156,112.96094 a 1.190625,1.190625 0 0 0 -1.1914062,1.1914 1.190625,1.190625 0 0 0 1.1914062,1.18946 H 200.73633 a 1.190625,1.190625 0 0 0 1.1914,-1.18946 1.190625,1.190625 0 0 0 -1.1914,-1.1914 z"
id="path36" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 180.14453,118.25195 a 1.190625,1.190625 0 0 0 -1.18945,1.19141 1.190625,1.190625 0 0 0 1.18945,1.19141 h 8.94922 a 1.190625,1.190625 0 0 0 1.19141,-1.19141 1.190625,1.190625 0 0 0 -1.19141,-1.19141 z"
id="path37" /></g><g
id="g89"><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 39.162109,38.353516 -2.21875,0.867187 6.207032,15.861328 2.216796,-0.867187 z"
id="path3" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 38.902344,80.289062 -4.63086,5.419922 1.808594,1.546875 4.632813,-5.419922 z"
id="path4" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 64.087891,75.970703 -1.189454,2.0625 12.404297,7.154297 1.189453,-2.064453 z"
id="path5" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 74.726562,52.677734 -12.070312,7.365235 1.240234,2.033203 12.070313,-7.365235 z"
id="path2" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 83.150391,38.503906 c -5.744916,0 -10.427735,4.682819 -10.427735,10.427735 0,5.744915 4.682819,10.427734 10.427735,10.427734 5.744915,0 10.427734,-4.682819 10.427734,-10.427734 0,-5.744916 -4.682819,-10.427735 -10.427734,-10.427735 z m 0,2.38086 c 4.457993,0 8.046875,3.588881 8.046875,8.046875 0,4.457993 -3.588882,8.046875 -8.046875,8.046875 -4.457994,0 -8.044922,-3.588882 -8.044922,-8.046875 0,-4.457994 3.586928,-8.046875 8.044922,-8.046875 z"
id="use16" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 83.757812,78.259766 c -5.744915,0 -10.427734,4.682819 -10.427734,10.427734 0,5.744915 4.682819,10.427734 10.427734,10.427734 5.744916,0 10.427735,-4.682819 10.427735,-10.427734 0,-5.744915 -4.682819,-10.427734 -10.427735,-10.427734 z m 0,2.380859 c 4.457994,0 8.046875,3.588881 8.046875,8.046875 0,4.457994 -3.588881,8.044922 -8.046875,8.044922 -4.457993,0 -8.046875,-3.586928 -8.046875,-8.044922 0,-4.457994 3.588882,-8.046875 8.046875,-8.046875 z"
id="use17" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 29.087891,83.179687 c -5.744916,0 -10.427735,4.682819 -10.427735,10.427735 0,5.744915 4.682819,10.427738 10.427735,10.427738 5.744915,0 10.427734,-4.682823 10.427734,-10.427738 0,-5.744916 -4.682819,-10.427735 -10.427734,-10.427735 z m 0,2.38086 c 4.457993,0 8.044921,3.588881 8.044921,8.046875 0,4.457994 -3.586928,8.044918 -8.044921,8.044918 -4.457994,0 -8.046875,-3.586924 -8.046875,-8.044918 0,-4.457994 3.588881,-8.046875 8.046875,-8.046875 z"
id="use18" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 34.621094,19.585937 c -5.744916,0 -10.427735,4.682819 -10.427735,10.427735 0,5.744915 4.682819,10.427734 10.427735,10.427734 5.744915,0 10.425781,-4.682819 10.425781,-10.427734 0,-5.744916 -4.680866,-10.427735 -10.425781,-10.427735 z m 0,2.382813 c 4.457994,0 8.044922,3.586928 8.044922,8.044922 0,4.457994 -3.586928,8.046875 -8.044922,8.046875 -4.457994,0 -8.046875,-3.588881 -8.046875,-8.046875 0,-4.457994 3.588881,-8.044922 8.046875,-8.044922 z"
id="use83" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 49.949219,55.927734 c -7.313646,0 -13.265625,5.951979 -13.265625,13.265625 0,7.313646 5.951979,13.265625 13.265625,13.265625 7.313646,0 13.265625,-5.951979 13.265625,-13.265625 0,-7.313646 -5.951979,-13.265625 -13.265625,-13.265625 z m 0,2.117188 c 6.169714,0 11.148437,4.978724 11.148437,11.148437 0,6.169714 -4.978723,11.148438 -11.148437,11.148438 -6.169714,0 -11.148438,-4.978724 -11.148438,-11.148438 0,-6.169713 4.978724,-11.148437 11.148438,-11.148437 z"
id="use84" /></g><g
id="g90"><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 127.79297,52.058594 v 2.380859 H 158.75 v -2.380859 z"
id="path61" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 171.97852,52.058594 v 2.380859 h 13.23046 v -2.380859 z"
id="path62" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 167.48047,40.416016 v 2.380859 h 17.72851 v -2.380859 z"
id="path63" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 138.90625,64.757812 v 2.38086 h 44.18555 v -2.38086 z"
id="path64" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 119.85547,76.929687 v 2.38086 h 19.05078 v -2.38086 z"
id="path65" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 174.0957,28.246094 v 2.380859 h 11.11328 v -2.380859 z"
id="path66" /><path
style="color:#000000;fill:#ffffff;stroke-dashoffset:8.8;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 158.75,89.628906 v 2.38086 h 11.11328 v -2.38086 z"
id="path67" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 171.97852,25.765625 c -2.01296,0 -3.66993,1.656968 -3.66993,3.669922 0,2.012954 1.65697,3.671875 3.66993,3.671875 2.01295,0 3.67187,-1.658921 3.67187,-3.671875 0,-2.012954 -1.65892,-3.669922 -3.67187,-3.669922 z m 0,2.380859 c 0.72603,0 1.28906,0.56303 1.28906,1.289063 0,0.726032 -0.56303,1.289062 -1.28906,1.289062 -0.72604,0 -1.28907,-0.56303 -1.28907,-1.289062 0,-0.726033 0.56303,-1.289063 1.28907,-1.289063 z"
id="use67" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 165.36523,37.9375 c -2.01295,0 -3.67187,1.656968 -3.67187,3.669922 0,2.012954 1.65892,3.669922 3.67187,3.669922 2.01296,0 3.66993,-1.656968 3.66993,-3.669922 0,-2.012954 -1.65697,-3.669922 -3.66993,-3.669922 z m 0,2.380859 c 0.72604,0 1.28907,0.56303 1.28907,1.289063 0,0.726032 -0.56303,1.289062 -1.28907,1.289062 -0.72603,0 -1.28906,-0.56303 -1.28906,-1.289062 0,-0.726033 0.56303,-1.289063 1.28906,-1.289063 z"
id="use68" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 185.20898,62.279297 c -2.01295,0 -3.67187,1.656968 -3.67187,3.669922 0,2.012954 1.65892,3.669922 3.67187,3.669922 2.01296,0 3.66993,-1.656968 3.66993,-3.669922 0,-2.012954 -1.65697,-3.669922 -3.66993,-3.669922 z m 0,2.380859 c 0.72604,0 1.28907,0.56303 1.28907,1.289063 0,0.726032 -0.56303,1.289062 -1.28907,1.289062 -0.72603,0 -1.28906,-0.56303 -1.28906,-1.289062 0,-0.726033 0.56303,-1.289063 1.28906,-1.289063 z"
id="use70" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 117.74023,74.449219 c -2.01295,0 -3.67187,1.656968 -3.67187,3.669922 0,2.012954 1.65892,3.669921 3.67187,3.669921 2.01296,0 3.66993,-1.656967 3.66993,-3.669921 0,-2.012954 -1.65697,-3.669922 -3.66993,-3.669922 z m 0,2.380859 c 0.72604,0 1.28907,0.56303 1.28907,1.289063 0,0.726032 -0.56303,1.289062 -1.28907,1.289062 -0.72603,0 -1.28906,-0.56303 -1.28906,-1.289062 0,-0.726033 0.56303,-1.289063 1.28906,-1.289063 z"
id="use71" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 171.97852,87.173828 c -2.01296,0 -3.66993,1.656968 -3.66993,3.669922 0,2.012954 1.65697,3.669922 3.66993,3.669922 2.01295,0 3.67187,-1.656968 3.67187,-3.669922 0,-2.012954 -1.65892,-3.669922 -3.67187,-3.669922 z m 0,2.380859 c 0.72603,0 1.28906,0.563031 1.28906,1.289063 0,0.726032 -0.56303,1.289062 -1.28906,1.289062 -0.72604,0 -1.28907,-0.56303 -1.28907,-1.289062 0,-0.726032 0.56303,-1.289062 1.28907,-1.289063 z"
id="use72" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use73"
width="5.3566022"
height="5.3566022"
x="149.09836"
y="-112.82577"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use74"
width="5.3566022"
height="5.3566022"
x="157.70444"
y="-104.21969"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use75"
width="5.3566022"
height="5.3566022"
x="166.31052"
y="-95.613609"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use76"
width="5.3566022"
height="5.3566022"
x="147.22748"
y="-77.278923"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use77"
width="5.3566022"
height="5.3566022"
x="131.384"
y="-77.899246"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use78"
width="5.3566022"
height="5.3566022"
x="150.78217"
y="-45.660938"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use79"
width="5.3566022"
height="5.3566022"
x="142.17609"
y="-54.267017"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use80"
width="5.3566022"
height="5.3566022"
x="173.79407"
y="-50.71233"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use81"
width="5.3566022"
height="5.3566022"
x="156.58191"
y="-86.633354"
transform="rotate(45)" /><rect
style="fill:#ffffff;stroke-width:1.89844;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
id="use82"
width="5.3566022"
height="5.3566022"
x="178.84547"
y="-73.724243"
transform="rotate(45)" /><path
style="color:#000000;fill:#ffffff;stroke-linecap:round;stroke-dashoffset:33.2598;-inkscape-stroke:none;paint-order:fill markers stroke"
d="m 125.67773,49.578125 c -2.01295,0 -3.67187,1.656968 -3.67187,3.669922 0,2.012954 1.65892,3.671875 3.67187,3.671875 2.01296,0 3.66993,-1.658921 3.66993,-3.671875 0,-2.012954 -1.65697,-3.669922 -3.66993,-3.669922 z m 0,2.380859 c 0.72604,0 1.28907,0.56303 1.28907,1.289063 0,0.726032 -0.56303,1.289062 -1.28907,1.289062 -0.72603,0 -1.28906,-0.56303 -1.28906,-1.289062 0,-0.726033 0.56303,-1.289063 1.28906,-1.289063 z"
id="use69" /></g></g></svg>

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 734 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.412851,0,0,0.412851,-164.727,-144.911)">
<path d="M399,404C477.667,404 563.667,422.167 640,421C712.766,419.888 784.237,398.26 857,397C934,395.667 1021,413.167 1102,413C1182.53,412.834 1262.47,395.225 1343,396C1482.5,397.343 1719.83,418.976 1861,421.056C1915.68,421.862 2097.72,404.026 2176.88,404.026L2176.88,351.026L399,351L399,404Z" style="fill:rgb(55,83,123);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 861 B

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 734 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(0.412851,0,0,0.412851,-164.727,-144.911)">
<path d="M399,404C477.667,404 563.667,422.167 640,421C712.766,419.888 784.237,398.26 857,397C934,395.667 1021,413.167 1102,413C1182.53,412.834 1262.47,395.225 1343,396C1482.5,397.343 1719.83,418.976 1861,421.056C1915.68,421.862 2097.72,404.026 2176.88,404.026L2176.88,351.026L399,351L399,404Z" style="fill:rgb(183,218,255);"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 863 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 475 283" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:1.5;">
<g id="Handlebars" transform="matrix(1,0,0,1,-100,-167)">
<path d="M404,196C407.778,166.333 384.333,169 364,184" style="fill:none;stroke:white;stroke-width:9px;"/>
</g>
<g id="Seat">
</g>
<path d="M120,42L160,42C177.006,42.052 186.77,48.289 191,58" style="fill:none;stroke:white;stroke-width:9px;"/>
<g id="Frame" transform="matrix(1,0,0,1,-100,-167)">
<path d="M314,390L445,274" style="fill:none;stroke:white;stroke-width:9px;"/>
<path d="M500,375L404,196" style="fill:none;stroke:white;stroke-width:9px;stroke-linecap:butt;"/>
<path d="M266,259L437,259" style="fill:none;stroke:white;stroke-width:9px;"/>
<path d="M314,390L248,209" style="fill:none;stroke:white;stroke-width:9px;stroke-linecap:butt;"/>
<g transform="matrix(0.815396,-0.0212494,-0.0212494,0.997554,66.2531,7.62625)">
<path d="M143.044,371.322L314,390" style="fill:none;stroke:white;stroke-width:10.11px;"/>
</g>
<path d="M175,375L266,259" style="fill:none;stroke:white;stroke-width:9px;"/>
</g>
<g id="Wheel" transform="matrix(1,0,0,1,-100,-167)">
<g transform="matrix(0.980392,0,0,0.980392,-46.0784,31.3725)">
<path d="M302,293.019C302,282.522 293.478,274 282.981,274L168.019,274C157.522,274 149,282.522 149,293.019L149,407.981C149,418.478 157.522,427 168.019,427L282.981,427C293.478,427 302,418.478 302,407.981L302,293.019ZM292.82,293.019L292.82,407.981C292.82,413.411 288.411,417.82 282.981,417.82C282.981,417.82 168.019,417.82 168.019,417.82C162.589,417.82 158.18,413.411 158.18,407.981L158.18,293.019C158.18,287.589 162.589,283.18 168.019,283.18L282.981,283.18C288.411,283.18 292.82,287.589 292.82,293.019Z" style="fill:white;"/>
</g>
<g transform="matrix(1,0,0,1,-50,26)">
<path d="M237,343C237,339.689 234.311,337 231,337L219,337C215.689,337 213,339.689 213,343L213,355C213,358.311 215.689,361 219,361L231,361C234.311,361 237,358.311 237,355L237,343Z" style="fill:white;"/>
</g>
</g>
<g id="Wheel1" serif:id="Wheel" transform="matrix(1,0,0,1,225,-167)">
<g transform="matrix(0.980392,0,0,0.980392,-46.0784,31.3725)">
<path d="M302,293.019C302,282.522 293.478,274 282.981,274L168.019,274C157.522,274 149,282.522 149,293.019L149,407.981C149,418.478 157.522,427 168.019,427L282.981,427C293.478,427 302,418.478 302,407.981L302,293.019ZM292.82,293.019L292.82,407.981C292.82,413.411 288.411,417.82 282.981,417.82C282.981,417.82 168.019,417.82 168.019,417.82C162.589,417.82 158.18,413.411 158.18,407.981L158.18,293.019C158.18,287.589 162.589,283.18 168.019,283.18L282.981,283.18C288.411,283.18 292.82,287.589 292.82,293.019Z" style="fill:white;"/>
</g>
<g transform="matrix(1,0,0,1,-50,26)">
<path d="M237,343C237,339.689 234.311,337 231,337L219,337C215.689,337 213,339.689 213,343L213,355C213,358.311 215.689,361 219,361L231,361C234.311,361 237,358.311 237,355L237,343Z" style="fill:white;"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

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