Compare commits

70 Commits
main ... dev

Author SHA1 Message Date
Gustavo "Guz" L. de Mello
eb8b5b5d32 chore: add licenses 2024-06-20 18:58:36 -03:00
Gustavo "Guz" L. de Mello
ed4cb4fc5c feat: added footer and copyright notice 2024-06-20 18:30:18 -03:00
Gustavo "Guz" L. de Mello
b90ab68c74 feat: add dynamic robots.txt and ai.txt 2024-06-19 16:58:52 -03:00
Gustavo "Guz" L. de Mello
91d5929260 fix(a11y): ul contains not-li elements 2024-06-19 16:32:47 -03:00
Gustavo "Guz" L. de Mello
6c435b8748 feat(a11y): forced colors support 2024-06-19 16:24:02 -03:00
Gustavo "Guz" L. de Mello
860a89db9f fix(a11y): improve contrast on blog summaries 2024-06-19 15:56:45 -03:00
Gustavo "Guz" L. de Mello
3280dbfffe fix: scroll snap of blog section 2024-06-19 15:51:24 -03:00
Gustavo "Guz" L. de Mello
e5b2020bda fix: responsiviness of contacts section 2024-06-19 15:43:47 -03:00
Gustavo "Guz" L. de Mello
4e848a0b68 chore: ommit gallery section for now
comment out the gallery section until a better image processing is done
2024-06-19 14:11:36 -03:00
Gustavo "Guz" L. de Mello
8e191c8864 feat: contact section 2024-06-19 14:10:38 -03:00
Gustavo "Guz" L. de Mello
43400ef31c refactor(deps): remove duplicated import and package 2024-06-17 16:43:21 -03:00
Gustavo "Guz" L. de Mello
199d3b2f8a fix(ci): templ files not generating 2024-06-17 16:37:03 -03:00
Gustavo "Guz" L. de Mello
4882060a62 fix(ci): vercel static build 2024-06-17 16:34:02 -03:00
Gustavo "Guz" L. de Mello
a9fd31fa97 fix: uncommitted changes 2024-06-17 16:30:12 -03:00
Gustavo "Guz" L. de Mello
92e83cd888 feat: blog section on homepage 2024-06-17 16:29:54 -03:00
Gustavo "Guz" L. de Mello
31174ea9a9 fix: smooth scroll on homepage 2024-06-17 16:29:15 -03:00
Gustavo "Guz" L. de Mello
df5e2a26cb chore: improve development workflow 2024-06-17 16:28:19 -03:00
Guz
e7332da3f1 chore: merge #10 image-optimzation into dev
feat!: refactor the api endpoint to follow and fix #9
2024-06-13 11:56:12 -03:00
Gustavo "Guz" L. de Mello
85ea7ddbd0 feat!: convert all images to webp and simplify everything 2024-06-13 11:10:21 -03:00
Gustavo "Guz" L. de Mello
eee1503855 fix: threshold calculation and resize update 2024-06-12 16:30:14 -03:00
Gustavo "Guz" L. de Mello
a2426b8f87 fix: type coersion
I should probably have testes this thing before commiting
2024-06-12 16:19:31 -03:00
Gustavo "Guz" L. de Mello
3edf844494 fix: threshold typo/missing getter 2024-06-12 16:15:37 -03:00
Gustavo "Guz" L. de Mello
2aa705489b fix: host typo 2024-06-12 16:15:23 -03:00
Gustavo "Guz" L. de Mello
3b1399390e feat!: refactor the api endpoint to follow and fix #9 2024-06-12 16:08:12 -03:00
Gustavo "Guz" L. de Mello
3f37c60e75 fix: cache on vercel 2024-06-11 16:43:42 -03:00
Gustavo "Guz" L. de Mello
b89909ec81 fix: request scheme on vercel 2024-06-11 16:37:42 -03:00
Gustavo "Guz" L. de Mello
2a1c79ffdc feat: image component and api 2024-06-11 16:31:51 -03:00
Gustavo "Guz" L. de Mello
7244e5503d refactor: add logs and cache removar to middleware 2024-06-11 16:31:31 -03:00
Gustavo "Guz" L. de Mello
c76cbd4682 feat: gallery section 2024-06-10 16:55:18 -03:00
Gustavo "Guz" L. de Mello
36b0206010 fix: makefile ignoring go files 2024-06-10 16:54:54 -03:00
Gustavo "Guz" L. de Mello
1fbf81292f fix: improve a11y 2024-06-07 20:00:51 -03:00
Gustavo "Guz" L. de Mello
149bfe3e25 feat: scrollbar style 2024-06-07 19:35:54 -03:00
Gustavo "Guz" L. de Mello
d97ff65332 fix: navbar shadow is too big on mobile 2024-06-07 16:06:57 -03:00
Gustavo "Guz" L. de Mello
35a4047a6c feat: scroll snap on desktop 2024-06-07 15:42:30 -03:00
Gustavo "Guz" L. de Mello
4207f349b9 fix: sizing issues and scalability 2024-06-07 14:59:25 -03:00
Gustavo "Guz" L. de Mello
d0293622b2 fix: sections sizing 2024-06-07 13:42:32 -03:00
Gustavo "Guz" L. de Mello
1b191dbb2e feat: projects section link 2024-06-07 13:42:25 -03:00
Gustavo "Guz" L. de Mello
8f4a98c9e3 fix: gradient overlay positioning 2024-06-07 13:41:51 -03:00
Gustavo "Guz" L. de Mello
54ba4969cd fix: icon size 2024-06-07 13:27:02 -03:00
Gustavo "Guz" L. de Mello
5b6501e8c9 fix: grdient overlay of navbar blocks interactivity 2024-06-07 13:26:44 -03:00
Gustavo "Guz" L. de Mello
7a02a56a63 feat: projects section on desktop 2024-06-07 11:14:43 -03:00
Gustavo "Guz" L. de Mello
ed59610650 fix: one pixel line on bottom of gradient 2024-06-07 10:49:26 -03:00
Gustavo "Guz" L. de Mello
e623d7d012 feat: projects section for mobile 2024-06-06 17:42:11 -03:00
Gustavo "Guz" L. de Mello
f2954f09d2 chore: add credits to custom preset 2024-06-06 15:49:58 -03:00
Gustavo "Guz" L. de Mello
0aadd4b383 fix: gradient overlay blocks interactivity 2024-06-06 15:49:43 -03:00
Gustavo "Guz" L. de Mello
8fd46e2543 fix: remove unused files 2024-06-06 15:14:34 -03:00
Gustavo "Guz" L. de Mello
8ed0ca9918 fix: fade-in animations timing 2024-06-06 15:14:25 -03:00
Gustavo "Guz" L. de Mello
2965d6e7a6 fix: ignore node_modules in makefile 2024-06-06 15:13:09 -03:00
Gustavo "Guz" L. de Mello
3b497e231b feat: create custom preset for container at-rules 2024-06-06 15:12:52 -03:00
Gustavo "Guz" L. de Mello
8c58acd9f8 fix: remove quote from heading 2024-06-03 15:30:36 -03:00
Gustavo "Guz" L. de Mello
be54eea7a9 fix: mobile navbar is not fixed to the screen 2024-06-03 15:27:08 -03:00
Gustavo "Guz" L. de Mello
6258431a9d fix: smooth scrolling and screen 2024-05-29 17:01:12 -03:00
Gustavo "Guz" L. de Mello
65d96abb40 feat: nav bar and footer shadows 2024-05-29 17:00:53 -03:00
Gustavo "Guz" L. de Mello
5da5e79f41 feat: about section 2024-05-29 17:00:24 -03:00
Gustavo "Guz" L. de Mello
e40f2de9e2 fix: commit new classes 2024-05-29 16:17:01 -03:00
Gustavo "Guz" L. de Mello
2de62be083 fix: lang attribute 2024-05-29 16:16:49 -03:00
Gustavo "Guz" L. de Mello
baac9b8642 fix: mobile menu appearing in desktop 2024-05-29 16:16:34 -03:00
Gustavo "Guz" L. de Mello
a2a86d7f32 chore: break lines in html to readability 2024-05-29 15:06:40 -03:00
Gustavo "Guz" L. de Mello
7f431aed5b feat: navigation menu 2024-05-28 19:17:38 -03:00
Gustavo "Guz" L. de Mello
9043cba830 chore: update packages 2024-05-28 15:21:55 -03:00
Gustavo "Guz" L. de Mello
8df2030bd8 fix: responsiviness and viewport properties 2024-05-28 15:21:40 -03:00
Gustavo "Guz" L. de Mello
c45b74bd53 fix: temporary fix to issue unocss/unocss#3845 2024-05-28 14:58:46 -03:00
Gustavo "Guz" L. de Mello
8c1375fe9a feat: unocss theme 2024-05-27 14:05:51 -03:00
Gustavo "Guz" L. de Mello
529230d926 refactor: move hero to homepage 2024-05-27 14:05:37 -03:00
Gustavo "Guz" L. de Mello
dc4d0ec5e0 feat: hero component 2024-05-24 15:59:09 -03:00
Gustavo "Guz" L. de Mello
84ef620259 fix: watch css and templ files in dev build 2024-05-24 15:58:45 -03:00
Gustavo "Guz" L. de Mello
db7ed4cea6 fix: makefile concurrent unocss and air 2024-05-24 14:06:51 -03:00
Gustavo "Guz" L. de Mello
92cda1f189 fix: dev mode in make dev 2024-05-24 11:29:44 -03:00
Gustavo "Guz" L. de Mello
cc53639ca8 feat: dev mode in server 2024-05-24 11:29:20 -03:00
Gustavo "Guz" L. de Mello
73a38e9083 fix: commands flags not being parsed 2024-05-24 11:28:23 -03:00
41 changed files with 2432 additions and 353 deletions

View File

@@ -42,7 +42,7 @@ jobs:
run: |
pnpm install
go install github.com/a-h/templ/cmd/templ@latest
make build-vercel
make build/static
- name: Deploy
uses: BetaHuhn/deploy-to-vercel-action@v1
with:

View File

@@ -37,7 +37,7 @@ jobs:
run: |
pnpm install
go install github.com/a-h/templ/cmd/templ@latest
make build-vercel
make build/static
- name: Deploy
uses: BetaHuhn/deploy-to-vercel-action@v1
with:

View File

@@ -37,7 +37,7 @@ jobs:
run: |
pnpm install
go install github.com/a-h/templ/cmd/templ@latest
make build-vercel
make build/static
- name: Deploy
uses: BetaHuhn/deploy-to-vercel-action@v1
with:

1
.gitignore vendored
View File

@@ -3,6 +3,7 @@ Session.vim
.direnv
.vercel
*_templ.go
*_templ.txt
dist
tmp
bin

373
LICENSE Normal file
View File

@@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

428
LICENSE-CC-BY-SA Normal file
View File

@@ -0,0 +1,428 @@
Attribution-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-ShareAlike 4.0 International Public
License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-ShareAlike 4.0 International Public License ("Public
License"). To the extent this Public License may be interpreted as a
contract, You are granted the Licensed Rights in consideration of Your
acceptance of these terms and conditions, and the Licensor grants You
such rights in consideration of benefits the Licensor receives from
making the Licensed Material available under these terms and
conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
l. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
m. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part; and
b. produce, reproduce, and Share Adapted Material.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
---
Copyright © 2024 Gustavo "Guz" L. de Mello.
Unless otherwise noticed, contents of this website itself are licensed under
the [Creative Commons Attribution-Share Alike 4.0 International ("CC BY-SA 4.0")](https://creativecommons.org/licenses/by-sa/4.0/)
[(Local copy)](./LICENSE-CC-BY-SA). Guz013, the 013 Logo, are trademarks of
Gustavo L. de Mello. The underlyng source code used to format and display that
content is, unless otherwise noticed, licensed under the [Mozilla Public License 2.0](https://www.mozilla.org/en-US/MPL/2.0/)
[(Local copy)](./LICENSE).

27
api/ai.go Normal file
View File

@@ -0,0 +1,27 @@
package api
import (
"io"
"net/http"
"www/internals"
)
func AiTxt(w http.ResponseWriter, r *http.Request) {
error := internals.HttpErrorHelper(w)
aiList, err := http.Get("https://raw.githubusercontent.com/ai-robots-txt/ai.robots.txt/main/ai.txt")
if error("Error trying to fetch ai block list", err, http.StatusInternalServerError) {
return
}
bytes, err := io.ReadAll(aiList.Body)
if error("Error trying to read ai block list", err, http.StatusInternalServerError) {
return
}
w.Write(bytes)
w.Header().Add("Cache-Control", "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400")
w.Header().Add("CDN-Cache-Control", "max-age=604800")
w.Header().Add("Content-Type", "text/plain")
}

View File

@@ -1,45 +0,0 @@
package api
import (
"encoding/json"
"fmt"
"io"
"math/rand/v2"
"net/http"
)
type helloObj struct {
Language string
Hello string
}
func getHelloList() ([]helloObj, error) {
res, err := http.Get("https://raw.githubusercontent.com/novellac/multilanguage-hello-json/master/hello.json")
if err != nil {
return nil, err
}
bytes, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
var hellos []helloObj
err = json.Unmarshal(bytes, &hellos)
if err != nil {
return nil, err
}
return hellos, nil
}
func Hello(w http.ResponseWriter, r *http.Request) {
hellos, err := getHelloList()
var hello string
if err != nil {
hello = "Welcome!"
} else {
hello = hellos[rand.IntN(len(hellos)-1)].Hello
}
fmt.Fprint(w, hello)
}

96
api/image.go Normal file
View File

@@ -0,0 +1,96 @@
package api
import (
"bytes"
"errors"
"image"
"io"
"net/http"
"net/url"
"strconv"
"www/internals"
"github.com/chai2010/webp"
"github.com/sunshineplan/imgconv"
)
func ImgOptimize(i image.Image, threshold int) image.Image {
w := i.Bounds().Max.X
if threshold >= w {
return i
}
d := w / threshold
return imgconv.Resize(i, &imgconv.ResizeOption{Width: w / d})
}
func Image(w http.ResponseWriter, r *http.Request) {
error := internals.HttpErrorHelper(w)
params, err := url.ParseQuery(r.URL.RawQuery)
if error("Error trying to parse query parameters", err, http.StatusInternalServerError) {
return
}
if _, some := params["url"]; !some {
error("\"url\" parameter missing", errors.New("Missing argument"), http.StatusBadRequest)
return
}
u, err := url.Parse(params.Get("url"))
if error("\"url\" is not a valid URL string", err, http.StatusBadRequest) {
return
}
if u.Hostname() == "" {
if r.URL.Scheme == "" {
u.Scheme = "https"
} else {
u.Scheme = r.URL.Scheme
}
u.Host = r.Host
}
if _, some := params["threshold"]; !some {
error("\"threshold\" parameter missing", errors.New("Missing argument"), http.StatusBadRequest)
return
}
threshold, err := strconv.Atoi(params.Get("threshold"))
if error("\"threshold\" parameter is not a valid integer", err, http.StatusBadRequest) {
return
}
res, err := http.Get(u.String())
if error("Error trying to fetch the image", err, http.StatusInternalServerError) {
return
}
if res.StatusCode < 200 || res.StatusCode >= 300 {
error(
"Error trying to fetch the image, response is a non 2XX code",
errors.New("Status code: "+res.Status),
http.StatusInternalServerError,
)
}
data, err := io.ReadAll(res.Body)
if error("Error trying to read the image data", err, http.StatusInternalServerError) {
return
}
img, err := imgconv.Decode(bytes.NewReader(data))
if error("Error trying to decode the image", err, http.StatusInternalServerError) {
return
}
img = ImgOptimize(img, threshold)
err = webp.Encode(w, img, &webp.Options{Lossless: true})
if error("Error trying to encode the image", err, http.StatusInternalServerError) {
return
}
w.Header().Add("Cache-Control", "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400")
w.Header().Add("CDN-Cache-Control", "max-age=604800")
w.Header().Add("Content-Type", "image/webp")
}

27
api/robots.go Normal file
View File

@@ -0,0 +1,27 @@
package api
import (
"io"
"net/http"
"www/internals"
)
func RobotsTxt(w http.ResponseWriter, r *http.Request) {
error := internals.HttpErrorHelper(w)
aiList, err := http.Get("https://raw.githubusercontent.com/ai-robots-txt/ai.robots.txt/main/robots.txt")
if error("Error trying to fetch ai block list", err, http.StatusInternalServerError) {
return
}
bytes, err := io.ReadAll(aiList.Body)
if error("Error trying to read ai block list", err, http.StatusInternalServerError) {
return
}
w.Write(bytes)
w.Header().Add("Cache-Control", "max-age=604800, stale-while-revalidate=86400, stale-if-error=86400")
w.Header().Add("CDN-Cache-Control", "max-age=604800")
w.Header().Add("Content-Type", "text/plain")
}

View File

@@ -13,6 +13,8 @@ func main() {
dir := flag.String("d", "./dist", "the directory to write the files")
staticDir := flag.String("s", "./static", "the directory to copy static files from")
flag.Parse()
w := internals.StaticWriter{
DistDir: dir,
StaticDir: staticDir,

View File

@@ -24,6 +24,8 @@ func main() {
staticDir := flag.String("s", "./static", "the directory to copy static files from")
port := flag.Int("p", 8080, "the port to run the server")
flag.Parse()
configFile, err := os.ReadFile(*configPath)
if err != nil {
logger.Fatalf("Unable to read vercel.json file due to:\n%s", err)

49
components/blog.templ Normal file
View File

@@ -0,0 +1,49 @@
package components
import "strings"
type Blog struct {
Title string
Summary string
Link templ.SafeURL
}
templ BlogSummary(entry Blog) {
<article
aria-labelledby={ "blog-entry-" + strings.ReplaceAll(entry.Title, " ", "-") }
>
<h3
id={ "blog-entry-" + strings.ReplaceAll(entry.Title, " ", "-") }
class="font-cal text-xl"
>
{ entry.Title }
</h3>
<div class="relative w-fit h-fit">
<p class="line-clamp-3 text-justify text-light-gray">
{ entry.Summary }
</p>
<div
aria-hidden="true"
class="h-0 w-0 pointer-events-none bg-transparent! contrast-more:hidden"
>
<div
class={ "absolute left-0 top-0 h-100% w-100% " +
"bg-transparent bg-gradient-to-t from-black/50" }
></div>
</div>
</div>
<div>
<a
class={ "transition-2s transition-all text-gray hover:text-light-gray no-underline " +
"hover:underline transform-gpu hover:-translate-y-0.2 " +
"contrast-more:text-light-gray contrast-more:hover:text-white" }
href={ entry.Link }
>
Read all
<span
class="w-3 h-3 i-solar:arrow-right-up-line-duotone inline-block"
></span>
</a>
</div>
</article>
}

29
components/image.templ Normal file
View File

@@ -0,0 +1,29 @@
package components
import "net/url"
templ Image(src templ.SafeURL, alt string, class string) {
<picture class={ class }>
<source
media="(min-width: 1536px)"
srcset={ "/api/image?threshold=1536&url=" + url.PathEscape(string(src)) }
/>
<source
media="(min-width: 1280px)"
srcset={ "/api/image?threshold=1280&url=" + url.PathEscape(string(src)) }
/>
<source
media="(min-width: 1024px)"
srcset={ "/api/image?threshold=1024&url=" + url.PathEscape(string(src)) }
/>
<source
media="(min-width: 768px)"
srcset={ "/api/image?threshold=768&url=" + url.PathEscape(string(src)) }
/>
<source
media="(min-width: 640px)"
srcset={ "/api/image?threshold=640&url=" + url.PathEscape(string(src)) }
/>
<img src={ string(src) } alt={ alt } class="w-100% h-100%"/>
</picture>
}

89
components/nav.templ Normal file
View File

@@ -0,0 +1,89 @@
package components
import (
"fmt"
)
type Link struct {
Text string
Link templ.SafeURL
}
templ Nav(links []Link) {
<div
aria-hidden="true"
class="h-0 w-0 pointer-events-none bg-transparent!"
>
<div
class="fixed left-0 top-0 w-screen z-100"
>
<div class="h-4rem bg-black z-100"></div>
<div class="h-10vh bg-transparent bg-gradient-to-b from-black z-100"></div>
</div>
</div>
<section
class="flex flex-row justify-between fixed top-0 font-cal w-90% lg:w-80% xl:w-90% z-110"
>
<p
class="text-gray contrast-more:text-light-gray cannot-hover md:block!"
>
Gustavo "Guz" L. de Mello
</p>
<p
class="text-gray contrast-more:text-light-gray can-hover md:hidden"
>
Guz
</p>
<nav class="can-hover">
<ul class="flex flex-row gap-3 list-none">
for _, i := range links {
<li class="transform-gpu hover:-translate-y-0.2 transition-transform">
<a
class={ "text-gray contrast-more:text-light-gray hover:text-white " +
"no-underline hover:underline transition-color transition-1s" }
id={ fmt.Sprintf("nav-anchor-%s", i.Link) }
href={ i.Link }
>
{ i.Text }
</a>
</li>
}
</ul>
</nav>
</section>
<button
class={ "block p-0.3 bg-black/97 b-0 m-0 outline-0 shadow-2xl " +
"fixed bottom-5 right-5 text-gray z-100 cannot-hover" }
popovertarget="nav-popover"
>
<span class="i-solar:hamburger-menu-broken w-2rem h-2rem block">Menu</span>
</button>
<nav
class={ "fixed pb-10 p-5 m-0 b-0 h-100vh bg-black/97 shadow-black shadow-2xl z-10 " +
"animate slide-from-r fade-in overflow-hidden cannot-hover" }
style="inset: unset; bottom: 0; right: 0; --anim-duration: 300ms; --anim-slide-from-x: 50%;"
id="nav-popover"
popover
>
<div class="text-right h-100% w-100% flex flex-col-reverse">
<ul class="flex flex-col h-fit gap-3 font-cal text-xl pl-0 text-gray list-none">
for _, i := range links {
<li
class={ "hover:text-white transform-gpu hover:-translate-y-0.2 " +
"transition-transform after:content-['@'] " +
"after:pl-4 after:i-solar:posts-carousel-vertical-line-duotone" }
>
<a
class={ "text-gray hover:text-white no-underline " +
"hover:underline transition-color transition-1s" }
id={ fmt.Sprintf("nav-anchor-touch-%s", i.Link) }
href={ i.Link }
>
{ i.Text }
</a>
</li>
}
</ul>
</div>
</nav>
}

View File

@@ -0,0 +1,77 @@
package components
import "strings"
import "slices"
import "cmp"
type Project struct {
Name string
Summary string
Image templ.SafeURL
Link templ.SafeURL
Icon string
WIP bool
Current bool
Language string
}
func SortProjects(projects []Project) []Project {
slices.SortFunc(projects, func(a, b Project) int {
if (a.Current && !b.Current) || (a.WIP && !b.WIP) {
return -1
}
return cmp.Compare(a.Name, b.Name)
})
return projects
}
templ ProjectCard(project Project) {
<article
class={ "bg-dark-gray relative h-100% test:m-1 @container/projectcard-size " +
"border-white forced-colors:border-3 forced-colors:border-solid" }
aria-labelledby={ "project-" + strings.ReplaceAll(project.Name, " ", "-") }
>
<div class="hidden @[h:12rem]/projectcard:block max-h-50% overflow-hidden relative">
<picture class="h-100% flex items-center -translate-y-25%">
<img class="h-auto w-100% self-center" src={ string(project.Image) } alt=""/>
</picture>
<div
aria-hidden="true"
class="w-100% h-100% absolute top-0 bg-gradient-to-t from-dark-gray translate-y-1%"
></div>
</div>
<div class="px-10 py-5 flex gap-5">
<div class="hidden @[w:24rem]/projectcard:flex items-center justify-center forced-colors:hidden">
<div class={ "w-12 h-12 bg-light-gray text-0 " + project.Icon }>Icon</div>
</div>
<div>
<hgroup class="flex items-center justify-between">
<h3
id={ "project-" + project.Name }
class="font-cal text-xl m-0"
>
{ project.Name }
</h3>
<p
aria-label="Status"
class="top-0 right-0 m-0 text-xs"
>
if project.Current {
<span class="bg-mauve text-dark-gray rounded-xl px-2">Current</span>
}
if project.WIP {
<span class="bg-yellow text-dark-gray rounded-xl px-2">
<abbr class="decoration-none" title="Work In Progress">WIP</abbr>
</span>
}
</p>
</hgroup>
<p
class="m-0 text-sm text-gray contrast-more:text-light-gray text-justify line-clamp-2"
>
{ project.Summary }
</p>
</div>
</div>
</article>
}

View File

@@ -1,17 +1,133 @@
package config
import (
"github.com/a-h/templ"
"math/rand"
"net/http"
"www/api"
"www/components"
"www/internals"
"www/pages"
)
var mockProjects = []components.Project{
{
Name: "rec-sh",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.SafeURL("https://github.com/dot013/rec-sh"),
Image: templ.SafeURL("https://images.unsplash.com/photo-1461749280684-dccba630e2f6?q=80&w=2669&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"),
Icon: "i-solar:programming-bold",
WIP: false,
Current: false,
Language: "bash",
},
{
Name: ".mdparser",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.SafeURL("https://github.com/dot013/rec-sh"),
Image: templ.SafeURL("https://images.unsplash.com/photo-1560697024-fd4affa63094?q=80&w=2630&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"),
Icon: "i-simple-icons:rust",
WIP: true,
Current: false,
Language: "rust",
},
{
Name: ".www",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.SafeURL("https://github.com/dot013/.www"),
Image: templ.SafeURL("https://images.unsplash.com/photo-1461749280684-dccba630e2f6?q=80&w=2669&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"),
Icon: "i-simple-icons:go",
WIP: true,
Current: true,
Language: "golang",
},
{
Name: "Project",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.SafeURL("https://github.com/dot013/.www"),
Image: templ.SafeURL("https://images.unsplash.com/photo-1461749280684-dccba630e2f6?q=80&w=2669&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"),
Icon: "i-solar:box-bold-duotone",
WIP: false,
Current: false,
Language: "nix",
},
{
Name: "Project",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.SafeURL("https://github.com/dot013/.www"),
Image: templ.SafeURL("https://images.unsplash.com/photo-1461749280684-dccba630e2f6?q=80&w=2669&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"),
Icon: "i-solar:box-bold-duotone",
WIP: false,
Current: false,
Language: "nix",
},
}
var mockBlog = []components.Blog{
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
{
Title: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim.",
Summary: "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint " +
"cillum sint consectetur cupidatat Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.",
Link: templ.URL("/001"),
},
}
var images = []string{
"/images/image-1.png",
"/images/image-2.png",
"/images/image-3.png",
"/images/image-4.png",
"/images/image-5.png",
"/images/image-6.png",
}
func init() {
rand.Shuffle(len(images), func(i, j int) {
images[i], images[j] = images[j], images[i]
})
}
var ROUTES = []internals.Page{
{Path: "index.html", Component: pages.Homepage()},
{Path: "index.html", Component: pages.Homepage(pages.HomepageProps{
Projects: mockProjects,
Images: []string{},
Blogs: mockBlog,
})},
}
func APIROUTES(mux *http.ServeMux) {
mux.HandleFunc("/api/hello", api.Hello)
mux.HandleFunc("/api/image", api.Image)
mux.HandleFunc("/robots.txt", api.RobotsTxt)
mux.HandleFunc("/ai.txt", api.AiTxt)
}

View File

@@ -21,7 +21,6 @@
{
devShells.default = pkgs.mkShell {
buildInputs = with pkgs; [
air
go
golangci-lint
templ

19
go.mod
View File

@@ -2,4 +2,21 @@ module www
go 1.22.2
require github.com/a-h/templ v0.2.697
require (
github.com/a-h/templ v0.2.697
github.com/chai2010/webp v1.1.1
github.com/sunshineplan/imgconv v1.1.10
)
require (
github.com/hhrutter/lzw v1.0.0 // indirect
github.com/hhrutter/tiff v1.0.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/pdfcpu/pdfcpu v0.8.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/sunshineplan/pdf v1.0.7 // indirect
golang.org/x/image v0.17.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)

27
go.sum
View File

@@ -1,4 +1,31 @@
github.com/a-h/templ v0.2.697 h1:OILxtWvD0NRJaoCOiZCopRDPW8paroKlGsrAiHLykNE=
github.com/a-h/templ v0.2.697/go.mod h1:5cqsugkq9IerRNucNsI4DEamdHPsoGMQy99DzydLhM8=
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
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/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0=
github.com/hhrutter/tiff v1.0.1/go.mod h1:zU/dNgDm0cMIa8y8YwcYBeuEEveI4B0owqHyiPpJPHc=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/pdfcpu/pdfcpu v0.8.0 h1:SuEB4uVsPFz1nb802r38YpFpj9TtZh/oB0bGG34IRZw=
github.com/pdfcpu/pdfcpu v0.8.0/go.mod h1:jj03y/KKrwigt5xCi8t7px2mATcKuOzkIOoCX62yMho=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/sunshineplan/imgconv v1.1.10 h1:EJZVXLwmvmKgEA1KIJpNSzSssjGaZMdtOLycGFyzxQA=
github.com/sunshineplan/imgconv v1.1.10/go.mod h1:de9NsLFCMW2JVom3mjRZu3GceLFwkEIEkf1EGS5rDX4=
github.com/sunshineplan/pdf v1.0.7 h1:62xlc079jh4tGLDjiihyyhwVFkn0IsxLyDpHplbG9Ew=
github.com/sunshineplan/pdf v1.0.7/go.mod h1:QsEmZCWBE3uFK8PCrM0pua1WDWLNU77YusiDEcY56OQ=
golang.org/x/image v0.17.0 h1:nTRVVdajgB8zCMZVsViyzhnMKPwYeroEERRC64JuLco=
golang.org/x/image v0.17.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

20
internals/helpers.go Normal file
View File

@@ -0,0 +1,20 @@
package internals
import (
"net/http"
)
func HttpErrorHelper(w http.ResponseWriter) func(msg string, err error, status int) bool {
return func(msg string, err error, status int) bool {
if err != nil {
w.WriteHeader(status)
_, err = w.Write([]byte(msg + "\n Error: " + err.Error()))
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, _ = w.Write([]byte("Error trying to return error code (somehow):\n" + err.Error()))
}
return true
}
return false
}
}

34
internals/middleware.go Normal file
View File

@@ -0,0 +1,34 @@
package internals
import (
"log"
"net/http"
)
type Middleware struct {
handler http.Handler
dev bool
noCache bool
logger *log.Logger
}
func (m *Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
m.logger.Printf("Handling request. path=%s", r.URL.Path)
if m.dev {
r.URL.Scheme = "http"
} else {
r.URL.Scheme = "https"
}
m.handler.ServeHTTP(w, r)
if m.noCache {
w.Header().Del("Cache-Control")
w.Header().Add("Cache-Control", "max-age=0")
}
}
func NewMiddleware(handler http.Handler, dev bool, noCache bool, logger *log.Logger) *Middleware {
return &Middleware{handler, dev, noCache, logger}
}

View File

@@ -1,26 +1,26 @@
package layouts
templ Page(title string) {
<html>
<!DOCTYPE html>
<html lang="en-US" class="scroll-smooth motion-reduce:scroll-auto">
<head>
<!-- TODO: improve a11y for zoomed states -->
<meta
name="viewport"
content={ "width=device-width, " +
"initial-scale=1.0, " +
"maximum-scale=1.0, " +
"user-scalable=no" }
/>
<link rel="stylesheet" href="/uno.css"/>
<style>
@font-face {
font-family: Inter;
src: url(inter.woff2);
}
@font-face {
font-family: Cal Sans;
src: url(cal-sans.woff2);
}
@font-face {
font-family: Fira Code;
src: url(fira-code.woff2);
}
</style>
<link rel="stylesheet" href="/global.css"/>
<title>{ title }</title>
</head>
<body class="bg-black flex flex-col justify-center items-center w-screen h-screen overflow-hidden text-white font-sans">
<body
class={ "flex flex-col justify-center items-center " +
"w-screen overflow-x-hidden text-white bg-black font-sans m-0" }
style="--anim-slide-from-y: 10px; --anim-delay: 120ms; --anim-duration: 0.6s;"
>
{ children... }
</body>
</html>

16
main.go
View File

@@ -17,6 +17,14 @@ var logger = log.Default()
func main() {
staticDir := flag.String("s", "./static", "the directory to copy static files from")
port := flag.Int("p", 8080, "the port to run the server")
dev := flag.Bool("d", false, "if the server is in development mode")
cache := flag.Bool("c", true, "if the static files are cached")
flag.Parse()
if *dev {
log.Printf("Running server in DEVELOPMENT MODE")
}
mux := http.NewServeMux()
@@ -29,8 +37,6 @@ func main() {
logger.Printf("Registering page route. page=%s route=%s", route.Path, path)
mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
logger.Printf("Handling request. path=%s", r.URL.Path)
w.Header().Add("Content-Type", "text/html")
err := route.Component.Render(r.Context(), w)
@@ -46,8 +52,6 @@ func main() {
return
}
logger.Printf("Handling request. path=%s", r.URL.Path)
w.Header().Add("Content-Type", "text/html")
index := slices.IndexFunc(config.ROUTES, func(route internals.Page) bool {
@@ -62,7 +66,9 @@ func main() {
})
logger.Printf("Running server at port: %v", *port)
err := http.ListenAndServe(fmt.Sprintf(":%v", *port), mux)
middleware := internals.NewMiddleware(mux, *dev, !*cache, log.Default())
err := http.ListenAndServe(fmt.Sprintf(":%v", *port), middleware)
if err != nil {
logger.Fatalf("Server crashed due to:\n%s", err)
}

View File

@@ -1,52 +1,47 @@
PORT?=8080
all: run
build: templ
pnpm unocss
go build -o bin/www
build/static: templ
pnpm unocss
go run ./cmd/build
dev/templ:
templ generate --watch \
--proxy=http://localhost:$(PORT) \
--open-browser=false
dev/server:
go run github.com/air-verse/air@v1.52.2 \
--build.cmd "go build -o tmp/bin/main" \
--build.bin "tmp/bin/main" \
--build.exclude_dir "node_modules" \
--build.include_ext "go" \
--build.stop_on_error "false" \
--misc.clean_on_exit true \
-- -p $(PORT) -d
dev/unocss:
pnpm unocss -w
dev/sync_assets:
go run github.com/air-verse/air@v1.52.2 \
--build.cmd "templ generate --notify-proxy" \
--build.bin "true" \
--build.delay "100" \
--build.exclude_dir "" \
--build.include_dir "static" \
--build.include_ext "js,css"
dev:
pnpm unocss -w &
air -build.pre_cmd 'make templ' \
-build.include_ext 'templ' \
-build.include_ext 'css' \
-proxy.enabled true \
-proxy.app_port $(PORT) \
-proxy.proxy_port $$(($(PORT) + 1)) \
-- -p $(PORT)
make -j4 dev/templ dev/server dev/unocss dev/sync_assets
dev-vercel:
air -build.pre_cmd 'make build-vercel' \
-build.include_ext 'templ' \
-build.cmd 'make build-vercel' \
-build.bin './bin/vercel' \
-proxy.enabled true \
-proxy.app_port $(PORT) \
-proxy.proxy_port $$(($(PORT) + 1)) \
-- -p $(PORT)
run: bin/www
run: build
./bin/www
run-vercel: bin/vercel
./bin/vercel
build-static: templ
pnpm unocss
go run ./cmd/build/main.go
build-vercel: bin/vercel build-static
bin/www: main.go templ
go build -o ./bin/www ./main.go
bin/vercel: cmd/vercel/main.go templ
go build -o ./bin/vercel ./cmd/vercel/main.go
# For some reason "templ generate" does not detect the files, so this is a
# workaround.
TEMPL_FILES=$(patsubst %.templ, %_templ.go, $(wildcard **/*.templ))
templ: $(TEMPL_FILES)
@echo Generating templ files
%_templ.go: %.templ
templ generate -f $^ > /dev/null
all: build
clean:
if [[ -d "dist" ]]; then rm -r ./dist; fi
@@ -54,3 +49,11 @@ clean:
if [[ -d "bin" ]]; then rm -r ./bin; fi
rm ./static/uno.css
rm $(TEMPL_FILES)
# For some reason "templ generate" does not detect the files in CI,
# so this is a workaround.
TEMPL_FILES=$(patsubst %.templ, %_templ.go, $(wildcard **/*.templ))
templ: $(TEMPL_FILES)
@echo Generating templ files
%_templ.go: %.templ
templ generate -f $^ > /dev/null

View File

@@ -2,10 +2,12 @@
"name": "www",
"version": "0.0.1",
"devDependencies": {
"@iconify-json/simple-icons": "^1.1.102",
"@iconify-json/simple-icons": "^1.1.103",
"@iconify-json/solar": "^1.1.9",
"@types/node": "^20.12.12",
"@unocss/cli": "^0.60.3",
"@unocss/core": "^0.60.4",
"@unocss/preset-mini": "^0.60.4",
"unocss": "^0.60.3"
}
}

View File

@@ -1,88 +1,378 @@
package pages
import (
"strings"
"www/layouts"
"www/components"
)
templ Homepage() {
type HomepageProps struct {
Projects []components.Project
Blogs []components.Blog
Images []string
}
templ Homepage(props HomepageProps) {
@layouts.Page("013") {
<main>
<img src="/logo-013.svg" alt="" width="100" height="100"/>
<h1 class="font-cal">Someone who's trying to improve</h1>
<div class="text-#181818 flex flex-row justify-between items-center">
<nav>
<ul class="list-none flex flex-row gap-3 p-0">
<li class="i-simple-icons:github w-4 hover:text-#ababab transition-colors">
@components.Nav([]components.Link{
{Text: "about", Link: templ.SafeURL("#about")},
{Text: "projects", Link: templ.SafeURL("#projects")},
// {Text: "gallery", Link: templ.SafeURL("#gallery")},
{Text: "blog", Link: templ.SafeURL("#blog")},
{Text: "contact", Link: templ.SafeURL("#contact")},
})
<section
id="homepage"
class={ "w-screen h-screen overflow-x-hidden overflow-y-scroll scroll-smooth motion-reduce:scroll-auto " +
"snap-y scrollbar thumb-gray contrast-more:thumb-light-gray track-black" }
>
<header
class="h-screen w-screen flex justify-center items-center snap-start"
id="about"
>
<div class="flex flex-col lg:flex-row lg:justify-between lg:gap-5rem w-90% lg:w-80% xl:w-60%">
<div class="w-50% xl:w-25%">
<img
src="/logo-013.svg"
class="animate slide-from-b fade-in"
style="--anim-stagger: 1; opacity: 0;"
alt="013 Logo"
/>
</div>
<h1
class={ "w-full lg:max-w-45rem mb-0 lg:mt-0 prose text-2.9rem lg:text-6xl xl:text-4.3rem " +
"animate slide-from-b fade-in" }
style="--anim-stagger: 2; opacity: 0;"
>
Someone who's trying to improve
</h1>
</div>
</header>
<main
aria-labelledby="about-header"
class="w-screen h-50vh lg:h-60vh xl:h-50vh flex justify-center items-center"
>
<div class="w-90% xl:w-50% lg:text-xl -translate-y-20% xl:-translate-y-45% text-justify snap-center">
<h2 id="about-header" class="opacity-0">About</h2>
<p class="animate slide-from-b fade-in" style="--anim-stagger: 4; opacity: 0;">
Lorem ipsum dolor sit amet, officia excepteur ex fugiat
reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex
esse exercitation amet. Nisi anim cupidatat excepteur officia.
Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate
voluptate dolor minim nulla est proident. Nostrud officia pariatur ut
officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate.
Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis
officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis
sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea
consectetur et est culpa et culpa duis.
</p>
<p class="animate slide-from-b fade-in" style="--anim-stagger: 5; opacity: 0;">
Lorem ipsum dolor sit amet, officia excepteur ex fugiat
reprehenderit enim labore culpa sint ad nisi Lorem pariatur mollit ex
esse exercitation amet. Nisi anim cupidatat excepteur officia.
Reprehenderit nostrud nostrud ipsum Lorem est aliquip amet voluptate
voluptate dolor minim nulla est proident. Nostrud officia pariatur ut
officia. Sit irure elit esse ea nulla sunt ex occaecat reprehenderit
commodo officia dolor Lorem duis laboris cupidatat officia voluptate.
Culpa proident adipisicing id nulla nisi laboris ex in Lorem sunt duis
officia eiusmod. Aliqua reprehenderit commodo ex non excepteur duis
sunt velit enim. Voluptate laboris sint cupidatat ullamco ut ea
consectetur et est culpa et culpa duis.
</p>
</div>
</main>
<section
aria-labelledby="projects-header"
id="projects"
class="w-screen h-screen flex justify-center items-center"
>
<div class="w-90% xl:w-50% snap-center">
<hgroup class="flex justify-between my-5">
<h2 id="projects-header" class="font-cal text-5xl m-0">Projects.</h2>
<p class="m-0">
<a
href="https://github.com/guz013"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
href="/projects"
class="decoration-none text-light-gray flex items-center"
>
GitHub
See more
<span
class="w-5 h-5 bg-light-gray i-solar:arrow-right-up-line-duotone inline-block"
></span>
</a>
</p>
</hgroup>
<div class="grid grid-flow-row auto-rows-[minmax(6.7rem,_2fr)] md:grid-cols-2 gap-5">
for i, project := range components.SortProjects(props.Projects) {
if i == 0 {
<div class="row-span-2">
@components.ProjectCard(project)
</div>
} else if i < 3 {
<div>
@components.ProjectCard(project)
</div>
} else {
<div class="hidden md:block">
@components.ProjectCard(project)
</div>
}
}
</div>
</div>
</section>
<!-- <section
aria-labelledby="gallery-header"
id="gallery"
class="w-screen min-h-screen flex justify-center items-center"
>
<div class="w-90% xl:w-50% max-h-60% snap-start">
<hgroup class="flex justify-between my-5">
<h2 id="gallery-header" class="font-cal text-5xl m-0">Gallery.</h2>
<p class="m-0">
<a
href="/gallery"
class="decoration-none text-light-gray flex items-center"
>
See more
<span
class="w-5 h-5 bg-light-gray i-solar:arrow-right-up-line-duotone inline-block"
></span>
</a>
</p>
</hgroup>
<div class="flex flex-wrap flex-col w-100% max-h-65vh md:max-h-70vh overflow-hidden">
for _, img := range props.Images {
<div class="w-50% md:w-33.3%">
@components.Image(templ.SafeURL(img), "", "block max-w-100%")
</div>
}
</div>
</div>
</section> -->
<section
aria-labelledby="blog-header"
id="blog"
class="w-screen min-h-screen flex justify-center items-center"
>
<div class="w-90% xl:w-50% max-h-60% snap-center">
<hgroup class="flex justify-between my-5">
<h2 id="blog-header" class="font-cal text-5xl m-0">Blog.</h2>
<p class="m-0">
<a
href="/blog"
class="decoration-none text-light-gray flex items-center"
>
See more
<span
class="w-5 h-5 bg-light-gray i-solar:arrow-right-up-line-duotone inline-block"
></span>
</a>
</p>
</hgroup>
<div
class={ "w-100% max-h-65vh md:max-h-70vh overflow-hidden " +
"md:grid grid-cols-2 gap-4" }
>
for i, blog := range props.Blogs {
if i < 2 {
<div class="">
@components.BlogSummary(blog)
</div>
} else if i < 4 {
<div class="hidden md:block">
@components.BlogSummary(blog)
</div>
}
}
</div>
</div>
</section>
<section
aria-labelledby="contact-header"
id="contact"
class="w-screen min-h-screen flex justify-center items-center"
>
<div class="w-90% xl:w-50% max-h-60% snap-start">
<hgroup class="flex justify-between my-5">
<h2 id="contact-header" class="font-cal text-5xl m-0">Contact.</h2>
</hgroup>
<ul class="text-xl pl-0 grid grid-cols-2 md:grid-cols-4 list-none w-100%">
<li>
@contactList("Software") {
@contactItem("i-simple-icons:github", "GitHub", "http://github.com/guz013")
@contactItem("i-simple-icons:codeberg", "Codeberg", "http://codeberg.org/guz013")
}
</li>
<li class="i-simple-icons:codeberg w-4 hover:text-#ababab transition-colors">
<a
href="https://codeberg.org/guz013"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
>
Codeberg
</a>
<li>
@contactList("Social") {
@contactItem("i-simple-icons:twitter", "Twitter", "http://twitter.com/guz013_")
@contactItem("i-simple-icons:mastodon", "Mastodon", "http://mastodon.social/@guz013")
}
</li>
<li class="i-simple-icons:twitter w-4 hover:text-#ababab transition-colors">
<a
href="https://twitter.com/guz013_"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
>
Twitter
</a>
<li>
@contactList("Photography") {
@contactItem("i-simple-icons:instagram", "Instagram", "http://instagram.com/guz013_")
@contactItem("i-simple-icons:pixelfed", "Pixelfed", "http://pixelfed.social/guz013")
}
</li>
<li class="i-simple-icons:mastodon w-4 hover:text-#ababab transition-colors">
<a
href="https://mastodon.social/@guz013"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
>
Mastodon
</a>
</li>
<li class="i-simple-icons:instagram w-4 hover:text-#ababab transition-colors">
<a
href="https://instagram.com/guz013_"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
>
Instagram
</a>
</li>
<li class="i-simple-icons:pixelfed w-4 hover:text-#ababab transition-colors">
<a
href="https://pixelfed.social/@guz013"
target="_blank"
class="opacity-0"
rel="noreferrer noopener"
>
Pixelfed
</a>
<li>
@contactList("Art") {
@contactItem("i-simple-icons:instagram", "Instagram", "http://instagram.com/guzsart")
@contactItem("i-simple-icons:pixelfed", "Pixelfed", "http://pixelfed.social/guzsart")
}
</li>
</ul>
</nav>
<p class="m-0">
<a class="text-#181818 hover:text-#ababab transition-colors" href="mailto:contact.guz013@gmail.com">
2024 &copy Gustavo L. de Mello
</a>
</p>
<div
class="mt-3 md:mt-10"
aria-labelledby="business-contact"
>
<h3
class="text-gray contrast-more:text-white text-xl font-normal mb-0 inline-flex items-center gap-2"
id="business-contact"
>
Business
<a
class={ "inline-flex items-center text-black text-sm p-0.5 px-2 rounded-lg no-underline " +
"transition-all transition-2s bg-gray hover:bg-light-gray bg-gradient-to-t from-black/50 " +
"contrast-more:bg-light-gray contrast-more:hover:bg-white contrast-more:from-black/0" }
rel="noopener nofollow noreferrer"
href="mailto:contact.guz013@gmail.com"
>
<span
class="inline-block i-solar:hand-shake-bold-duotone w-4.5 h-4.5"
aria-hidden="true"
></span>
<span class="opacity-0">(</span>Open to hire!<span class="opacity-0">)</span>
</a>
</h3>
<ul class="list-none pl-0 flex gap-2 md:gap-5 relative">
<li>
<a
class={ "transition-all transition-2s text-light-gray hover:text-white " +
"flex items-center gap-1 no-underline hover:underline" }
target="_blank"
rel="noopener nofollow noreferrer"
href="mailto:contact.guz013@gmail.com"
>
<span
aria-hidden="true"
class="inline-block w-4.5 h-4.5 i-solar:mailbox-bold-duotone"
></span>
<span
class="transform-gpu pl-4.5 -translate-x-4.5 hover:-translate-y-0.2 transition-transform"
>
contact.guz013@gmail.com
</span>
</a>
</li>
@contactItem("i-simple-icons:linkedin", "LinkedIn", "http://linkedin.com/in/guz013")
<div
aria-hidden="true"
class="h-0 w-0 pointer-events-none bg-transparent! contrast-more:hidden"
>
<div
class={ "absolute left-0 top-0 h-100% w-100% " +
"bg-transparent bg-gradient-to-t from-black/50" }
></div>
</div>
</ul>
</div>
</div>
</section>
<footer
aria-labelledby="footer-header"
class="w-screen min-h-screen flex justify-center items-center"
>
<div
class="w-90% xl:w-50% max-h-60% snap-start text-center"
id="footer"
>
<h3 id="footer-header" class="opacity-0">Footer</h3>
<p>Copyright &copy; 2024 Gustavo "Guz" L. de Mello</p>
<p class="text-sm text-gray contrast-more:text-light-gray" id="license">
Unless otherwise noticed, contents of this website itself are licensed under
the
<a
class={ "transition-all transition-2s text-gray hover:text-light-gray "+
"contrast-more:text-light-gray contrart-more:hover:text-white "+
"underline" }
href="https://creativecommons.org/licenses/by-sa/4.0/"
rel="noopener nofollow noreferrer"
>
Creative Commons Attribution-Share Alike 4.0 International ("CC BY-SA 4.0")
</a>.
Guz013, the 013 Logo, are trademarks of Gustavo L. de Mello. The underlyng
source code used to format and display that content is, unless otherwise noticed,
licensed under the
<a
class={ "transition-all transition-2s text-gray hover:text-light-gray "+
"contrast-more:text-light-gray contrart-more:hover:text-white "+
"underline" }
href="https://www.mozilla.org/en-US/MPL/2.0/"
rel="noopener nofollow noreferrer"
>
Mozilla Public License 2.0
</a>.
</p>
</div>
</footer>
<div
aria-hidden="true"
class="h-0 w-0 pointer-events-none bg-transparent!"
>
<div
class={ "fixed bottom-0 left-0 w-screen h-40vh md:h-20vh " +
"bg-transparent bg-gradient-to-t from-black from-10%" }
></div>
</div>
</main>
<footer class="fixed bottom-0 text-xs font-mono ">
<p><a class="text-#181818 hover:text-#ababab" href="https://dot013-www-guz013-guzsprojects.vercel.app">new website in development</a></p>
</footer>
</section>
}
}
templ contactList(label string) {
<h3
class="mb-2 text-gray contrast-more:text-white font-normal text-xl"
id={ "contact-list-" + strings.ReplaceAll(label, " ", "-") }
>{ label }</h3>
<ul
class="list-none pl-0 relative"
aria-labelledby={ "contact-list-" + strings.ReplaceAll(label, " ", "-") }
>
{ children... }
<div
aria-hidden="true"
class="h-0 w-0 pointer-events-none bg-transparent! contrast-more:hidden"
>
<div
class={ "absolute left-0 top-0 h-100% w-100% " +
"bg-transparent bg-gradient-to-t from-black/50" }
></div>
</div>
</ul>
}
templ contactItem(icon string, label string, url string) {
<li>
<a
class={ "transition-all transition-2s text-light-gray hover:text-white " +
"flex items-center gap-1 no-underline hover:underline" }
target="_blank"
rel="noopener nofollow noreferrer"
href={ templ.URL(url) }
>
<span
aria-hidden="true"
class={ "inline-block w-4.5 h-4.5 " + icon }
></span>
<span
class="transform-gpu pl-4.5 -translate-x-4.5 hover:-translate-y-0.2 transition-transform"
>{ label }</span>
<span
aria-hidden="true"
class="inline-block i-solar:arrow-right-up-line-duotone w-4.5 h-4.5 -translate-x-4.5"
></span>
</a>
</li>
}

351
pnpm-lock.yaml generated
View File

@@ -6,8 +6,8 @@ settings:
devDependencies:
'@iconify-json/simple-icons':
specifier: ^1.1.102
version: 1.1.102
specifier: ^1.1.103
version: 1.1.103
'@iconify-json/solar':
specifier: ^1.1.9
version: 1.1.9
@@ -17,6 +17,12 @@ devDependencies:
'@unocss/cli':
specifier: ^0.60.3
version: 0.60.3
'@unocss/core':
specifier: ^0.60.4
version: 0.60.4
'@unocss/preset-mini':
specifier: ^0.60.4
version: 0.60.4
unocss:
specifier: ^0.60.3
version: 0.60.3(postcss@8.4.38)(vite@5.2.11)
@@ -42,33 +48,33 @@ packages:
resolution: {integrity: sha512-rWQkqXRESdjXtc+7NRfK9lASQjpXJu1ayp7qi1d23zZorY+wBHVLHHoVcMsEnkqEBWTFqbztO7/QdJFzyEcLTg==}
dev: true
/@babel/code-frame@7.24.2:
resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
/@babel/code-frame@7.24.6:
resolution: {integrity: sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.24.5
'@babel/highlight': 7.24.6
picocolors: 1.0.1
dev: true
/@babel/compat-data@7.24.4:
resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==}
/@babel/compat-data@7.24.6:
resolution: {integrity: sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/core@7.24.5:
resolution: {integrity: sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==}
/@babel/core@7.24.6:
resolution: {integrity: sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@ampproject/remapping': 2.3.0
'@babel/code-frame': 7.24.2
'@babel/generator': 7.24.5
'@babel/helper-compilation-targets': 7.23.6
'@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5)
'@babel/helpers': 7.24.5
'@babel/parser': 7.24.5
'@babel/template': 7.24.0
'@babel/traverse': 7.24.5
'@babel/types': 7.24.5
'@babel/code-frame': 7.24.6
'@babel/generator': 7.24.6
'@babel/helper-compilation-targets': 7.24.6
'@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.6)
'@babel/helpers': 7.24.6
'@babel/parser': 7.24.6
'@babel/template': 7.24.6
'@babel/traverse': 7.24.6
'@babel/types': 7.24.6
convert-source-map: 2.0.0
debug: 4.3.4
gensync: 1.0.0-beta.2
@@ -78,281 +84,278 @@ packages:
- supports-color
dev: true
/@babel/generator@7.24.5:
resolution: {integrity: sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==}
/@babel/generator@7.24.6:
resolution: {integrity: sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
'@jridgewell/gen-mapping': 0.3.5
'@jridgewell/trace-mapping': 0.3.25
jsesc: 2.5.2
dev: true
/@babel/helper-annotate-as-pure@7.22.5:
resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
/@babel/helper-annotate-as-pure@7.24.6:
resolution: {integrity: sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-compilation-targets@7.23.6:
resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==}
/@babel/helper-compilation-targets@7.24.6:
resolution: {integrity: sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/compat-data': 7.24.4
'@babel/helper-validator-option': 7.23.5
'@babel/compat-data': 7.24.6
'@babel/helper-validator-option': 7.24.6
browserslist: 4.23.0
lru-cache: 5.1.1
semver: 6.3.1
dev: true
/@babel/helper-create-class-features-plugin@7.24.5(@babel/core@7.24.5):
resolution: {integrity: sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==}
/@babel/helper-create-class-features-plugin@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-annotate-as-pure': 7.22.5
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-function-name': 7.23.0
'@babel/helper-member-expression-to-functions': 7.24.5
'@babel/helper-optimise-call-expression': 7.22.5
'@babel/helper-replace-supers': 7.24.1(@babel/core@7.24.5)
'@babel/helper-skip-transparent-expression-wrappers': 7.22.5
'@babel/helper-split-export-declaration': 7.24.5
'@babel/core': 7.24.6
'@babel/helper-annotate-as-pure': 7.24.6
'@babel/helper-environment-visitor': 7.24.6
'@babel/helper-function-name': 7.24.6
'@babel/helper-member-expression-to-functions': 7.24.6
'@babel/helper-optimise-call-expression': 7.24.6
'@babel/helper-replace-supers': 7.24.6(@babel/core@7.24.6)
'@babel/helper-skip-transparent-expression-wrappers': 7.24.6
'@babel/helper-split-export-declaration': 7.24.6
semver: 6.3.1
dev: true
/@babel/helper-environment-visitor@7.22.20:
resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
/@babel/helper-environment-visitor@7.24.6:
resolution: {integrity: sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-function-name@7.23.0:
resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
/@babel/helper-function-name@7.24.6:
resolution: {integrity: sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.24.0
'@babel/types': 7.24.5
'@babel/template': 7.24.6
'@babel/types': 7.24.6
dev: true
/@babel/helper-hoist-variables@7.22.5:
resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
/@babel/helper-hoist-variables@7.24.6:
resolution: {integrity: sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-member-expression-to-functions@7.24.5:
resolution: {integrity: sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==}
/@babel/helper-member-expression-to-functions@7.24.6:
resolution: {integrity: sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-module-imports@7.24.3:
resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==}
/@babel/helper-module-imports@7.24.6:
resolution: {integrity: sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-module-transforms@7.24.5(@babel/core@7.24.5):
resolution: {integrity: sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==}
/@babel/helper-module-transforms@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-module-imports': 7.24.3
'@babel/helper-simple-access': 7.24.5
'@babel/helper-split-export-declaration': 7.24.5
'@babel/helper-validator-identifier': 7.24.5
'@babel/core': 7.24.6
'@babel/helper-environment-visitor': 7.24.6
'@babel/helper-module-imports': 7.24.6
'@babel/helper-simple-access': 7.24.6
'@babel/helper-split-export-declaration': 7.24.6
'@babel/helper-validator-identifier': 7.24.6
dev: true
/@babel/helper-optimise-call-expression@7.22.5:
resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
/@babel/helper-optimise-call-expression@7.24.6:
resolution: {integrity: sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-plugin-utils@7.24.5:
resolution: {integrity: sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==}
/@babel/helper-plugin-utils@7.24.6:
resolution: {integrity: sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-replace-supers@7.24.1(@babel/core@7.24.5):
resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==}
/@babel/helper-replace-supers@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-member-expression-to-functions': 7.24.5
'@babel/helper-optimise-call-expression': 7.22.5
'@babel/core': 7.24.6
'@babel/helper-environment-visitor': 7.24.6
'@babel/helper-member-expression-to-functions': 7.24.6
'@babel/helper-optimise-call-expression': 7.24.6
dev: true
/@babel/helper-simple-access@7.24.5:
resolution: {integrity: sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==}
/@babel/helper-simple-access@7.24.6:
resolution: {integrity: sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-skip-transparent-expression-wrappers@7.22.5:
resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
/@babel/helper-skip-transparent-expression-wrappers@7.24.6:
resolution: {integrity: sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-split-export-declaration@7.24.5:
resolution: {integrity: sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==}
/@babel/helper-split-export-declaration@7.24.6:
resolution: {integrity: sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/helper-string-parser@7.24.1:
resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==}
/@babel/helper-string-parser@7.24.6:
resolution: {integrity: sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-validator-identifier@7.24.5:
resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
/@babel/helper-validator-identifier@7.24.6:
resolution: {integrity: sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helper-validator-option@7.23.5:
resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
/@babel/helper-validator-option@7.24.6:
resolution: {integrity: sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/helpers@7.24.5:
resolution: {integrity: sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==}
/@babel/helpers@7.24.6:
resolution: {integrity: sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/template': 7.24.0
'@babel/traverse': 7.24.5
'@babel/types': 7.24.5
transitivePeerDependencies:
- supports-color
'@babel/template': 7.24.6
'@babel/types': 7.24.6
dev: true
/@babel/highlight@7.24.5:
resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==}
/@babel/highlight@7.24.6:
resolution: {integrity: sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.24.5
'@babel/helper-validator-identifier': 7.24.6
chalk: 2.4.2
js-tokens: 4.0.0
picocolors: 1.0.1
dev: true
/@babel/parser@7.24.5:
resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==}
/@babel/parser@7.24.6:
resolution: {integrity: sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==}
engines: {node: '>=6.0.0'}
hasBin: true
dependencies:
'@babel/types': 7.24.5
'@babel/types': 7.24.6
dev: true
/@babel/plugin-syntax-jsx@7.24.1(@babel/core@7.24.5):
resolution: {integrity: sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA==}
/@babel/plugin-syntax-jsx@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-plugin-utils': 7.24.5
'@babel/core': 7.24.6
'@babel/helper-plugin-utils': 7.24.6
dev: true
/@babel/plugin-syntax-typescript@7.24.1(@babel/core@7.24.5):
resolution: {integrity: sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw==}
/@babel/plugin-syntax-typescript@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-plugin-utils': 7.24.5
'@babel/core': 7.24.6
'@babel/helper-plugin-utils': 7.24.6
dev: true
/@babel/plugin-transform-modules-commonjs@7.24.1(@babel/core@7.24.5):
resolution: {integrity: sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==}
/@babel/plugin-transform-modules-commonjs@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-module-transforms': 7.24.5(@babel/core@7.24.5)
'@babel/helper-plugin-utils': 7.24.5
'@babel/helper-simple-access': 7.24.5
'@babel/core': 7.24.6
'@babel/helper-module-transforms': 7.24.6(@babel/core@7.24.6)
'@babel/helper-plugin-utils': 7.24.6
'@babel/helper-simple-access': 7.24.6
dev: true
/@babel/plugin-transform-typescript@7.24.5(@babel/core@7.24.5):
resolution: {integrity: sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw==}
/@babel/plugin-transform-typescript@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-annotate-as-pure': 7.22.5
'@babel/helper-create-class-features-plugin': 7.24.5(@babel/core@7.24.5)
'@babel/helper-plugin-utils': 7.24.5
'@babel/plugin-syntax-typescript': 7.24.1(@babel/core@7.24.5)
'@babel/core': 7.24.6
'@babel/helper-annotate-as-pure': 7.24.6
'@babel/helper-create-class-features-plugin': 7.24.6(@babel/core@7.24.6)
'@babel/helper-plugin-utils': 7.24.6
'@babel/plugin-syntax-typescript': 7.24.6(@babel/core@7.24.6)
dev: true
/@babel/preset-typescript@7.24.1(@babel/core@7.24.5):
resolution: {integrity: sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==}
/@babel/preset-typescript@7.24.6(@babel/core@7.24.6):
resolution: {integrity: sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w==}
engines: {node: '>=6.9.0'}
peerDependencies:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.24.5
'@babel/helper-plugin-utils': 7.24.5
'@babel/helper-validator-option': 7.23.5
'@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5)
'@babel/plugin-transform-modules-commonjs': 7.24.1(@babel/core@7.24.5)
'@babel/plugin-transform-typescript': 7.24.5(@babel/core@7.24.5)
'@babel/core': 7.24.6
'@babel/helper-plugin-utils': 7.24.6
'@babel/helper-validator-option': 7.24.6
'@babel/plugin-syntax-jsx': 7.24.6(@babel/core@7.24.6)
'@babel/plugin-transform-modules-commonjs': 7.24.6(@babel/core@7.24.6)
'@babel/plugin-transform-typescript': 7.24.6(@babel/core@7.24.6)
dev: true
/@babel/template@7.24.0:
resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==}
/@babel/template@7.24.6:
resolution: {integrity: sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.24.2
'@babel/parser': 7.24.5
'@babel/types': 7.24.5
'@babel/code-frame': 7.24.6
'@babel/parser': 7.24.6
'@babel/types': 7.24.6
dev: true
/@babel/traverse@7.24.5:
resolution: {integrity: sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==}
/@babel/traverse@7.24.6:
resolution: {integrity: sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/code-frame': 7.24.2
'@babel/generator': 7.24.5
'@babel/helper-environment-visitor': 7.22.20
'@babel/helper-function-name': 7.23.0
'@babel/helper-hoist-variables': 7.22.5
'@babel/helper-split-export-declaration': 7.24.5
'@babel/parser': 7.24.5
'@babel/types': 7.24.5
'@babel/code-frame': 7.24.6
'@babel/generator': 7.24.6
'@babel/helper-environment-visitor': 7.24.6
'@babel/helper-function-name': 7.24.6
'@babel/helper-hoist-variables': 7.24.6
'@babel/helper-split-export-declaration': 7.24.6
'@babel/parser': 7.24.6
'@babel/types': 7.24.6
debug: 4.3.4
globals: 11.12.0
transitivePeerDependencies:
- supports-color
dev: true
/@babel/types@7.24.5:
resolution: {integrity: sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==}
/@babel/types@7.24.6:
resolution: {integrity: sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-string-parser': 7.24.1
'@babel/helper-validator-identifier': 7.24.5
'@babel/helper-string-parser': 7.24.6
'@babel/helper-validator-identifier': 7.24.6
to-fast-properties: 2.0.0
dev: true
@@ -563,8 +566,8 @@ packages:
dev: true
optional: true
/@iconify-json/simple-icons@1.1.102:
resolution: {integrity: sha512-ErRQGs7tjGsq4sj5SSeYwBOQ766yd9LtWblWakyL+ugg1k48ImabkI3mptDN5o+XSUb9SC+b7YNSStlrrecqNQ==}
/@iconify-json/simple-icons@1.1.103:
resolution: {integrity: sha512-u5r+Sirr0CME+Q0qUr6OgjErFpTSsGyttJbkfL5BUcRwELgN9FpCj8zYXySKTqCP1ttWIgAAiTC4ZKGoN5Gehw==}
dependencies:
'@iconify/types': 2.0.0
dev: true
@@ -850,12 +853,22 @@ packages:
resolution: {integrity: sha512-4bBX1pavDl2DSCozEII7bxYGT0IkyO7kKlUuCtooTePWyLjf2F7essdzHkJ00EpNR64kkebR9V0lqBMBo07VPw==}
dev: true
/@unocss/core@0.60.4:
resolution: {integrity: sha512-6tz8KTzC30oB0YikwRQoIpJ6Y6Dg+ZiK3NfCIsH+UX11bh2J2M53as2EL/5VQCqtiUn3YP0ZEzR2d1AWX78RCA==}
dev: true
/@unocss/extractor-arbitrary-variants@0.60.3:
resolution: {integrity: sha512-PnwNwkeAHmbJbrf5XN0xQG1KT1VQEye8neYn5yz1MHnT8Cj2nqjrqoCRGLCLhpOUg3/MNj+bpiA7hGnFbXWaCQ==}
dependencies:
'@unocss/core': 0.60.3
dev: true
/@unocss/extractor-arbitrary-variants@0.60.4:
resolution: {integrity: sha512-USuFGs5CLft9q7IGNdAEp1oliuUns+W7OO0Tx5qtx/oBh6pU/L93lcNNsuuGNrMU8BCmF3atx1/PEmGymgJ7VA==}
dependencies:
'@unocss/core': 0.60.4
dev: true
/@unocss/inspector@0.60.3:
resolution: {integrity: sha512-2cXAPA1yddB79mmpMXxPpSpizn4TskAsB7aSocbprOTYIU2Ff53gfkkijnLixrBvbG8xw91d9oPuI5Hm9GCyMQ==}
dependencies:
@@ -904,6 +917,14 @@ packages:
'@unocss/rule-utils': 0.60.3
dev: true
/@unocss/preset-mini@0.60.4:
resolution: {integrity: sha512-ZiHbP69vkyz0xmhqzC4B4PegwV+LPlZOBT7cRhsh0P8oPOQKYOyDRy4rAl+sJBJeIrggn1r1LgN+Z0Xvd8Ytcw==}
dependencies:
'@unocss/core': 0.60.4
'@unocss/extractor-arbitrary-variants': 0.60.4
'@unocss/rule-utils': 0.60.4
dev: true
/@unocss/preset-tagify@0.60.3:
resolution: {integrity: sha512-pzD6bgtGuIk7M1n/JQiR6EpwnVvafSTHoM70Jhf+T8MSuatDb+KFJCn3VELV2v38aikcUY5cTf95jqHQdzOAhQ==}
dependencies:
@@ -949,7 +970,15 @@ packages:
resolution: {integrity: sha512-I47/DcKQ2z12W80+Ffth0K6LzNvqcQPYRWk7KwVemVoEiGYamMV8/s+SbB26Fk9KUFjh+Ns/pGAo4iJZo0ueUQ==}
engines: {node: '>=14'}
dependencies:
'@unocss/core': 0.60.3
'@unocss/core': 0.60.4
magic-string: 0.30.10
dev: true
/@unocss/rule-utils@0.60.4:
resolution: {integrity: sha512-7qUN33NM4T/IwWavm9VIOCZ2+4hLBc0YUGxcMNTDZSFQRQLkWe3N5dOlgwKXtMyMKatZfbIRUKVDUgvEefoCTA==}
engines: {node: '>=14'}
dependencies:
'@unocss/core': 0.60.4
magic-string: 0.30.10
dev: true
@@ -960,9 +989,9 @@ packages:
/@unocss/transformer-attributify-jsx-babel@0.60.3:
resolution: {integrity: sha512-6WcEFPSaxscGR22dRUcNqY0ippC3/Q/LBVFVSCJh++hoIPVCZbxF505cPq/bOdF2bpNzj9yXW0OJt03nB505Hg==}
dependencies:
'@babel/core': 7.24.5
'@babel/plugin-syntax-jsx': 7.24.1(@babel/core@7.24.5)
'@babel/preset-typescript': 7.24.1(@babel/core@7.24.5)
'@babel/core': 7.24.6
'@babel/plugin-syntax-jsx': 7.24.6(@babel/core@7.24.6)
'@babel/preset-typescript': 7.24.6(@babel/core@7.24.6)
'@unocss/core': 0.60.3
transitivePeerDependencies:
- supports-color
@@ -1052,8 +1081,8 @@ packages:
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
hasBin: true
dependencies:
caniuse-lite: 1.0.30001621
electron-to-chromium: 1.4.780
caniuse-lite: 1.0.30001623
electron-to-chromium: 1.4.783
node-releases: 2.0.14
update-browserslist-db: 1.0.16(browserslist@4.23.0)
dev: true
@@ -1063,8 +1092,8 @@ packages:
engines: {node: '>=8'}
dev: true
/caniuse-lite@1.0.30001621:
resolution: {integrity: sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==}
/caniuse-lite@1.0.30001623:
resolution: {integrity: sha512-X/XhAVKlpIxWPpgRTnlgZssJrF0m6YtRA0QDWgsBNT12uZM6LPRydR7ip405Y3t1LamD8cP2TZFEDZFBf5ApcA==}
dev: true
/chalk@2.4.2:
@@ -1159,8 +1188,8 @@ packages:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
dev: true
/electron-to-chromium@1.4.780:
resolution: {integrity: sha512-NPtACGFe7vunRYzvYqVRhQvsDrTevxpgDKxG/Vcbe0BTNOY+5+/2mOXSw2ls7ToNbE5Bf/+uQbjTxcmwMozpCw==}
/electron-to-chromium@1.4.783:
resolution: {integrity: sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ==}
dev: true
/esbuild@0.20.2:

61
static/global.css Normal file
View File

@@ -0,0 +1,61 @@
@font-face {
font-family: Inter;
src: url(inter.woff2);
}
@font-face {
font-family: Cal Sans;
src: url(cal-sans.woff2);
}
@font-face {
font-family: Fira Code;
src: url(fira-code.woff2);
}
@keyframes anim-in {
from {
opacity: var(--anim-fade-from, 1);
transform:
translateY(var(--anim-slide-from-y, 0)) translateX(var(--anim-slide-from-x, 0));
}
to {
opacity: var(--anim-fade-to, 1);
transform:
translateY(var(--anim-slide-to-y, 0)) translateX(var(--anim-slide-to-x, 0));
}
}
@media (hover: hover) {
.cannot-hover {
display: none;
}
}
@media not all and (hover: hover) {
.can-hover {
display: none;
}
}
.animate {
animation-name: anim-in;
animation-delay: calc(var(--anim-delay, 0) * var(--anim-stagger, 1) * var(--start, 1));
animation-duration: var(--anim-duration, 1s);
animation-fill-mode: var(--anim--fill-mode, forwards);
animation-iteration-count: var(--anim-iter-count, 1);
animation-timing-function: var(--anim-timing, ease-in-out);
}
.fade-in {
--anim-fade-from: 0;
}
.slide-from-b {
--anim-slide-from-y: 1.7rem;
}
.slide-from-r {
--anim-slide-from-x: 1.7rem;
}

BIN
static/images/image-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
static/images/image-2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

BIN
static/images/image-3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

BIN
static/images/image-4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
static/images/image-5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

BIN
static/images/image-6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

BIN
static/images/image-7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View File

@@ -1 +0,0 @@
test

143
uno-utils.js Normal file
View File

@@ -0,0 +1,143 @@
/**
This file is licensed under the MIT license provided down below:
MIT License
Copyright (c) 2024-PRESENT Gustavo L. de Mello
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-------------------------------------------------------------------------------
This file has source code modified from the UnoCSS repository, licensed under the MIT
license. A copy of the original licensed is provided here https://github.com/unocss/unocss/blob/main/LICENSE
and down below:
MIT License
Copyright (c) 2021-PRESENT Anthony Fu <https://github.com/antfu>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* @param {string} str
* @param {string} [requiredType]
*
* @license MIT
* @author Anthony Fu <https://github.com/antfu>
*/
function bracketWithType(str, requiredType) {
if (str && str.startsWith('[') && str.endsWith(']')) {
/** @type {string | undefined } */
let base
/** @type {string | undefined } */
let hintedType
const bracketTypeRe = /^\[(color|length|size|position|quoted|string):/i
const match = str.match(bracketTypeRe)
if (!match) {
base = str.slice(1, -1)
}
else {
if (!requiredType)
hintedType = match[1]
base = str.slice(match[0].length, -1)
}
if (!base)
return
// test/preset-attributify.test.ts > fixture5
if (base === '=""')
return
if (base.startsWith('--'))
base = `var(${base})`
let curly = 0
for (const i of base) {
if (i === '[') {
curly += 1
}
else if (i === ']') {
curly -= 1
if (curly < 0)
return
}
}
if (curly)
return
switch (hintedType) {
case 'string': return base
.replace(/(^|[^\\])_/g, '$1 ')
.replace(/\\_/g, '_')
case 'quoted': return base
.replace(/(^|[^\\])_/g, '$1 ')
.replace(/\\_/g, '_')
.replace(/(["\\])/g, '\\$1')
.replace(/^(.+)$/, '"$1"')
}
return base
.replace(/(url\(.*?\))/g, v => v.replace(/_/g, '\\_'))
.replace(/(^|[^\\])_/g, '$1 ')
.replace(/\\_/g, '_')
.replace(/(?:calc|clamp|max|min)\((.*)/g, (match) => {
/** @type {string[]} */
const vars = []
return match
.replace(/var\((--.+?)[,)]/g, (match, g1) => {
vars.push(g1)
return match.replace(g1, '--un-calc')
})
.replace(/(-?\d*\.?\d(?!-\d.+[,)](?![^+\-/*])\D)(?:%|[a-z]+)?|\))([+\-/*])/g, '$1 $2 ')
.replace(/--un-calc/g, () => /** @type {string} */(vars.shift()))
})
}
}
/**
* @param {string} str
*
* @license MIT
* @author Anthony Fu <https://github.com/antfu>
*/
export function bracket(str) {
return bracketWithType(str)
}

View File

@@ -7,19 +7,175 @@ import {
transformerDirectives,
transformerVariantGroup,
} from 'unocss';
import { definePreset } from 'unocss';
import { colorResolver, variantGetParameter } from '@unocss/preset-mini/utils';
import * as utils from './uno-utils.js';
const presetForcedColors = definePreset(
/** @returns {import('unocss').Preset} */
() => {
return {
name: 'preset-forced-colors',
variants: [
{
name: 'forced-colors',
match(matcher, ctx) {
if (!matcher.startsWith('forced-colors:')) {
return matcher
}
return {
matcher: matcher.slice('forced-colors:'.length),
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$` : ''}@media(forced-colors: active)`,
parentOrder: 1000,
}),
}
/* handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$` : ''}@container${label ? ` ${label} ` : ''}${container}`,
parentOrder: order,
}), */
},
multiPass: true,
}
],
}
}
)
/**
* Preset based on https://github.com/tailwindlabs/tailwindcss-container-queries
*/
const presetContainers = definePreset(
/**
* @param {{ containers?: Record<string, string | number>}} [options={}]
*/
(options = {}) => {
const defaultContainers = {
'xs': '20rem' /* 320px */,
'sm': '24rem' /* 384px */,
'md': '28rem' /* 448px */,
'lg': '32rem' /* 512px */,
'xl': '36rem' /* 576px */,
'2xl': '42rem' /* 672px */,
'3xl': '48rem' /* 768px */,
'4xl': '56rem' /* 896px */,
'5xl': '64rem' /* 1024px */,
'6xl': '72rem' /* 1152px */,
'7xl': '80rem' /* 1280px */,
};
options.containers = {
...defaultContainers,
...Object.fromEntries(Object.entries(defaultContainers).map(e => [`h-${e[0]}`, e[1]])),
...Object.fromEntries(Object.entries(defaultContainers).map(e => [`w-${e[0]}`, e[1]])),
...options.containers,
};
/** @type {import('unocss').Preset} */
const preset = {
name: 'preset-containers',
rules: [
[/^@container(?:\/(\w+))?(?:-(normal|size))?$/, ([, l, v]) => {
return {
'container-type': v ?? 'inline-size',
'container-name': l,
}
}],
],
variants: [
{
name: '@',
match(matcher, ctx) {
if (matcher.startsWith('@container')) {
return matcher
}
const variant = variantGetParameter('@', matcher, ctx.generator.config.separators)
if (variant) {
const [match, rest, label] = variant;
const unit = utils.bracket(match);
/** @type {string | undefined } */
let container;
if (unit?.startsWith("h:")) {
container = `(min-height: ${unit.replace('h:', '')})`
} else if (unit?.startsWith("w:") || unit) {
container = `(min-width: ${unit.replace('w:', '')})`
} else {
/** @type {string | number} */
const size = options.containers?.[match] ?? '';
container =
`(${match.startsWith('h-') ? 'min-height' : 'min-width'}: ` +
`${typeof size === 'number' ? `${size}px` : size})`
}
if (!container) {
return
}
let order = (label ? 1000 : 2000) + Object.keys(options.containers ?? {}).indexOf(match);
return {
matcher: rest,
handle: (input, next) => next({
...input,
parent: `${input.parent ? `${input.parent} $$` : ''}@container${label ? ` ${label} ` : ''}${container}`,
parentOrder: order,
}),
}
}
},
multiPass: true,
}
],
}
return preset;
})
export default defineConfig({
theme: {
colors: {
'black': '#000000',
'white': '#ffffff',
'light-gray': '#9c9c9c',
'gray': '#383838',
'dark-gray': '#0c0c0c',
'mauve': '#cba6f7',
'yellow': '#f9e2af',
},
},
rules: [
[
'scrollbar',
{
'scrollbar-color': 'var(--un-scrollbar-thumb, #ddd) var(--un-scrollbar-track, #f5f5f5)',
},
],
[
/^(?:scrollbar-)?thumb-(?:color-)?(.+)$/,
// @ts-expect-error
colorResolver('--un-scrollbar-thumb', 'scrollbar-thumb'),
{ autocomplete: 'scrollbar-thumb-$colors' },
],
[
/^(?:scrollbar-)?track-(?:color-)?(.+)$/,
// @ts-expect-error
colorResolver('--un-scrollbar-track', 'scrollbar-thumb'),
{ autocomplete: 'scrollbar-track-$colors' },
],
],
cli: {
entry: {
patterns: [
'./{pages,layouts}/**/*.templ',
'./static/**/*.{js,css,html}',
'!./static/uno.css',
'./{components,layouts,pages}/*.templ',
'./static/*.{js,html}',
],
outFile: './static/uno.css',
},
},
presets: [
presetForcedColors(),
presetContainers(),
presetIcons(),
presetTypography(),
presetUno(),

View File

@@ -1,5 +1,16 @@
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"outputDirectory": "dist"
"outputDirectory": "dist",
"redirects": [
{
"source": "/robots.txt",
"destination": "/api/robots",
"statusCode": 301
},
{
"source": "/ai.txt",
"destination": "/api/ai",
"statusCode": 301
}
]
}