Browse Source

Merge branch 'main' into wip (building but not checked for quality)

image-sizing
Logan McGrath 11 months ago
parent
commit
03d0dcf44e
  1. 2
      green.cabal
  2. 4
      site/404.md
  3. 2
      site/_drafts/lessons-from-sterling.md
  4. 2
      site/_drafts/sterling-with-memoization.md
  5. 0
      site/_layouts/bare-content.html
  6. 39
      site/_layouts/default.html
  7. 5
      site/_layouts/page.html
  8. 7
      site/_layouts/post.html
  9. 27
      site/_layouts/skeleton.html
  10. 142
      site/_partials/about-me.html
  11. 4
      site/_partials/employment-opportunities.html
  12. 0
      site/_partials/post-list.html
  13. 18
      site/_partials/teaser-list.html
  14. 39
      site/_posts/2012-11-07-using-perforce-chronicle-for-application-configuration.md
  15. 10
      site/_posts/2012-11-16-scm-backed-application-configuration-with-perforce.md
  16. 2
      site/_posts/2012-11-20-app-config-app-in-action.md
  17. 12
      site/_posts/2012-11-28-promoting-changes-with-app-config-app.md
  18. 10
      site/_templates/image.html
  19. 4
      site/_templates/robots.txt
  20. 2
      site/_templates/sitemap.xml
  21. 14
      site/_templates/youtube.html
  22. 4
      site/blog/archives.html
  23. 8
      site/blog/blog.html
  24. 4
      site/blog/drafts.html
  25. 6
      site/blog/index.html
  26. 9
      site/contact.md
  27. 75
      site/css/_code.sass
  28. 212
      site/css/_default.sass
  29. 42
      site/css/_theme.sass
  30. 12
      site/css/_theme.scss
  31. 30
      site/css/_variables.scss
  32. 79
      site/css/elements/_asides.scss
  33. 98
      site/css/elements/_code.scss
  34. 44
      site/css/elements/_containers.scss
  35. 73
      site/css/elements/_default.scss
  36. 53
      site/css/elements/_headers.scss
  37. 104
      site/css/fonts/_code.scss
  38. 20
      site/css/layout/_footer.scss
  39. 61
      site/css/layout/_header.scss
  40. 8
      site/css/layout/_main.scss
  41. 9
      site/css/layout/_post.scss
  42. 1
      site/css/main.sass
  43. 2
      site/css/main.scss
  44. 222
      site/css/pages/_homepage.scss
  45. 6
      site/css/screen-sizes/_huge-format.sass
  46. 1
      site/css/screen-sizes/_large-format.sass
  47. 1
      site/css/screen-sizes/_medium-format.sass
  48. 1
      site/css/screen-sizes/_small-format.sass
  49. 565
      site/css/vendor/_include-media.scss
  50. 7
      site/gen/_post.md
  51. BIN
      site/images/about-me/headshot-w-meatball-doge_768w.png
  52. 7
      site/index.html
  53. 38
      site/layouts/default.html
  54. 5
      site/layouts/post.html
  55. 16
      site/layouts/skeleton.html
  56. 100
      site/pages/about-me.md
  57. 13
      site/pages/contact.md
  58. 7
      site/pages/index.md
  59. 7
      site/pages/resume.md
  60. 1
      site/partials/employment-opportunities.md
  61. 3
      site/partials/image.html
  62. 19
      site/partials/previous-posts.html
  63. 10
      site/partials/teaser-list.html
  64. 7
      site/partials/youtube.html
  65. 7
      site/resume.md
  66. 4
      site/templates/robots.txt
  67. 2
      src/Green.hs
  68. 2
      src/Green/Compiler/Layout.hs
  69. 4
      src/Green/Config.hs
  70. 35
      src/Green/Context.hs
  71. 109
      src/Green/Context/Field.hs
  72. 12
      src/Green/Context/GitCommits.hs
  73. 1
      src/Green/Context/Post.hs
  74. 22
      src/Green/Route.hs
  75. 25
      src/Green/Rule.hs
  76. 163
      src/Green/Rule/Blog.hs
  77. 17
      src/Green/Rule/Css.hs
  78. 4
      src/Green/Rule/Feed.hs
  79. 27
      src/Green/Rule/Index.hs
  80. 23
      src/Green/Rule/Page.hs
  81. 2
      src/Green/Rule/Robot.hs
  82. 10
      src/Green/Rule/Sitemap.hs
  83. 12
      src/Green/Util.hs
  84. 24
      test/Green/RouteSpec.hs
  85. 38
      test/Green/Rule/BlogSpec.hs

2
green.cabal

@ -40,7 +40,9 @@ library
Green.Route
Green.Rule
Green.Rule.Blog
Green.Rule.Css
Green.Rule.Feed
Green.Rule.Index
Green.Rule.Js
Green.Rule.Page
Green.Rule.Robot

4
site/pages/404.md → site/404.md

@ -1,6 +1,6 @@
---
layout: default
title: "404 Not Found"
layout: page
title: 404 Field Not Found
updated: 2021-05-24T20:07:11-05:00
---

2
site/_drafts/lessons-from-sterling.md

@ -405,6 +405,6 @@ memoization becomes a near requirement in order to make lazy evaluation useful.
[virtually anywhere for anything]: http://brandonbyars.com/2008/07/21/orthogonality/
[directly into a language]: http://paulhammant.com/blog/crazy-bob-and-type-safety-for-dependency-injection.html/
[open/closed principle]: http://en.wikipedia.org/wiki/Open/closed_principle
[memoization]: $route-to("posts/2013-06-17-sterling-with-memoization.md")$
[memoization]: $getRoute("_drafts/sterling-with-memoization.md")$
[visitor pattern]: http://en.wikipedia.org/wiki/Visitor_pattern#Java_example
[single dispatch]: http://en.wikipedia.org/wiki/Multiple_dispatch#Java

2
site/_drafts/sterling-with-memoization.md

@ -133,7 +133,7 @@ function should not leverage memoization.
* [Commit containing memoization changes][]
* [Benchmark showing O(1) complexity][]
[last post]: $route-to("posts/2013-06-16-sterling-benchmarks.md")$
[last post]: $getRoute("_drafts/sterling-benchmarks.md")$
[Sterling]: https://github.com/lmcgrath/sterling
[Memoization]: https://en.wikipedia.org/wiki/Memoization
[Commit containing memoization changes]: https://github.com/lmcgrath/sterling/commit/7d69d49a911d2d916701fa973e02ffabe82afe9d

0
site/layouts/bare-content.html → site/_layouts/bare-content.html

39
site/_layouts/default.html

@ -0,0 +1,39 @@
---
layout: skeleton
---
<header class="page-header">
<div class="content-bound">
<div class="logo-icon"><a href="/"></a></div>
<h1 class="logo"><a href="/">This Field Was Green</a></h1>
<nav class="header-nav">
<a href='$getRoute("index.html")$'>Home</a>
<a href='$getRoute("blog/index.html")$'>Blog</a>
<a href='$getRoute("resume.md")$'>Resume</a>
<a href='$getRoute("contact.md")$'>Contact</a>
</nav>
</div>
</header>
<main class="page-content">
<div class="content-bound">
$body$
</div>
</main>
<footer>
<div class="content-bound">
<p class="copyright">Logan McGrath &copy; <span class="copyright-date">2012</span></p>
<div class="generated-by-hakyll">
<p>
Site proudly generated by <a href="http://jaspervdj.be/hakyll">Hakyll</a> and source commit <a class="commit-link" href="$gitWebUrl$/commit/$gitSha1$">[$gitSha1$] $gitMessage$</a>$if(isChanged)$ with local changes$endif$.
</p>
<p>
$if(isGenerated)$
This page was rendered from derived content.
$else$
This page was rendered from <a href="$gitWebUrl$/blob/$gitSha1$/$path$">$path$</a>.
$endif$
</p>
</div>
</div>
</footer>

5
site/_layouts/page.html

@ -0,0 +1,5 @@
---
layout: default
---
<h1 class="page-title">$title$</h1>
$body$

7
site/partials/post.html → site/_layouts/post.html

@ -1,7 +1,10 @@
---
layout: default
----
<article class="post">
<header>
<h1>$title$</h1>
<p class="published">
<h1 class="page-title post-title">$title$</h1>
<em class="published">
Posted on $date$
$if(author)$
by $author$

27
site/_layouts/skeleton.html

@ -0,0 +1,27 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
$if(siteTitle)$
<title>This Field Was Green - $siteTitle$</title>
$else$
<title>This Field Was Green - $title$</title>
$endif$
$if(author)$<link rel="author" content="$author$">$endif$
<link rel="icon" href="/images/grass.svg">
<link rel="stylesheet" href="/css/main.css">
<script src="/js/main.js"></script>
</head>
<body class="$if(body-class)$$body-class$$endif$">
$body$
</body>
</html>

142
site/_partials/about-me.html

@ -0,0 +1,142 @@
<section class="intro">
<aside class="meatball-headshot">
<figure>
<img width="288" height="384"
src='$getRoute("images/about-me/headshot-w-meatball-doge_400w.png")$'
title="Myself and Meatball. He's cute cuz he's little."
alt="Mysql and Meatball">
<figcaption>
Myself and Meatball, who is a very good boy and wearing his very best treat face.
</figcaption>
</figure>
</aside>
<div class="myself">
<h2>Hello!</h2>
<p>
I'm Logan McGrath, I'm a senior software engineer, and I specialize in a segment of software applications engineering that sits between the framework and the business logic. In my day job at <a href="https://creditkarma.com">Credit Karma</a> I work with a team to provide building blocks with which my fellow product engineers can write less code and more quickly deliver valuable features to members. By night I dabble in esoteric programming languages, theories, and tools to better hone my craft. It's what I like to do when my husband isn't encouraging me to go play outside.
</p>
<p>
I have been working in tech since 2007, where I started as just a wee web developer putting together shopping carts. I've since found my way into bigger projects.
</p>
</div>
<div class="life-itself">
<h2>My Life Away from Work</h2>
<p>
Every few months I try looping some electronic music, but I'm really bad at
it and I intend one day to share and self-deprecate.
</p>
<p>
When I'm away from the computer I'm spending time with my husband Dr. Corey Blanchette and our two dogs, Jellybean and Meatball. Corey cooks and I do the dishes if I can beat him to them. Most evenings we can be found on the patio enjoying my latest mixology attempt while he tries to teach me ways to remember different parts of human anatomy. For the most part all I can retain are the acronyms that sound inappropriate, and I'm happy to share them over a drink. One of my favorites is a mnemonic he was taught in school to name the "carpals", which I'm pretty sure is a kind of bone.
</p>
<p>
Sometimes I make bad drinks, but fortunately we have a reliable backup. We call it <em>The Bunny</em>, consisting of your choice of liquor, ginger beer, carrot juice, fresh lime, and a little bit of orange liqueur over the top. Adjust to taste and best served in a copper mug. Very refreshing, and it might even count as a serving of vegetables!
</p>
</div>
</section>
<section class="personal-stuff">
<aside class="meatball-jellybean">
<figure>
<img width="200" height="266"
src='$getRoute("images/about-me/meatball-n-jelly-doges_400w.png")$'
title="Meatball is the little one, Jellybean is the big one."
alt="Meatball and Jellybean">
<figcaption>
The little one is Meatball, the big one is Jellybean. Both are very good boys, <em>and they both know I have a treat in my hand.</em>
</figcaption>
</figure>
</aside>
<div class="my-life">
<h2>My Life as It Relates to My Site</h2>
<p>
<em>As this is my site and my life, all opinions I express here are my own. Let me know if I'm wrong.</em>
</p>
<p>
I like to share what makes life worthwhile. Sometimes that's helping my dogs figure out something new, or finding a really cool trick at work that helps my team out. Sometimes hard things have to happen in order for life to be worthwhile, and I can't promise that reading about what I share is easy. I've come to good places by way of some painful lessons both personally and professionally.
</p>
<p>
My goal isn't to express edgy opinions, technical or otherwise. It's as easy to express something <em>objectively harmful</em> and empower grotesque behavior as it is to simply to hate on <em>technology</em> and get some fake internet points. Anyone can write a page full of salt. Salt's a popular, low-effort genre. I want show people things that can be constructive, and I think this is an important bar for myself.
</p>
</div>
</section>
<section class="professional-offering">
<h1>My Professional Offering</h1>
<div class="professional-toolbox">
<h2>Tools of the Trade</h2>
<section class="skills foundations">
<h3>Foundations and Practices</h3>
<ul>
<li>Low Code</li>
<li>Frameworks and Platforms</li>
<li>Technical Enablement</li>
<li>Agile, Scrum, Kanban</li>
<li>Source Control</li>
<li>Test Automation</li>
<li>Experimentation</li>
<li>Test in Production</li>
<li>Automate the Hard Parts</li>
<li>Pair Programming</li>
<li>Mentorship</li>
<li>Continuous Improvement</li>
<li>Always Learning</li>
</ul>
</section>
<section class="skills languages">
<h3>Languages</h3>
<ul>
<li>Scala</li>
<li>Ruby</li>
<li>Python</li>
<li>Rust</li>
<li>Java <em>and</em> C#</li>
<li>Haskell</li>
<li>JavaScript</li>
<li>TypeScript</li>
<li>Sometimes Go!</li>
</ul>
</section>
<section class="skills databases">
<h3>Databases</h3>
<ul>
<li>Postgres</li>
<li>MySQL</li>
<li>Oracle</li>
<li>SQL Server</li>
<li>Mongo</li>
<li>Firebase</li>
<li>Thumb Drive</li>
</ul>
</section>
<section class="skills interfaces">
<h3>Interfaces</h3>
<ul>
<li>React</li>
<li>Angular</li>
<li>HTML, <em>by hand!</em></li>
</ul>
</section>
<section class="skills integrations">
<h3>Integrations</h3>
<ul>
<li>GraphQL</li>
<li>Protobuf</li>
<li>Thrift</li>
<li>gRPC</li>
<li>REST</li>
</ul>
</section>
<div class="applied">
<h2>Putting Technology to Work</h2>
<p>
My primary customers are technical teams looking to accelerate time to market for new features and changes. Product teams need solid building blocks to deliver these features and I work as a force multiplier by providing the low code frameworks, tools, and infrastructure required to ship quickly and be nimble to change. My goal as a professional is to craft systems that reduce the number of teams and organizations, and more importantly <em>time and cost</em>, required to ship work in order to maximize value to the business and better serve customers.
</p>
<h3>Making the Hard Work Matter</h3>
<p>
Engineers are too expensive to be putting together bespoke content with high rates of churn. Low code allows engineers to focus on the hard problems and enables more opportunities for businesses to better harness the value they bring. I mentor engineers to help them realize their full potential as technologists and become drivers in better engineering with less code.
</p>
$partial("_partials/employment-opportunities.html")$
</div>
</div>
</section>

4
site/_partials/employment-opportunities.html

@ -0,0 +1,4 @@
<h3>Looking for an Engineer?</h3>
<p>
For prospective employers, referrals, and recruiters: <em>I am happily employed</em>, though I welcome chats about prospects if you believe I am a good fit for your technical needs. I apply what works from my experience to technical teams and reinforce what the teams are already doing well. Sometimes my existing toolbelt doesn't work so well because unexpected problems can hard and no two projects are the same, but that's ok. Together we'll find a way to make things better.
</p>

0
site/partials/post-list.html → site/_partials/post-list.html

18
site/_partials/teaser-list.html

@ -0,0 +1,18 @@
<section class="teaser-list">
<h1>Recent Posts</h1>
$for(recentPosts)$
<section class="teaser-item">
<header>
<h2 class="post-title"><a href="$url$">$title$</a></h2>
<em class="published">
Posted on $date$
$if(author)$
by $author$
$endif$
</em>
</header>
$if(teaser)$$teaser$$endif$
<p class="read-more"><a href="$url$">Read more...</a></p>
</section>
$endfor$
</section>

39
site/_posts/2012-11-07-using-perforce-chronicle-for-application-configuration.md

@ -4,6 +4,7 @@ title: "Using Perforce Chronicle for application configuration"
author: "Logan McGrath"
date: 2012-11-07T13:54:00-05:00
published: 2012-11-07T13:54:00-05:00
updated: 2021-06-27T10:12:00-05:00
tags: Perforce, Configuration Management
---
@ -82,12 +83,12 @@ with PHP.
The source JSON configuration is the same, albeit sorted:
$include-code("json", "app-config/stack_configuration.json")$
$getCode("json", "app-config/stack_configuration.json")$
The `index.html` page has been modified from the original to support only the
basic _commit_ and _diffs_ functionality:
$include-code("html", "app-config/index.html")$
$getCode("html", "app-config/index.html")$
Both of these assets were added by performing:
@ -125,22 +126,22 @@ To create the module, the following paths need to be added:
Declare the module with `INSTALL/application/appconfig/module.ini`:
$include-code("ini", "app-config/module/module.ini")$
$getCode("ini", "app-config/module/module.ini")$
Add a view script for displaying plaintext
assets, `INSTALL/application/appconfig/views/scripts/index/index.phtml`:
$include-code("php", "app-config/module/views/scripts/index/index.phtml")$
$getCode("php", "app-config/module/views/scripts/index/index.phtml")$
Add a view script for displaying
diffs, `INSTALL/application/appconfig/views/scripts/index/diffs.phtml`:
$include-code("php", "app-config/module/views/scripts/index/diffs.phtml")$
$getCode("php", "app-config/module/views/scripts/index/diffs.phtml")$
And a controller
at `INSTALL/application/appconfig/controllers/IndexController.phtml`:
$include-code("php", "app-config/module/controllers/IndexController.php")$
$getCode("php", "app-config/module/controllers/IndexController.php")$
## AngularJS
@ -155,27 +156,27 @@ stack_configuration.json and post changes back.
From `http://localhost/appconfig/index.html`, the data from
stack_configuration.json is loaded into the form:
$img("/images/app-config/start.png")$
$img("img-config-form", "/images/app-config/start.png")$
Edits to stack_configuration.json can be made using the form, and the diffs
viewed by clicking on "View Diffs":
$img("/images/app-config/diffs.png")$
$img("img-config-diffs", "/images/app-config/diffs.png")$
The changes can be saved by entering a commit message and clicking "Commit
Changes". After which, clicking "View Diffs" will show no changes:
$img("/images/app-config/diffs-after-commit.png")$
$img("img-config-commit", "/images/app-config/diffs-after-commit.png")$
To show that edits have in fact been made to stack_configuration.json, go
to `http://localhost/stack_configuration.json`, select "History" and click on "
History List":
$img("/images/app-config/history.png")$
$img("img-config-history", "/images/app-config/history.png")$
Chronicle also provides an interface for viewing diffs between revisions:
$img("/images/app-config/history-diffs.png")$
$img("img-config-revisions", "/images/app-config/history-diffs.png")$
## Disk Usage
@ -257,6 +258,22 @@ repository and work independently of Chronicle.
I would like to thank the guys at Perforce for their assistance and answering
all my questions as I worked with Chronicle, especially Randy Defauw.
## Update 06/27/2021
This is the first blog post I have ever written. Paul Hammant, who I had met in other contexts previously, happened to be working out of the ThoughtWorks office in Dallas, TX the very same day I started at ThoughtWorks. He asked me if I knew PHP, which I did, and set me off to explore Perforce Chronicle as a solution for managing configuration.
I had never written professionally before or been aware of configuration management: I was very lucky to explore a passion space that Paul has worked within for a very long time. I don't believe I ever gave him a proper thanks. He gave me an opportunity that probably not a lot of people get in their early careers, and it was an invaluable experience that I learned a lot from and think about fairly often.
The other posts in this series were also written with guidance from Paul:
- $linkedTitle("_posts/2012-11-16-scm-backed-application-configuration-with-perforce.md")$
- $linkedTitle("_posts/2012-11-20-app-config-app-in-action.md")$
- $linkedTitle("_posts/2012-11-28-promoting-changes-with-app-config-app.md")$
The subject of configuration as described in these posts is still fresh even after nearly ten years. Even now configuration as code still doesn't have a perfect solution, though products have become available that make managing configuration easier. Changing configuration in a running process as a general solution remains elusive, as supporting it imposes a lot of constraints on design.
On a more personal note: today is Pride. This is the first Pride I've ever participated in and only in the last two years have I felt safe enough to come out in circles beyond close friends. I was out to Paul but only as a detail I confided in passing. When I was working with Paul on these posts he advised that I should consider relocating to the Bay Area. In January, 2013, I moved to San Francisco. Discovering my own life as a _person_ was set by Paul being brave enough to share a deeply personal piece of advice. I'm so thankful he said it, and I'm glad I listened.
[proof of concept]: http://paulhammant.com/2012/08/14/app-config-using-git-and-angular/
[Perforce]: http://en.wikipedia.org/wiki/Perforce
[Perforce Chronicle]: http://www.perforce.com/products/chronicle

10
site/_posts/2012-11-16-scm-backed-application-configuration-with-perforce.md

@ -41,21 +41,21 @@ All installation and example setup details may be found in
When you login, you should see this screen:
$img("/images/app-config2/start.png")$
$img("img-app-start", "/images/app-config2/start.png")$
You'll notice I made the extra effort to add colors and drop shadows :D The
application works from the project root in Perforce, so the files in each branch
are viewable here. Clicking on "Dev" > "aardvark_configuration.html" will bring
up a form for editing `aardvark_configuration.json` as in the previous version:
$img("/images/app-config2/aardvark_configuration.png")$
$img("img-app-config", "/images/app-config2/aardvark_configuration.png")$
Changes to the form data are automatically saved. After making a view edits, you
can click "View Diff" to get the diffs or "Revert" your changes. Go ahead and
change the email address and fiddle around with the banned nicks, then go click
"Pending Changes":
$img("/images/app-config2/changes.png")$
$img("img-app-changes", "/images/app-config2/changes.png")$
This screen shows all files that were changed and their diffs as well. You can
"Revert" each file individually, and if you want to commit all changes, then
@ -63,7 +63,7 @@ enter a commit message and click "Commit Changes". If you commit the changes and
go back to "Dev" > "aardvark_configuration.html", you'll see the new values in
the form:
$img("/images/app-config2/aardvark_configuration-changed.png")$
$img("image-app-commit", "/images/app-config2/aardvark_configuration-changed.png")$
## Security and Permissions
@ -170,7 +170,7 @@ existing infrastructure.
The reason I point out Subversion and TFS is largely due to support of
per-branch permissions.
[last post]: $route-to("posts/2012-11-07-using-perforce-chronicle-for-application-configuration.md")$
[last post]: $getRoute("_posts/2012-11-07-using-perforce-chronicle-for-application-configuration.md")$
[forked]: https://github.com/lmcgrath/App-Config-App/
[AngularJS]: http://angularjs.org/
[App-Config-App's README]: https://github.com/lmcgrath/app-config-app/blob/master/README.md

2
site/_posts/2012-11-20-app-config-app-in-action.md

@ -15,7 +15,7 @@ configuration without reloading the UI.
<!--more-->
$youtube("hZbQhF6fsEo")$
$youtube("app-config-demo", "hZbQhF6fsEo")$
## Making it work for yourself

12
site/_posts/2012-11-28-promoting-changes-with-app-config-app.md

@ -40,7 +40,7 @@ staging-prod staging prod
If you login to App-Config-App and go to "Promote Changes," you get an interface
showing these relationships:
$img("/images/app-config3/promote_changes.png")$
$img("img-promote-changes", "/images/app-config3/promote_changes.png")$
Changes between environments can be promoted in either direction along a mapping
configuration. The receiving environment accepts all changes (developers would
@ -49,11 +49,11 @@ the changes by clicking on the "Pending Changes" link.
For example, I've promoted changes from "qa" to "dev":
$img("/images/app-config3/promote_result.png")$
$img("img-promote-result", "/images/app-config3/promote_result.png")$
I can then review the changes by clicking on "Pending Changes":
$img("/images/app-config3/pending_changes.png")$
$img("img-pending-changes", "/images/app-config3/pending_changes.png")$
Changes may be edited or reverted before committing them.
@ -66,7 +66,7 @@ changes get promoted, but it requires a little more work.
I've connected P4V to my App-Config-App user workspace to perform the same
promotion from "qa" to "dev":
$img("/images/app-config3/p4v.png")$
$img("img-config-promotion", "/images/app-config3/p4v.png")$
Select the "qa" folder, then from the menu bar go to "Actions" >
"Merge/Integrate". This will bring up a wizard for performing the integration.
@ -82,12 +82,12 @@ Resolve option: "Accept source"
And ensure the direction of integration is "Target" < "Source":
$img("/images/app-config3/p4v_integrate.png")$
$img("img-config-integrate", "/images/app-config3/p4v_integrate.png")$
Finally, click "Merge". If you expand the "dev" folder, you can see the where
the changes are:
$img("/images/app-config3/p4v_integrate_result.png")$
$img("img-config-results", "/images/app-config3/p4v_integrate_result.png")$
You are now free to modify the files further before finally committing the
changes.

10
site/_templates/image.html

@ -0,0 +1,10 @@
<aside id="$imgId$-aside" class="image">
<figure>
<a href="$imgSrc$" class="image-link">
<img id="$imgId$" src="$imgSrc$" title="$imgTitle$" alt="$imgAlt$">
</a>
</figure>
$if(imgTitle)$
<figcaption>$imgTitle$</figcaption>
$endif$
</aside>

4
site/_templates/robots.txt

@ -0,0 +1,4 @@
# Generated from commit $gitSha1$
User-agent: *
Disallow: $siteRoot$/drafts/*
Sitemap: $siteRoot$/sitemap.xml

2
site/templates/sitemap.xml → site/_templates/sitemap.xml

@ -7,7 +7,7 @@
xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">
$for(pages)$
<url>
<loc>$site-root$$url$</loc>
<loc>$siteRoot$$url$</loc>
<lastmod>$if(updated)$$updated$$else$$if(date)$$date$$endif$$endif$</lastmod>
<changefreq>$if(changefreq)$$changefreq$$else$weekly$endif$</changefreq>
<priority>$if(priority)$$priority$$else$0.8$endif$</priority>

14
site/_templates/youtube.html

@ -0,0 +1,14 @@
<aside id="$youtubeAsideId$" class="youtube">
<figure>
<iframe src="https://www.youtube.com/embed/$youtubeVideoId$"
title="$youtubeVideoTitle$"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen>
</iframe>
</figure>
$if(youtubeVideoTitle)$
<figcaption>
$youtubeVideoTitle$
</figcaption>
$endif$
</aside>

4
site/blog/archives.html

@ -1,9 +1,9 @@
---
layout: default
layout: page
title: "These Posts Were Green"
updated: 2021-05-24T20:07:11-05:00
---
Here you can find all my previous posts:
$partial("partials/post-list.html")$
$partial("_partials/post-list.html")$

8
site/blog/blog.html

@ -1,8 +0,0 @@
---
layout: default
title: "This Blog Was Green"
updated: 2021-05-24T20:07:11-05:00
---
$latest-post$
$partial("partials/previous-posts.html")$

4
site/blog/drafts.html

@ -1,8 +1,8 @@
---
layout: default
layout: page
title: "These Drafts Are Still Green"
updated: 2021-05-24T20:07:11-05:00
---
Here you can find all my drafts:
$partial("partials/post-list.html")$
$partial("_partials/post-list.html")$

6
site/blog/index.html

@ -0,0 +1,6 @@
---
layout: page
updated: 2021-05-24T20:07:11-05:00
---
$latestPost$
$partial("_partials/teaser-list.html")$

9
site/contact.md

@ -0,0 +1,9 @@
---
layout: page
title: Contact
updated: 2021-05-24T20:07:11-05:00
---
Please contact me via [blog@thisfieldwas.green](mailto:blog@thisfieldwas.green). I welcome conversations about what I do or related subjects, and I'm happy to answer any questions and ask a few of my own!
$partial("_partials/employment-opportunities.html")$

75
site/css/_code.sass

@ -1,75 +0,0 @@
code
color: $color-em-text
font-family: $code-font-family
font-size: $code-font-size
font-variant-ligatures: none
white-space: pre-wrap
word-wrap: break-word
// keyword
.kw, .cf
color: seagreen
font-weight: bold
.op
color: orangered
.ot
color: slateblue
.dt
color: blue
// function
.fu
color: blueviolet
.st
color: lightseagreen
// character
.ch
color: yellowgreen
.cn
color: blueviolet
.at
color: darkblue
.va
color: cornflowerblue
pre
@include scrollbars
overflow: scroll
margin-right: 0.5rem
code.sourceCode
@include bordered-figure
// background-color: $bg-greenfield
display: table
padding: 0.5rem 0
margin-bottom: 0.5rem
white-space: pre
word-wrap: initial
.line
display: table-row
&:target
background-color: $color-highlight
&:hover
background-color: $color-hover
.line-number
display: table-cell
padding: 0 0.5rem 0 0.5rem
border-right: $border-thin solid $border-color-sides
text-align: right
user-select: none
text-decoration: none
.line-content
display: table-cell
padding: 0 0.5rem
width: 100%

212
site/css/_default.sass

@ -1,212 +0,0 @@
@import "theme"
@import "code"
*
line-height: 1.6em
html
width: 100%
height: 100%
margin: 0
padding: 0
background-color: $color-greenfield
font-family: $text-font-family
font-size: $text-font-size
font-variant: discretionary-ligatures
background-color: $color-greenfield
body
margin: 0
padding: 0
color: $color-text
background-color: $bg-content
overflow: scroll
> header
@include body-block
border-top: 0.7rem solid $border-color
border-bottom: $border-very-thick solid $border-color
> nav
font-size: 0
> a
font-size: $text-font-size
display: inline-block
line-height: 1.2em
& + a
margin-left: 0.5rem
padding-left: 0.5rem
border-left: $border-regular solid $border-color
nav
border-top: 0.1rem
max-width: 75rem
margin: 0 auto
footer
@include body-block
border-bottom: 0.7rem solid $border-color
border-top: $border-very-thick solid $border-color
padding-bottom: 1rem
clear: both
> *
max-width: 75rem
margin: 0 auto
main
@include body-block
margin: 0 auto
max-width: 75rem
a
color: dodgerblue
text-decoration: underline
h1, h2, h3, h4, h5, h6
line-height: 1.2em
color: $color-em-text
h1
font-size: 2rem
h2
font-size: 1.6rem
h3
font-size: 1.4rem
h4
font-size: 1.2rem
h5
font-size: 1rem
h6
font-size: 0.9rem
.post
header
h1
display: none
.published
font-size: 1.4rem
font-style: italic
color: slategrey
.logo
max-width: 75rem
margin: 0 auto 0.5rem
a
font-weight: bold
color: $color-greenfield
text-decoration: none
.logo-icon
display: block
float: right
width: 3.5rem
height: 3.5rem
background-image: url("/images/grass.svg")
background-size: 3.5rem
strong, em, b, i
color: $color-em-text
p
&.image
overflow-x: scroll
@include scrollbars
img
@include bordered-figure
&.youtube
text-align: center
blockquote
margin-left: 2rem
padding-left: 0.5rem
border-left: 0.1rem solid $color-em-text
color: $color-em-text
font-style: italic
iframe
border: none
.teaser-list
> header h1
padding: 0.6rem 0
margin: 0
background-color: $bg-greenfield
border-top: 0.2rem solid $color-text
border-bottom: 0.05rem solid $color-text
.post
header
h1
display: block
font-size: 1.4rem
em
font-size: 1.2rem
.read-more
display: block
padding: 0.5rem 0
background-color: $bg-greenfield
border-bottom: 0.05rem solid $color-text
.copyright
font-size: 0.9rem
.generated-by-hakyll
font-size: 0.8rem
.generated-from
font-size: 0.9rem
.tools-flexbox
display: flex
flex-direction: row
flex-wrap: wrap
justify-content: flex-start
align-items: space-between
align-content: flex-start
> div
& + div
margin-left: 1rem
padding-left: 1rem
border-left: $border-regular solid $border-color
h3
margin-bottom: 0
padding-bottom: 0
ul
padding-left: 1rem
margin-left: 0
@import "screen-sizes/small-format"
@import "screen-sizes/medium-format"
@import "screen-sizes/large-format"
@import "screen-sizes/huge-format"
// cover all smartphones in portrait mode
@media only screen and (max-width: 420px)
@include small-format
// most smartphones in landscape mode
@media only screen and (min-width: 421px) and (max-width: 767px)
@include small-format
// most Android tablets and iPads in portrait mode
@media only screen and (min-width: 768px) and (max-width: 1023px)
@include medium-format
//most Android tablets and iPads in landscape mode, older desktop/laptop monitors
@media only screen and (min-width: 1024px) and (max-width: 1365px)
@include medium-format
// iPad PRO, HDready and FullHD desktop laptop monitors
@media only screen and (min-width: 1366px) and (max-width: 1919px)
@include large-format
// 4K and above
@media only screen and (min-width: 1920px)
@include huge-format

42
site/css/_theme.sass

@ -1,42 +0,0 @@
@import "fonts/code"
$text-font-family: "Georgia", serif
$text-font-size: 1rem
$code-font-family: "JetBrains Mono", monospace
$code-font-size: 85% // because JetBrains Mono runs a bit big
$color-greenfield: darkgreen
$color-text: darkslategray
$color-em-text: darkgreen
$color-highlight: #FFFAB0
$color-hover: lemonchiffon
$bg-content: white
$bg-greenfield: honeydew
$border-very-thick: 0.3rem
$border-thick: 0.2rem
$border-regular: 0.1rem
$border-thin: 0.05rem
$border-color: change-color($color-greenfield, $green: 80%)
// $border-color-sides: change-color($border-color, $lightness: 30%)
$border-color-sides: change-color($color-greenfield, $green: 80%)
@mixin body-block
margin: 0
padding: 1rem
@mixin bordered-figure
border-top: $border-thick solid $border-color
border-bottom: ($border-thick * 1.5) solid $border-color
border-left: $border-thin dotted $border-color-sides
border-right: $border-thin dotted $border-color-sides
box-sizing: border-box
@mixin scrollbars
&::-webkit-scrollbar
height: 0.5rem
width: 0.5rem
&::-webkit-scrollbar-thumb
background-color: cadetblue
border-radius: 0.5rem

12
site/css/_theme.scss

@ -0,0 +1,12 @@
@import "vendor/include-media";
@import "fonts/code";
@import "elements/default";
@import "elements/containers";
@import "elements/headers";
@import "elements/asides";
@import "elements/code";
@import "layout/header";
@import "layout/main";
@import "layout/footer";
@import "layout/post";

30
site/css/_variables.scss

@ -0,0 +1,30 @@
$text-font-family: "Georgia", serif;
$text-font-size: 1rem;
$text-hyphens: none;
$text-align-default: left;
$code-font-family: "JetBrains Mono", monospace;
$code-font-size: 80%; // because JetBrains Mono runs a bit big
$color-green: darkgreen;
$color-green-light: lighten($color-green, 78%);
$color-text: darkslategray;
$color-text-em: $color-green;
$color-highlight: yellow;
$color-hover: lemonchiffon;
$bg-content: ivory;
$border-ginormous-width: 0.5rem;
$border-very-thick-width: 0.4rem;
$border-thick-width: 0.3rem;
$border-regular-width: 0.2rem;
$border-thin-width: 0.1rem;
$border-color: darken($color-green, 4%);
$border-style: solid $border-color;
$border-ginormous: $border-ginormous-width $border-style;
$border-very-thick: $border-very-thick-width $border-style;
$border-thick: $border-thick-width $border-style;
$border-regular: $border-regular-width $border-style;
$border-thin: $border-thin-width $border-style;

79
site/css/elements/_asides.scss

@ -0,0 +1,79 @@
@import "../variables";
@import "containers";
aside {
display: flex;
flex-direction: column;
align-items: center;
> * {
flex-basis: 0;
}
figure {
background-color: $color-green-light;
margin: 1rem 0.5rem;
padding: 0.75rem 1.5rem;
border-top: $border-regular;
border-bottom: $border-thin;
text-align: center;
.image-link {
display: inline-block;
margin: 0 auto;
}
figcaption {
color: darken($color-green, 10%);
font-size: 1rem;
text-align: center;
padding: 0.5rem;
margin: 0.5rem 0 0;
}
@include media('<tablet') {
padding-left: 0.5rem;
padding-right: 0.5rem;
margin: 0;
img {
height: auto;
margin: 0 auto;
}
}
@include media('>=tablet') {
display: grid;
grid-auto-columns: min-content;
img {
margin: 0 1rem;
}
}
}
&.image {
figure {
border-top: none;
img {
margin: 0;
padding: 0;
}
}
@include media('>=tablet') {
figure {
border-top: none;
display: block;
img {
width: 100%;
}
}
}
@include media("<tablet") {
figure {
border-top: none;
img {
width: 100%;
}
}
}
}
}

98
site/css/elements/_code.scss

@ -0,0 +1,98 @@
code {
color: $color-text-em;
font-family: $code-font-family;
font-size: $code-font-size;
font-variant-ligatures: none;
white-space: pre-wrap;
word-wrap: break-word;
// keyword
.kw, .cf {
color: seagreen;
font-weight: bold;
}
.op {
color: orangered;
}
.ot {
color: slateblue;
}
.dt {
color: blue;
}
// function
.fu {
color: blueviolet;
}
.st {
color: lightseagreen;
}
// character
.ch {
color: yellowgreen;
}
.cn {
color: blueviolet;
}
.at {
color: darkblue;
}
.va {
color: cornflowerblue;
}
}
div.sourceCode {
@include scrollable;
margin-left: 1rem;
margin-right: 1rem;
code.sourceCode {
background-color: lighten($color-green, 78%);
border-top: $border-regular;
border-bottom: $border-thin;
display: table;
white-space: pre;
word-wrap: initial;
.line {
display: table-row;
&:target {
background-color: $color-highlight;
}
&:hover {
background-color: $color-hover;
}
&:first-child > * {
padding-top: 0.3rem;
}
&:last-child > * {
padding-bottom: 0.3rem;
}
}
.line-number {
display: table-cell;
padding: 0 0.5rem 0 0.5rem;
border-right: $border-thin;
text-align: right;
user-select: none;
text-decoration: none;
}
.line-content {
display: table-cell;
padding: 0 0.5rem;
width: 100%;
}
}
}

44
site/css/elements/_containers.scss

@ -0,0 +1,44 @@
@mixin body-segment {
margin: 0;
padding: 0 1rem;
.content-bound {
max-width: 75rem;
margin: 0 auto;
text-align: $text-align-default;
@content
}
}
@mixin segment {
margin: 1rem 0;
}
@mixin container {
@include segment;
padding: 1rem 0.5rem;
}
@mixin scrollable {
overflow: hidden;
& > * {
overflow-x: scroll;
}
&::-webkit-scrollbar {
height: 0.5rem;
width: 0.5rem;
}
&::-webkit-scrollbar-thumb {
background-color: cadetblue;
border-radius: 0.5rem;
}
}
@mixin grid-container {
display: grid;
grid-gap: 1rem;
}

73
site/css/elements/_default.scss

@ -0,0 +1,73 @@
@import "variables";
@import "containers";
* {
line-height: 1.6
}
html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
background-color: $color-green;
font-family: $text-font-family;
font-size: $text-font-size;
font-variant: discretionary-ligatures;
text-align: $text-align-default;
hyphens: $text-hyphens;
}
body {
margin: 0;
padding: 0;
color: $color-text;
background-color: $bg-content;
overflow: scroll;
}
strong, em, b, i {
color: $color-text-em
}
p {
@include segment;
&.youtube {
text-align: center;
}
}
blockquote {
background-color: $color-green-light;
margin: 0.5rem 1rem;
padding: 0.5rem 1rem;
border-left: $border-regular;
border-right: $border-thin;
color: $color-text-em;
font-style: italic;
& > *:first-child {
margin-top: 0;
}
& > *:last-child {
margin-bottom: 0;
}
}
iframe {
border: none;
}
nav {
border-top: 0.1rem;
max-width: 75rem;
margin: 0 auto;
}
a {
color: dodgerblue;
text-decoration: underline;
}
.image-link {
text-decoration: none;
}

53
site/css/elements/_headers.scss

@ -0,0 +1,53 @@
@import "containers";
h1, h2, h3, h4, h5, h6 {
@include segment;
line-height: 1.2;
padding: 0;
color: $color-text-em;
a {
color: inherit;
text-decoration: none;
&:hover {
color: dodgerblue;
}
}
}
section h1 {
border-top: $border-regular;
border-bottom: $border-thin;
padding: 0.5rem 0;
}
h1 {
font-size: 1.4rem;
&.logo {
border: none;
}
&.page-title {
border-bottom: $border-thin;
padding: 0 0 0.5rem;
}
}
h2 {
font-size: 1.3rem;
}
h3 {
font-size: 1.2rem;
}
h4 {
font-size: 1.1rem;
}
h5 {
font-size: 1rem;
}
h6 {
font-size: 0.9rem;
}
@include media("<tablet") {
section > h1, section > header h1 {
text-align: center;
}
}

104
site/css/fonts/_code.sass → site/css/fonts/_code.scss

@ -1,55 +1,63 @@
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Bold-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Bold-Italic.woff') format('woff')
font-weight: 700
font-style: italic
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Bold-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Bold-Italic.woff') format('woff');
font-weight: 700;
font-style: italic;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Bold.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Bold.woff') format('woff')
font-weight: 700
font-style: normal
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Bold.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Bold.woff') format('woff');
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-ExtraBold-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-ExtraBold-Italic.woff') format('woff')
font-weight: 800
font-style: italic
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-ExtraBold-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-ExtraBold-Italic.woff') format('woff');
font-weight: 800;
font-style: italic;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-ExtraBold.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-ExtraBold.woff') format('woff')
font-weight: 800
font-style: normal
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-ExtraBold.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-ExtraBold.woff') format('woff');
font-weight: 800;
font-style: normal;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Italic.woff') format('woff')
font-weight: 400
font-style: italic
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Italic.woff') format('woff');
font-weight: 400;
font-style: italic;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Medium-Italic.woff') format('woff')
font-weight: 500
font-style: italic
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium-Italic.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Medium-Italic.woff') format('woff');
font-weight: 500;
font-style: italic;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Medium.woff') format('woff')
font-weight: 500
font-style: normal
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Medium.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Medium.woff') format('woff');
font-weight: 500;
font-style: normal;
font-display: swap;
}
@font-face
font-family: 'JetBrains Mono'
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Regular.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Regular.woff') format('woff')
font-weight: 400
font-style: normal
font-display: swap
@font-face {
font-family: 'JetBrains Mono';
src: url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff2/JetBrainsMono-Regular.woff2') format('woff2'), url('https://cdn.jsdelivr.net/gh/JetBrains/JetBrainsMono/web/woff/JetBrainsMono-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}

20
site/css/layout/_footer.scss

@ -0,0 +1,20 @@
@import "../elements/containers";
body > footer {
@include body-segment;
margin: 0 auto;
padding: 1rem;
border-top: $border-regular;
border-bottom: $border-ginormous;
text-align: center;
p {
text-align: left;
margin: 0.3rem 0;
}
.copyright {
font-size: 0.9rem;
}
.generated-by-hakyll {
font-size: 0.8rem
}
}

61
site/css/layout/_header.scss

@ -0,0 +1,61 @@
@import "../variables";
@import "../vendor/include-media";
body > header {
$logo-icon-width: 3.5rem;
@include body-segment {
display: grid;
grid-template-columns: auto $logo-icon-width;
}
padding: 0.5rem 1rem;
border-top: $border-ginormous;
border-bottom: $border-regular;
.logo {
grid-column: 1 / span 1;
margin: 0;
padding: 0;
font-weight: bold;
font-size: 1.1rem;
a {
color: $color-green;
text-decoration: none;
}
}
.logo-icon {
grid-column: 2 / span 1;
grid-row: 1 / span 2;