diff --git a/.gitignore b/.gitignore index 56638ca..9bb3d9d 100755 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ build public resources node_modules -hugo_stats.json \ No newline at end of file +hugo_stats.json + +*.crt +*.key \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 71f0e15..ccf6238 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,8 +2,7 @@ resources public static pnpm-lock.yaml -content/_index.md layouts/**/*.md layouts/partials/imgh.html -layouts/_default/_markup/render-heading.html +layouts/resume/_markup/render-heading.html build \ No newline at end of file diff --git a/README.md b/README.md index 0a6ab42..c11fe60 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,5 @@ # modern-hugo-resume -[![Hugo](https://img.shields.io/badge/Hugo-%5E0.115.3-ff4088?style=round-square&logo=hugo)](https://gohugo.io/) [![Tailwind CSS](https://img.shields.io/badge/Tailwind%20CSS-%5E3.3.3-38B2AC?style=round-square&logo=tailwind-css)](https://tailwindcss.com/) -[![Prettier](https://img.shields.io/badge/Prettier-%5E2.8.8-c596c7?style=round-square&logo=prettier)](https://prettier.io/) -[![Stylelint](https://img.shields.io/badge/Stylelint-%5E15.10.2-3578e5?style=round-square&logo=stylelint)](https://stylelint.io) - -## Overview - _A minimal static resume builder; inspired by [sproogen's modern-resume-theme](https://github.com/sproogen/modern-resume-theme) and [mnjul's html-resume](https://github.com/mnjul/html-resume). Powered by Hugo, Tailwind CSS, and GitHub Pages._ _Host your own resume on GitHub for free!_ @@ -68,12 +62,14 @@ To make changes and instantly see them at http://localhost:1313, run: pnpm dev ``` -To create a production build, run: +To make the server accessible over tailscale, run ```sh -pnpm build +pnpm dev:tailscale ``` -## Note +To create a production build, run: -This project contains a file `article_txt_replace.toml`, which is released under the terms of the Apache License, Version 2.0. A copy of the Apache License is available in the `data/plaintextreplace` directory of this project. Please see the Apache License for details regarding usage and distribution restrictions. +```sh +pnpm build +``` diff --git a/archetypes/default.md b/archetypes/default.md deleted file mode 100644 index 26f317f..0000000 --- a/archetypes/default.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true ---- diff --git a/assets/css/main.css b/assets/css/main.css index f83633d..cca1633 100644 --- a/assets/css/main.css +++ b/assets/css/main.css @@ -3,15 +3,17 @@ @tailwind utilities; @layer base { - html { - @apply bg-neutral-800 text-neutral-200; - + body { + /* TODO(cjshearer): remove when we update to tailwind >= v3.4.0 + https://github.com/tailwindlabs/tailwindcss/pull/12299 */ -webkit-tap-highlight-color: transparent; - font-family: Roboto, sans-serif; + + @apply prose prose-sm prose-invert prose-resume font-[Roboto,_sans-serif]; + @apply bg-neutral-800; } a { - @apply underline decoration-1 underline-offset-4 hover:text-neutral-100; + @apply underline decoration-1 underline-offset-4 hover:text-neutral-100 print:no-underline; } code { @@ -19,8 +21,27 @@ } } -@media print { - a { - text-decoration: none; +@layer components { + .avatar { + @apply relative aspect-square overflow-hidden rounded-full; + + /* after */ + @apply after:absolute after:top-0 after:block after:h-full after:w-full after:rounded-full after:[box-shadow:inset_0_0_20px_0_theme(colors.neutral.500)]; + } + + .button { + @apply relative flex h-12 w-12 items-center justify-center rounded-full; + + /* before */ + @apply before:absolute before:left-0 before:top-0 before:-z-10 before:h-full before:w-full before:scale-90 before:rounded-full before:duration-[250ms] before:[box-shadow:inset_0_0_0_3rem_currentColor]; + + /* hover:before */ + @apply hover:before:scale-100 hover:before:[box-shadow:inset_0_0_0_0.125rem_currentColor]; + + /* svg */ + @apply [&_svg]:inline [&_svg]:h-[58%] [&_svg]:w-[58%] [&_svg]:fill-current [&_svg]:text-neutral-800; + + /* hover:svg */ + @apply [&_svg]:hover:text-inherit; } } diff --git a/content/_index.md b/content/_index.md index 11a31e5..12aa334 100644 --- a/content/_index.md +++ b/content/_index.md @@ -1,26 +1,9 @@ --- -type: resume outputs: [html, txt] -avatar: avatar.jpg -links: - - svg: node_modules/@fortawesome/fontawesome-free/svgs/solid/globe - url: https://cjshearer.dev - name: Website - - svg: node_modules/@fortawesome/fontawesome-free/svgs/brands/github - url: https://github.com/cjshearer - name: GitHub - - svg: node_modules/@fortawesome/fontawesome-free/svgs/brands/linkedin - url: https://linkedin.com/in/cjshearer - name: LinkedIn - - svg: node_modules/@fortawesome/fontawesome-free/svgs/solid/envelope - url: mailto:cjshearer@live.com - name: Email -name: Cody Shearer -summary: | - Software Developer with 3 Years of Experience in Full Stack Web and Mobile Development -footer: | - Fully typeset with HTML and CSS — see [github.com/cjshearer/modern-hugo-resume](https://github.com/cjshearer/modern-hugo-resume) - +dateformat: + short: Jan. 2006 + long: January 2006 +title: Resume skills: - languages: - TypeScript @@ -67,9 +50,41 @@ skills: - SendGrid --- +{{
}} + +# Cody Shearer + +Software Developer with 3 Years of Experience in Full Stack Web and Mobile Development +{class="font-light mb-2"} + +[![GitHub: github.com/cjshearer](svgs/brands/github.svg)](https://github.com/cjshearer "GitHub") +[![LinkedIn: cjshearer.dev](svgs/brands/linkedin.svg)](https://linkedin.com/in/cjshearer "LinkedIn") +[![Email: cjshearer@live.com](svgs/solid/envelope.svg)](mailto:cjshearer@live.com "Email") +{class="[&>*]:button [&>*]:inline-flex [&>*]:mr-1 md:hidden"} + +{{
}} + +{{}} + +{{
}} + ## Experience -{{}} +### Software Developer – Full Stack, Krumware + +{{}} - Collaborated in cross-functional team following agile (scrum) methodologies - Improved time-to-market by up to 20% with project templates @@ -81,6 +96,7 @@ skills: - Promoted culture of continuous improvement, code reviews, and linting Project Highlights: + - Developed React app, React-Native app, Node servers for equipment manufacturer - Created Bluetooth abstraction with data anomaly filtering, connection recovery - Engineered data pipeline for real-time capture and display across applications @@ -93,27 +109,45 @@ Project Highlights: - Developed a React SPA and Node socket server for escape room company - Created multiplayer puzzle game with draggable puzzle pieces - Designed email notification system for automated booking reminders -{{}} -{{}} +### Research Assistant, AI and Systems Laboratory + +{{}} + - Analyzed cross-platform performance behavior of deep-learning recommender system - Reproduced results from past research on highly configurable systems - Researched relevant works on causal inference and machine learning -{{}} -{{}} +### Software Developer – Intern, Velocity + +{{}} - Created AWS storage primitive abstracting cloud complexity for high level orchestration - Developed storage optimization solution for Amazon Elastic Block Storage -{{}} ## Education -{{}} +### BS Computer Science, University of South Carolina + +{{}} -- Graduated [*magna cum laude*](pdf/usc-diploma.pdf) with a mathematics minor +- Graduated [_magna cum laude_](pdf/usc-diploma.pdf) with a mathematics minor - Achieved [Outstanding Senior Award](https://sc.edu/about/offices_and_divisions/leadership_and_service_center/awards_and_recognition/senior-awards/index.php) and the [Palmetto Fellows Scholarship](https://sc.edu/about/offices_and_divisions/financial_aid/scholarships/scholarships_for_sc_residents/palmetto_fellows/index.php) - Earned honors including President's List, Dean's List, and [Phi Beta Kappa](https://www.pbk.org/About) -- Served as President and Treasurer of the Carolina Movement Club (*parkour!*) +- Served as President and Treasurer of the Carolina Movement Club (_parkour!_) + +## Skills {.md:hidden} + +{{}} + +{{
}} + +{{}} diff --git a/assets/images/avatar.jpg b/content/avatar.jpg similarity index 100% rename from assets/images/avatar.jpg rename to content/avatar.jpg diff --git a/data/plaintextreplace/LICENSE b/data/plaintextreplace/LICENSE deleted file mode 100644 index f49a4e1..0000000 --- a/data/plaintextreplace/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff --git a/data/plaintextreplace/article_txt_replace.toml b/data/plaintextreplace/article_txt_replace.toml deleted file mode 100644 index 5d35054..0000000 --- a/data/plaintextreplace/article_txt_replace.toml +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright (c) 2023 Rebecca Sutton Koeser -# -# This code is derived from startwords -# (https://github.com/Princeton-CDH/startwords), which is released under the -# terms of the Apache License, Version 2.0 (the "License"); you may not use this -# file except in compliance with the License. You may obtain a copy of the -# License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. -# -# Changes from source: -# - remove URLs instead of altering them -# - added replacement to remove italics, modifying the "bold" replacement to -# accommodate this method -# - removed 'heading', 'js script', 'tweet group', and 'add newline' - -# Configure regular expressions for custom article text output. -# Arguments for replaceRE, applied iteratively to .RawContent. -# Patterns with backslashes must be encapsulated within single quotes. -# Use single backslashes to escape characters. Do not use double backslashes. -# Set skip = true to skip a particular replacement. - -[[args]] -pattern = '!\[([^\]]+)\]\([^\)]+\)' -replacement = "[IMAGE: $1]" -comment = "convert markdown image" - -[[args]] -pattern = '{{\<[^\>]+>}}' -replacement = "" -comment = "remove hugo shortcodes" - -[[args]] -pattern = '(?m)(<\/?[^>]+>)' -replacement = "" -comment = "remove html tags" - -[[args]] -pattern = '(?m)^\[\^(\d+)\]: ' -replacement = "$1. " -comment = "Convert footnote label from markdown syntax to numbered list" - -[[args]] -pattern = '\[\^(\d+)\]' -replacement = '[NOTE $1]' -comment = "Convert footnote reference from markdown syntax to human readable format" - -[[args]] -pattern = '\[([^\]]+)\]\(([^\)]+)\)' -replacement = "$1" -comment = "remove markdown urls" - -[[args]] -pattern = '\*([^*]+)\*' -replacement = "$1" -comment = "remove indicators for italic text" - -[[args]] -# this works only when used after the above replacement -pattern = '\*([^*]+)\*' -replacement = "$1" -comment = "remove indicators for bold text" - -[[args]] -pattern = '{#[a-z-0-9]+}' -replacement = "" -comment = "remove custom anchor names (markdown syntax)" - -[[args]] -pattern = '\[(.+)\]\(#.*\)' -replacement = "$1" -comment = "remove anchor links within the current document" - -[[args]] -pattern = '(?ms)^\s*$(^\s*$)+' -replacement = "" -comment = "Consolidate multiple newlines" diff --git a/hugo.yaml b/hugo.yaml index 16d38ae..f24ab4d 100644 --- a/hugo.yaml +++ b/hugo.yaml @@ -15,15 +15,23 @@ disableKinds: enableEmoji: true enableRobotsTXT: true languageCode: en-us +markup: + goldmark: + renderer: + unsafe: true + parser: + attribute: + block: true + title: true + wrapStandAloneImageWithinParagraph: false module: mounts: - source: assets target: assets - source: hugo_stats.json target: assets/watching/hugo_stats.json - - source: data - target: data - excludeFiles: plaintextreplace/LICENSE + - source: node_modules/@fortawesome/fontawesome-free/svgs + target: assets/svgs mediaTypes: text/plain: suffixes: @@ -33,6 +41,5 @@ outputFormats: mediaType: text/plain baseName: index isPlainText: true -title: "Cody Shearer" Params: faviconEmoji: 💼 diff --git a/layouts/404.html b/layouts/404.html index 95bad8a..88fdd29 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -1,6 +1,6 @@ - {{ partial "head.html" . }} + {{ partialCached "head.html" . }}
diff --git a/layouts/_default/_markup/render-heading.html b/layouts/_default/_markup/render-heading.html deleted file mode 100644 index 44d390f..0000000 --- a/layouts/_default/_markup/render-heading.html +++ /dev/null @@ -1 +0,0 @@ -{{ .Text | safeHTML }} \ No newline at end of file diff --git a/layouts/_default/_markup/render-heading.txt b/layouts/_default/_markup/render-heading.txt deleted file mode 100644 index 7a27331..0000000 --- a/layouts/_default/_markup/render-heading.txt +++ /dev/null @@ -1,7 +0,0 @@ -{{- if eq .Level 2 -}} - ------------------------------------------------------------------------------------------- -{{ .Text | strings.ToUpper -}} -{{- else -}} - TODO: implement me if this shows up -{{- end }} - diff --git a/layouts/_default/_markup/render-image.html b/layouts/_default/_markup/render-image.html new file mode 100644 index 0000000..941eea7 --- /dev/null +++ b/layouts/_default/_markup/render-image.html @@ -0,0 +1,42 @@ +{{- $src := .Page.Resources.GetMatch .Destination | default (resources.GetMatch .Destination) -}} +{{- $class := .Attributes.class -}} +{{- if eq "svg" $src.MediaType.SubType -}} + {{/* Derived from Utkarsh Verma's inline SVG */}} + {{/* https://bitbanged.com/posts/how-to-use-inline-svgs-with-hugo/ */}} + {{ $attributes := replaceRE `.*` "$1" $src.Content }} + {{ $svg := replaceRE `(.*)` "$1" $src.Content }} + + {{ $svg | safeHTML }} + +{{- else if in (slice "bmp" "gif" "jpeg" "png" "tif" "tiff" "webp") $src.MediaType.SubType -}} + {{/* Derived from Bryce Wray's image render hook */}} + {{/* https://github.com/brycewray/hugo-site/blob/33c3420768246006acf3b8f45792c545f7d01cec/layouts/_default/_markup/render-image.html */}} + {{- $width := $src.Width -}} + {{- $height := $src.Height -}} + {{- $sizes := split (.Attributes.sizes | default "320 640 960 1280 1600 1920") " " -}} + {{- $dataSizes := .Attributes.dataSizes | default "(min-width: 1024px) 100vw, 50vw" -}} + {{- $hint := .Attributes.hint | default "photo" -}} + {{- $filter := .Attributes.filter | default "MitchellNetravali" -}} + {{- $backupImage := $src.Process (print "resize 640x jpg " $filter) -}} + {{- $srcset := slice -}} + {{- range $sizes -}} + {{- if ge $width . -}} + {{ $resizedImageLink := ($src.Process (print "resize " . "x webp " $hint " " $filter)).RelPermalink }} + {{ $srcset = $srcset | append (print $resizedImageLink " " . "w") }} + {{- end -}} + {{- end -}} + {{ $srcset = delimit $srcset ", " }} + + + {{ $.Text }} + +{{- else -}} +

Image unavailable.

+{{- end -}} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html deleted file mode 100644 index 86f8724..0000000 --- a/layouts/_default/baseof.html +++ /dev/null @@ -1,8 +0,0 @@ - - - {{ partial "head.html" . }} - - {{ block "main" . }} - {{ end }} - - diff --git a/layouts/index.html b/layouts/index.html index f07decc..df7a8a2 100644 --- a/layouts/index.html +++ b/layouts/index.html @@ -1,18 +1,9 @@ -{{ define "main" }} -
+ + {{ partialCached "head.html" . }} + - {{ partial "resume/drawer" .Params }} -
- {{ partial "resume/header.html" .Params }} -
- {{ .Content }} -
- {{ partial "resume/footer" .Params }} -
-
-{{ end }} + {{ .Content }} + + diff --git a/layouts/index.txt b/layouts/index.txt index b75555d..455406b 100644 --- a/layouts/index.txt +++ b/layouts/index.txt @@ -1,17 +1,32 @@ -{{ .Params.name }} -{{ .Params.summary }} -------------------------------------------------------------------------------------------- -SKILLS - -{{ range .Params.Skills }} - {{- range $category, $items := . }} - {{- $category | strings.FirstUpper }}: {{ delimit $items ", " }} - {{- end }} -{{ end }} -{{ .Content -}} -------------------------------------------------------------------------------------------- -LINKS - -{{ range .Params.links }} - {{- .name}}: {{ partial "plainTextURI.html" .url }} -{{ end }} \ No newline at end of file +{{- /* Process Raw Content------------------------------------------------*/ -}} +{{- $raw := .RawContent -}} + +{{- /* join with preceding element */ -}} +{{- $raw = replaceRE `\s{2}({{\}})\s*` ", $1\n" $raw -}} + +{{- /* stylize headers */ -}} +{{- $raw = replaceRE `(?m)^#{1} (.+)` "$1" $raw -}} +{{- $raw = replaceRE `(?m)^#{2} (.+)` (printf "%s\n$1\n" (strings.Repeat 102 "-")) $raw -}} +{{- $raw = replaceRE `(?m)^#{3} (.+)` "● $1" $raw -}} + +{{- /* remove italic, bold, and italic-and-bold indicators */ -}} +{{- range seq 3 -}} + {{- $raw = replaceRE `\b_(.*?)_\b|\*(.*?)\*` "$1$2" $raw -}} +{{- end -}} + +{{- /* replace images and links with their text */ -}} +{{- $raw = replaceRE `!{0}\[(.*?)\]\(.*?\)` "$1" $raw -}} +{{- $raw = replaceRE `!{1}\[(.*?)\]\(.*?\)` "$1" $raw -}} + +{{- /* Process Rendered Content-------------------------------------------*/ -}} +{{- $content := $raw | .Page.RenderString -}} + +{{- /* remove hugo attributes */ -}} +{{- $content = replaceRE `{.*}\s?` "" $content -}} + +{{- /* consolidate multiple newlines */ -}} +{{- $content = replaceRE `(?m)^(\s*\n)+` "\n" $content -}} + +{{- $content = strings.TrimLeft "\n" $content -}} + +{{- $content }} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 77e5862..b4cb8cb 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -4,7 +4,7 @@ - {{ .Site.Title }} + {{ .Page.Title | default .Site.Title }} diff --git a/layouts/partials/imgh.html b/layouts/partials/imgh.html deleted file mode 100644 index 3c3068d..0000000 --- a/layouts/partials/imgh.html +++ /dev/null @@ -1,104 +0,0 @@ -{{/* - Credit to: - https://www.brycewray.com/posts/2022/06/responsive-optimized-images-hugo/ -*/}} -{{- $respSizes := slice "320" "640" "960" "1280" "1600" "1920" -}} -{{/* - These are breakpoints in pixels. Adjust these to fit your use cases. - Obviously, the more breakpoints, the more images you'll be producing. - (Fortunately, Hugo does that **really** fast, as you'd expect, but watch out - for any storage issues this can present either locally or in your online repo, - especially if you have a really large number of original images.) -*/}} -{{- $imgBase := "images/" -}} -{{/* - This will be from top-level `assets/images`, where we'll keep all images for - Hugo's processing (this makes them "global resources," as noted in the - documentation). -*/}} -{{- $src := resources.Get (printf "%s%s" $imgBase .src) -}} -{{- $alt := resources.Get .alt -}} -{{- $divClass := "" -}} -{{/* - The styling in $imgClass, below, makes an image fill the container - horizontally and adjust its height automatically for that, and then fade in - for the LQIP effect. Feel free to adjust your CSS/SCSS as desired. -*/}} -{{- $imgClass := "w-full h-auto animate-fade" -}} -{{- $dataSzes := "(min-width: 1024px) 100vw, 50vw" -}} -{{/* - Now we'll create the 20-pixel-wide LQIP and turn it into Base64-encoded data, - which is better for performance and caching. - */}} -{{- $LQIP_img := $src.Resize "20x jpg" -}} -{{- $LQIP_b64 := $LQIP_img.Content | base64Encode -}} -{{/* - $CFPstyle is for use in styling the div's background, as you'll see shortly. -*/}} -{{- $CFPstyle := printf "%s%s%s" "background: url(data:image/jpeg;base64," $LQIP_b64 "); background-size: cover; background-repeat: no-repeat;" -}} -{{/* - Then, we create a 640-pixel-wide JPG of the image. This will serve as the - "fallback" image for that tiny percentage of browsers that don't understand - the HTML `picture` tag. -*/}} -{{- $actualImg := $src.Resize "640x jpg" -}} -{{/* - Now we'll handle the LQIP background for the div that will contain the image - content; the conditional at the top controls whether we're doing inline - styling --- which is a no-no for a tight Content Security Policy (CSP). Here, - it checks whether we're using nonces (and thus a tight CSP), as spec'd in the - site config file. If so, it creates a new class, named with an md5 hash for - the value of $src, that the div can use to provide the LQIP background. - Otherwise, it inserts inline styling. **THEREFORE** . . . If you don't have a - problem with inline styling, feel free to use only the second option and avoid - the conditional altogether. -*/}} -{{- $imgBd5 := md5 $src -}} -{{- if .Site.Params.Nonces -}} - -
-{{- else -}} -
-{{- end -}} -{{/* - Now we'll build the `picture` which modern browsers use to decide which image, - and which format thereof, to show. Remember to put `webp` first, since the - browser will use the first format it **can** use, and WebP files usually are - smaller. After WebP, the fallback is the universally safe JPG format. -*/}} - - - - {{ $alt }} - -
\ No newline at end of file diff --git a/layouts/partials/plainTextURI.html b/layouts/partials/plainTextURI.html deleted file mode 100644 index c6d9560..0000000 --- a/layouts/partials/plainTextURI.html +++ /dev/null @@ -1,2 +0,0 @@ -{{/* Removes `scheme ":" ["//" authority]` */}} -{{ return replaceRE ".+:/*(.*)" "$1" . }} diff --git a/layouts/partials/resume/avatar.html b/layouts/partials/resume/avatar.html deleted file mode 100644 index 05ca5e8..0000000 --- a/layouts/partials/resume/avatar.html +++ /dev/null @@ -1,7 +0,0 @@ -
-
- {{ partial "imgh.html" (dict "src" .) }} -
-
diff --git a/layouts/partials/resume/drawer.html b/layouts/partials/resume/drawer.html deleted file mode 100644 index 8094ab1..0000000 --- a/layouts/partials/resume/drawer.html +++ /dev/null @@ -1,59 +0,0 @@ - - - - - diff --git a/layouts/partials/resume/footer.html b/layouts/partials/resume/footer.html deleted file mode 100644 index 9b6f59c..0000000 --- a/layouts/partials/resume/footer.html +++ /dev/null @@ -1,3 +0,0 @@ -
- {{ .footer | markdownify }} -
diff --git a/layouts/partials/resume/header.html b/layouts/partials/resume/header.html deleted file mode 100644 index 37ffae2..0000000 --- a/layouts/partials/resume/header.html +++ /dev/null @@ -1,26 +0,0 @@ -
-

- {{ .name }} -

- {{ with .summary }} -

- {{ . | markdownify }} -

- {{ end }} - -
diff --git a/layouts/partials/svg.html b/layouts/partials/svg.html deleted file mode 100644 index 1e9544b..0000000 --- a/layouts/partials/svg.html +++ /dev/null @@ -1,5 +0,0 @@ -{{/* Credit to https://bitbanged.com/posts/how-to-use-inline-svgs-with-hugo/ */}} -{{ $svg := .src }} -{{ $match := "(.*)" }} -{{ $replaceWith := printf `${2}` .size .size }} -{{ return (replaceRE $match $replaceWith (printf "%s.svg" $svg | readFile) | safeHTML) }} diff --git a/layouts/shortcodes/aside.html b/layouts/shortcodes/aside.html new file mode 100644 index 0000000..254129b --- /dev/null +++ b/layouts/shortcodes/aside.html @@ -0,0 +1,9 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} + + + diff --git a/layouts/shortcodes/aside.txt b/layouts/shortcodes/aside.txt new file mode 100644 index 0000000..695e39a --- /dev/null +++ b/layouts/shortcodes/aside.txt @@ -0,0 +1,2 @@ +{{/* Workaround for Hugo requiring evaluation of Inner */}} +{{- $workaround := .Inner -}} diff --git a/layouts/shortcodes/date-range.html b/layouts/shortcodes/date-range.html new file mode 100644 index 0000000..87ff7b8 --- /dev/null +++ b/layouts/shortcodes/date-range.html @@ -0,0 +1,34 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} + +{{- $format := .Page.Params.dateformat.short -}} +{{- $start := .Get "start" -}} +{{- $end := .Get "end" -}} +{{- $startFormatted := time.Format $format $start -}} +{{- $endFormatted := "now" -}} +{{- with $end -}} + {{- $endFormatted = time.Format $format $end -}} +{{- end -}} + + +
+ + {{- if ne $startFormatted $endFormatted -}} + + + {{- end -}} +
diff --git a/layouts/shortcodes/date-range.txt b/layouts/shortcodes/date-range.txt new file mode 100644 index 0000000..a8b3ecb --- /dev/null +++ b/layouts/shortcodes/date-range.txt @@ -0,0 +1,10 @@ +{{- $format := .Page.Params.dateformat.long -}} +{{- $start := .Get "start" -}} +{{- $end := .Get "end" | default "now" -}} +{{- with $start -}} + {{- $start = time.Format $format $start -}} +{{- end -}} +{{- with .Get "end" -}} + {{- $end = time.Format $format . -}} +{{- end -}} +{{- print $start " to " $end -}} diff --git a/layouts/shortcodes/footer.html b/layouts/shortcodes/footer.html new file mode 100644 index 0000000..a1af476 --- /dev/null +++ b/layouts/shortcodes/footer.html @@ -0,0 +1,7 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} +
+ {{ .Inner | .Page.RenderString }} +
diff --git a/layouts/shortcodes/footer.txt b/layouts/shortcodes/footer.txt new file mode 100644 index 0000000..695e39a --- /dev/null +++ b/layouts/shortcodes/footer.txt @@ -0,0 +1,2 @@ +{{/* Workaround for Hugo requiring evaluation of Inner */}} +{{- $workaround := .Inner -}} diff --git a/layouts/shortcodes/header.html b/layouts/shortcodes/header.html new file mode 100644 index 0000000..3a50816 --- /dev/null +++ b/layouts/shortcodes/header.html @@ -0,0 +1,7 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} +
+ {{ .Inner | .Page.RenderString }} +
diff --git a/layouts/shortcodes/header.txt b/layouts/shortcodes/header.txt new file mode 100644 index 0000000..89ca9fd --- /dev/null +++ b/layouts/shortcodes/header.txt @@ -0,0 +1 @@ +{{- .InnerDeindent -}} \ No newline at end of file diff --git a/layouts/shortcodes/main.html b/layouts/shortcodes/main.html new file mode 100644 index 0000000..5c72d08 --- /dev/null +++ b/layouts/shortcodes/main.html @@ -0,0 +1,9 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} +
+ {{ .Inner | .Page.RenderString }} +
diff --git a/layouts/shortcodes/main.txt b/layouts/shortcodes/main.txt new file mode 100644 index 0000000..3aa78df --- /dev/null +++ b/layouts/shortcodes/main.txt @@ -0,0 +1 @@ +{{ .InnerDeindent }} \ No newline at end of file diff --git a/layouts/shortcodes/resume/entry.html b/layouts/shortcodes/resume/entry.html deleted file mode 100644 index a85ff02..0000000 --- a/layouts/shortcodes/resume/entry.html +++ /dev/null @@ -1,33 +0,0 @@ -{{ $dateFormat := .Get "dateformat" | default "2006" }} -{{ $startDate := .Get "startdate" }} -{{ $endDate := .Get "enddate" | default "now" }} - -{{ with $startDate }} - {{ $startDate = time.Format $dateFormat $startDate }} -{{ end }} -{{ with .Get "enddate" }} - {{ $endDate = time.Format $dateFormat . }} -{{ end }} - -{{ with .Get "name" }} -

{{ . }}

-{{ end }} -{{ with $startDate }} -
-

{{ $endDate }}

-
-

{{ $startDate }}

-
-{{ end }} -{{ with .Get "affiliation" }} -

{{ . }}

-{{ end }} -
- {{ .Inner | .Page.RenderString }} -
diff --git a/layouts/shortcodes/resume/entry.txt b/layouts/shortcodes/resume/entry.txt deleted file mode 100644 index 704c7e1..0000000 --- a/layouts/shortcodes/resume/entry.txt +++ /dev/null @@ -1,18 +0,0 @@ -{{- $dateFormat := .Get "dateformat" | default "01/06" -}} -{{- $startDate := .Get "startdate" -}} -{{- $endDate := .Get "enddate" | default "now" -}} -{{- with $startDate -}} - {{- $startDate = time.Format $dateFormat $startDate -}} -{{- end -}} -{{- with .Get "enddate" -}} - {{- $endDate = time.Format $dateFormat . -}} -{{- end -}} -{{- $fullDate := printf "%s to %s" $startDate $endDate -}} -● {{ printf "%s, %s, %s" (.Get "name") (.Get "affiliation") $fullDate -}} -{{- $rawContent := .Inner -}} -{{- range .Site.Data.plaintextreplace.article_txt_replace.args -}} - {{- if not .skip -}} - {{- $rawContent = $rawContent | replaceRE .pattern .replacement -}} - {{- end -}} -{{- end -}} -{{- $rawContent -}} diff --git a/layouts/shortcodes/skills.html b/layouts/shortcodes/skills.html new file mode 100644 index 0000000..5530fa5 --- /dev/null +++ b/layouts/shortcodes/skills.html @@ -0,0 +1,37 @@ +{{- $class := "" -}} +{{- with .Get "class" -}} + {{- $class = . -}} +{{- end -}} +{{- $layout := .Get "layout" | default "horizontal" -}} +{{- with .Page.Params.skills -}} +
    + {{- range . -}} + {{- range $category, $skills := . -}} + {{- if eq "horizontal" $layout -}} +
  • +

    {{- $category | title -}}:

    +

    + {{- delimit $skills ", " -}} +

    +
  • + {{- else -}} +
  • + {{- range $skills -}} +

    {{ . }}

    + {{- end -}} +
  • + {{- end -}} + {{- end -}} + {{- end -}} +
+{{- end -}} diff --git a/layouts/shortcodes/skills.txt b/layouts/shortcodes/skills.txt new file mode 100644 index 0000000..43f70cc --- /dev/null +++ b/layouts/shortcodes/skills.txt @@ -0,0 +1,7 @@ +{{ with .Page.Params.Skills }} +{{ range . }} +{{ range $category, $items := . }} +{{- $category | strings.FirstUpper }}: {{ delimit $items ", " }} +{{- end }} +{{- end }} +{{ end }} diff --git a/package.json b/package.json index 5722c2b..46ea1fd 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "build": "pnpm run hugo:build", "clean": "pnpm run hugo:clean && rm -rf node_modules", "dev": "pnpm run hugo:serve", + "dev:tailscale": "./tailscale-dev.sh", "format:check": "pnpm format --check", "format:fix": "pnpm format --write", "format": "pnpm prettier .", diff --git a/tailscale-dev.sh b/tailscale-dev.sh new file mode 100644 index 0000000..edec920 --- /dev/null +++ b/tailscale-dev.sh @@ -0,0 +1,12 @@ +#!/bin/bash +DOMAIN=${HOSTNAME}.$(tailscale status --json | jq -j '.MagicDNSSuffix') +if ! openssl x509 -checkend 0 -noout -in "${DOMAIN}".crt; +then + sudo tailscale cert "${DOMAIN}" +fi +pnpm run dev \ + --baseURL "https://${DOMAIN}" \ + --bind "${HOSTNAME}" \ + --tlsCertFile "${DOMAIN}".crt \ + --tlsKeyFile "${DOMAIN}".key \ + "$@" diff --git a/tailwind.config.js b/tailwind.config.js index 77adb70..514eb1f 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,3 +1,5 @@ +const defaultTheme = require("tailwindcss/defaultTheme"); + /** @type {import('tailwindcss').Config} */ module.exports = { content: ["./hugo_stats.json"], @@ -7,13 +9,12 @@ module.exports = { ], theme: { extend: { - typography: () => ({ + typography: { DEFAULT: { css: { a: { color: false, fontWeight: false, - textDecoration: false, }, "blockquote p:first-of-type::before": false, "blockquote p:last-of-type::after": false, @@ -26,7 +27,36 @@ module.exports = { maxWidth: false, }, }, - }), + resume: { + css: { + h1: { + fontSize: defaultTheme.fontSize["2xl"][0], + fontWeight: defaultTheme.fontWeight.medium, + lineHeight: defaultTheme.fontSize["2xl"][1].lineHeight, + marginBottom: 0, + }, + h2: { + fontWeight: defaultTheme.fontWeight.medium, + marginBottom: "0.5em", + marginTop: 0, + }, + h3: { + fontWeight: defaultTheme.fontWeight.medium, + marginBottom: 0, + marginTop: 0, + }, + h4: { + fontSize: defaultTheme.fontSize["base"][0], + fontWeight: defaultTheme.fontWeight.light, + lineHeight: defaultTheme.fontSize["base"][1].lineHeight, + }, + p: { + marginBottom: 0, + marginTop: 0, + }, + }, + }, + }, // TODO(cjshearer): remove subgrid once // https://github.com/tailwindlabs/tailwindcss/pull/12298/files is // released @@ -36,11 +66,7 @@ module.exports = { subgrid: "subgrid", }, gridTemplateRows: { - resume: ` - min-content - 1fr - min-content - `, + resume: "repeat(3, min-content)", subgrid: "subgrid", }, // https://savvywombat.com.au/tailwind-css/grid-areas