Initial commit

This commit is contained in:
Fiscal Velvet Poet 2021-11-04 19:23:31 +10:00
commit c28e591961
Signed by: fiscalvelvetpoet
GPG key ID: D8EBFD58B023BD47
35 changed files with 2142 additions and 0 deletions

2
.envrc Normal file
View file

@ -0,0 +1,2 @@
use nix
watch_file nix/*

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.direnv

61
LICENSE Normal file
View file

@ -0,0 +1,61 @@
ANARCHIST LICENSE
Version 1.0, 1 May, 2021
Copyright © 2021 JFDI Collective
This is Anarchist software, released for free use by individuals and
organizations that do not operate by capitalist principles.
Permission is hereby granted, free of charge, to any peaceful non-aggressive
sovereign individual or group of sovereign individuals (the "individual")
obtaining a copy of this software, associated documentation files, and other
forms of information (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:
1. The above copyright notice and this permission notice shall be included in
all copies or modified versions of the Software.
2. The User is one of the following:
a. An individual person, laboring for themselves
b. A non-profit organization
c. An educational institution
d. An organization that seeks shared profit for all of its members, and
allows non-members to set the cost of their labor
3. If the User is an organization with owners, then all owners are workers and
all workers are owners with equal equity and/or equal vote.
4. If the User is an organization, then the User is not law enforcement or
military, or working for or under either.
Any individual breaking the Natural Law of Non-Aggression and Self-Defense is
entirely prohibited to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the software. This includes explicitly but is
not limited to,
* Any individual engaging in, or encouraging murder, assault, theft, rape,
trespassing, coercion, lying, or any other initiation of aggressive violence
against the private property of peaceful individuals;
* Any officer, contractor, subcontractor, or staff acting on behalf of, or being
funded by any government or law enforcement agency;
* Any officer, contractor, subcontractor, or staff associated with the
investigation of any active criminal proceedings of victimless crimes;
* Any individual relying on monopolistic privilege licenses granted by any
government or law enforcement agency;
* Any officer, contractor, subcontractor, or staff of any surveillance effort
acting in an official and/or commercial capacity or being contracted by any
government or law enforcement agency;
* Any individual investigating "money laundering" or "unexplained wealth"; or
* Any individual aggressively enforcing "intellectual property rights".
DON'T TRUST, VERIFY. 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.

10
README.rst Normal file
View file

@ -0,0 +1,10 @@
JFDIC Web
=========
Website configuration for the `JFDI Collective`_.
The canonical home for this repo is
https://source.jfdic.org/jfdic/jfdic-web
.. _NixOps: https://nixos.org/nixops
.. _JFDI Collective: https://jfdic.org/

419
css/base.css Normal file
View file

@ -0,0 +1,419 @@
/*
* Base CSS
*/
/*
* Contents
*
* Body resets
* Custom type
* Messages
* Container
* Masthead
* Posts and pages
* Pagination
* Reverse layout
* Themes
*/
/*
* Body resets
*
* Update the foundational and global aspects of the page.
*/
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
}
html {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 16px;
line-height: 1.5;
}
@media (min-width: 38em) {
html {
font-size: 20px;
}
}
body {
color: #515151;
background-color: #fff;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
/* No `:visited` state is required by default (browsers will use `a`) */
a {
color: #268bd2;
text-decoration: none;
}
a strong {
color: inherit;
}
/* `:focus` is linked to `:hover` for basic accessibility */
a:hover,
a:focus {
text-decoration: underline;
}
/* Headings */
h1, h2, h3, h4, h5, h6 {
margin-bottom: .5rem;
font-weight: bold;
line-height: 1.25;
color: #313131;
text-rendering: optimizeLegibility;
}
h1 {
font-size: 2rem;
}
h2 {
margin-top: 1rem;
font-size: 1.5rem;
}
h3 {
margin-top: 1.5rem;
font-size: 1.25rem;
}
h4, h5, h6 {
margin-top: 1rem;
font-size: 1rem;
}
/* Body text */
p {
margin-top: 0;
margin-bottom: 1rem;
}
strong {
color: #303030;
}
/* Lists */
ul, ol, dl {
margin-top: 0;
margin-bottom: 1rem;
}
dt {
font-weight: bold;
}
dd {
margin-bottom: .5rem;
}
/* Misc */
hr {
position: relative;
margin: 1.5rem 0;
border: 0;
border-top: 1px solid #eee;
border-bottom: 1px solid #fff;
}
abbr {
font-size: 85%;
font-weight: bold;
color: #555;
text-transform: uppercase;
}
abbr[title] {
cursor: help;
border-bottom: 1px dotted #e5e5e5;
}
/* Code */
code,
pre {
font-family: Menlo, Monaco, "Courier New", monospace;
}
code {
padding: .25em .5em;
font-size: 85%;
color: #bf616a;
background-color: #f9f9f9;
border-radius: 3px;
}
pre {
display: block;
margin-top: 0;
margin-bottom: 1rem;
padding: 1rem;
font-size: .8rem;
line-height: 1.4;
white-space: pre;
white-space: pre-wrap;
word-break: break-all;
word-wrap: break-word;
background-color: #f9f9f9;
}
pre code {
padding: 0;
font-size: 100%;
color: inherit;
background-color: transparent;
}
/* Pygments via Jekyll */
.highlight {
margin-bottom: 1rem;
border-radius: 4px;
}
.highlight pre {
margin-bottom: 0;
}
/* Gist via GitHub Pages */
.gist .gist-file {
font-family: Menlo, Monaco, "Courier New", monospace !important;
}
.gist .markdown-body {
padding: 15px;
}
.gist pre {
padding: 0;
background-color: transparent;
}
.gist .gist-file .gist-data {
font-size: .8rem !important;
line-height: 1.4;
}
.gist code {
padding: 0;
color: inherit;
background-color: transparent;
border-radius: 0;
}
/* Quotes */
blockquote {
padding: .5rem 1rem;
margin: .8rem 0;
color: #7a7a7a;
border-left: .25rem solid #e5e5e5;
}
blockquote p:last-child {
margin-bottom: 0;
}
@media (min-width: 30em) {
blockquote {
padding-right: 5rem;
padding-left: 1.25rem;
}
}
img {
display: block;
max-width: 100%;
margin: 0 0 1rem;
border-radius: 5px;
}
/* Tables */
table {
margin-bottom: 1rem;
width: 100%;
border: 1px solid #e5e5e5;
border-collapse: collapse;
}
td,
th {
padding: .25rem .5rem;
border: 1px solid #e5e5e5;
}
tbody tr:nth-child(odd) td,
tbody tr:nth-child(odd) th {
background-color: #f9f9f9;
}
/*
* Custom type
*
* Extend paragraphs with `.lead` for larger introductory text.
*/
.lead {
font-size: 1.25rem;
font-weight: 300;
}
/*
* Messages
*
* Show alert messages to users. You may add it to single elements like a `<p>`,
* or to a parent if there are multiple elements to show.
*/
.message {
margin-bottom: 1rem;
padding: 1rem;
color: #717171;
background-color: #f9f9f9;
}
/*
* Container
*
* Center the page content.
*/
.container {
max-width: 38rem;
padding-left: 1rem;
padding-right: 1rem;
margin-left: auto;
margin-right: auto;
}
/*
* Masthead
*
* Super small header above the content for site name and short description.
*/
.masthead {
padding-top: 1rem;
padding-bottom: 1rem;
margin-bottom: 3rem;
}
.masthead-title {
margin-top: 0;
margin-bottom: 0;
color: #505050;
}
.masthead-title a {
color: #505050;
}
.masthead-title small {
font-size: 75%;
font-weight: 400;
color: #c0c0c0;
letter-spacing: 0;
}
/*
* Posts and pages
*
* Each post is wrapped in `.post` and is used on default and post layouts. Each
* page is wrapped in `.page` and is only used on the page layout.
*/
.page,
.post {
margin-bottom: 4em;
}
/* Blog post or page title */
.page-title,
.post-title,
.post-title a {
color: #303030;
}
.page-title,
.post-title {
margin-top: 0;
}
/* Meta data line below post title */
.post-date {
display: block;
margin-top: -.5rem;
margin-bottom: 1rem;
color: #9a9a9a;
}
/* Related posts */
.related {
padding-top: 2rem;
padding-bottom: 2rem;
border-top: 1px solid #eee;
}
.related-posts {
padding-left: 0;
list-style: none;
}
.related-posts h3 {
margin-top: 0;
}
.related-posts li small {
font-size: 75%;
color: #999;
}
.related-posts li a:hover {
color: #268bd2;
text-decoration: none;
}
.related-posts li a:hover small {
color: inherit;
}
/*
* Pagination
*
* Super lightweight (HTML-wise) blog pagination. `span`s are provide for when
* there are no more previous or next posts to show.
*/
.pagination {
overflow: hidden; /* clearfix */
margin-left: -1rem;
margin-right: -1rem;
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #ccc;
text-align: center;
}
/* Pagination items can be `span`s or `a`s */
.pagination-item {
display: block;
padding: 1rem;
border: 1px solid #eee;
}
.pagination-item:first-child {
margin-bottom: -1px;
}
/* Only provide a hover state for linked pagination items */
a.pagination-item:hover {
background-color: #f5f5f5;
}
@media (min-width: 30em) {
.pagination {
margin: 3rem 0;
}
.pagination-item {
float: left;
width: 50%;
}
.pagination-item:first-child {
margin-bottom: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.pagination-item:last-child {
margin-left: -1px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
}

141
css/default.css Normal file
View file

@ -0,0 +1,141 @@
html {
font-size: 62.5%;
}
body {
font-size: 1.6rem;
color: #000;
}
header {
border-bottom: 0.2rem solid #000;
}
nav {
text-align: right;
}
nav a {
font-size: 1.8rem;
font-weight: bold;
color: black;
text-decoration: none;
text-transform: uppercase;
}
footer {
margin-top: 3rem;
padding: 1.2rem 0;
border-top: 0.2rem solid #000;
font-size: 1.2rem;
color: #555;
}
h1 {
font-size: 2.4rem;
}
h2 {
font-size: 2rem;
}
article .header {
font-size: 1.4rem;
font-style: italic;
color: #555;
}
.logo a {
font-weight: bold;
color: #000;
text-decoration: none;
}
@media (max-width: 319px) {
body {
width: 90%;
margin: 0;
padding: 0 5%;
}
header {
margin: 4.2rem 0;
}
nav {
margin: 0 auto 3rem;
text-align: center;
}
footer {
text-align: center;
}
.logo {
text-align: center;
margin: 1rem auto 3rem;
}
.logo a {
font-size: 2.4rem;
}
nav a {
display: block;
line-height: 1.6;
}
}
@media (min-width: 320px) {
body {
width: 90%;
margin: 0;
padding: 0 5%;
}
header {
margin: 4.2rem 0;
}
nav {
margin: 0 auto 3rem;
text-align: center;
}
footer {
text-align: center;
}
.logo {
text-align: center;
margin: 1rem auto 3rem;
}
.logo a {
font-size: 2.4rem;
}
nav a {
display: inline;
margin: 0 0.6rem;
}
}
@media (min-width: 640px) {
body {
width: 60rem;
margin: 0 auto;
padding: 0;
}
header {
margin: 0 0 3rem;
padding: 1.2rem 0;
}
nav {
margin: 0;
text-align: right;
}
nav a {
margin: 0 0 0 1.2rem;
display: inline;
}
footer {
text-align: right;
}
.logo {
margin: 0;
text-align: left;
}
.logo a {
float: left;
font-size: 1.8rem;
}
}

532
css/jfdic.css Normal file
View file

@ -0,0 +1,532 @@
/*
* JFDIC theme
*/
/*
* Global resets
*
* Update the foundational and global aspects of the page.
*/
/* Prevent scroll on narrow devices */
html,
body {
overflow-x: hidden;
}
html {
font-family: "PT Serif", Georgia, "Times New Roman", serif;
}
h1, h2, h3, h4, h5, h6 {
font-family: "PT Sans", Helvetica, Arial, sans-serif;
font-weight: 400;
color: #313131;
letter-spacing: -.025rem;
}
/*
* Wrapper
*
* The wrapper is used to position site content when the sidebar is toggled. We
* use an outter wrap to position the sidebar without interferring with the
* regular page content.
*/
.wrap {
position: relative;
width: 100%;
}
/*
* Container
*
* Center the page content.
*/
.container {
max-width: 28rem;
}
@media (min-width: 38em) {
.container {
max-width: 32rem;
}
}
@media (min-width: 56em) {
.container {
max-width: 38rem;
}
}
/*
* Masthead
*
* Super small header above the content for site name and short description.
*/
.masthead {
padding-top: 1rem;
padding-bottom: 1rem;
margin-bottom: 3rem;
border-bottom: 1px solid #eee;
}
.masthead-title {
margin-top: 0;
margin-bottom: 0;
color: #505050;
}
.masthead-title a {
color: #505050;
}
.masthead-title small {
font-size: 75%;
font-weight: 400;
color: #c0c0c0;
letter-spacing: 0;
}
@media (max-width: 48em) {
.masthead-title {
text-align: center;
}
.masthead-title small {
display: none;
}
}
/*
* Sidebar
*
* The sidebar is the drawer, the item we are toggling with our handy hamburger
* button in the corner of the page.
*
* This particular sidebar implementation was inspired by Chris Coyier's
* "Offcanvas Menu with CSS Target" article, and the checkbox variation from the
* comments by a reader. It modifies both implementations to continue using the
* checkbox (no change in URL means no polluted browser history), but this uses
* `position` for the menu to avoid some potential content reflow issues.
*
* Source: http://css-tricks.com/off-canvas-menu-with-css-target/#comment-207504
*/
/* Style and "hide" the sidebar */
.sidebar {
position: fixed;
top: 0;
bottom: 0;
left: -14rem;
width: 14rem;
visibility: hidden;
overflow-y: auto;
font-family: "PT Sans", Helvetica, Arial, sans-serif;
font-size: .875rem; /* 15px */
color: rgba(255,255,255,.6);
background-color: #202020;
-webkit-transition: all .3s ease-in-out;
transition: all .3s ease-in-out;
}
@media (min-width: 30em) {
.sidebar {
font-size: .75rem; /* 14px */
}
}
/* Sidebar content */
.sidebar a {
font-weight: normal;
color: #fff;
}
.sidebar-item {
padding: 1rem;
}
.sidebar-item p:last-child {
margin-bottom: 0;
}
/* Sidebar nav */
.sidebar-nav {
border-bottom: 1px solid rgba(255,255,255,.1);
}
.sidebar-nav-item {
display: block;
padding: .5rem 1rem;
border-top: 1px solid rgba(255,255,255,.1);
}
.sidebar-nav-item.active,
a.sidebar-nav-item:hover,
a.sidebar-nav-item:focus {
text-decoration: none;
background-color: rgba(255,255,255,.1);
border-color: transparent;
}
@media (min-width: 48em) {
.sidebar-item {
padding: 1.5rem;
}
.sidebar-nav-item {
padding-left: 1.5rem;
padding-right: 1.5rem;
}
}
/* Hide the sidebar checkbox that we toggle with `.sidebar-toggle` */
.sidebar-checkbox {
position: absolute;
opacity: 0;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
/* Style the `label` that we use to target the `.sidebar-checkbox` */
.sidebar-toggle {
position: absolute;
top: .8rem;
left: 1rem;
display: flex;
align-items: center;
padding: .25rem .75rem;
color: #505050;
background-color: #fff;
border-radius: .25rem;
cursor: pointer;
}
.sidebar-toggle::before {
display: inline-block;
width: 32px;
height: 32px;
content: "";
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23555' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat;
}
.sidebar-toggle:active,
#sidebar-checkbox:focus ~ .sidebar-toggle,
#sidebar-checkbox:checked ~ .sidebar-toggle {
color: #fff;
background-color: #555;
}
.sidebar-toggle:active:before,
#sidebar-checkbox:focus ~ .sidebar-toggle::before,
#sidebar-checkbox:checked ~ .sidebar-toggle::before {
background: url("data:image/svg+xml,%3Csvg viewBox='0 0 16 16' fill='%23fff' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' d='M2.5 11.5A.5.5 0 013 11h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 7h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5zm0-4A.5.5 0 013 3h10a.5.5 0 010 1H3a.5.5 0 01-.5-.5z' clip-rule='evenodd'/%3E%3C/svg%3E") no-repeat;
}
@media (min-width: 30.1em) {
.sidebar-toggle {
position: fixed;
}
}
@media print {
.sidebar-toggle {
display: none;
}
}
/* Slide effect
*
* Handle the sliding effects of the sidebar and content in one spot, seperate
* from the default styles.
*
* As an a heads up, we don't use `transform: translate3d()` here because when
* mixed with `position: fixed;` for the sidebar toggle, it creates a new
* containing block. Put simply, the fixed sidebar toggle behaves like
* `position: absolute;` when transformed.
*
* Read more about it at http://meyerweb.com/eric/thoughts/2011/09/12/.
*/
.wrap,
.sidebar,
.sidebar-toggle {
-webkit-backface-visibility: hidden;
-ms-backface-visibility: hidden;
backface-visibility: hidden;
}
.wrap,
.sidebar-toggle {
-webkit-transition: -webkit-transform .3s ease-in-out;
transition: transform .3s ease-in-out;
}
#sidebar-checkbox:checked + .sidebar {
z-index: 10;
visibility: visible;
}
#sidebar-checkbox:checked ~ .sidebar,
#sidebar-checkbox:checked ~ .wrap,
#sidebar-checkbox:checked ~ .sidebar-toggle {
-webkit-transform: translateX(14rem);
-ms-transform: translateX(14rem);
transform: translateX(14rem);
}
/*
* Posts and pages
*
* Each post is wrapped in `.post` and is used on default and post layouts. Each
* page is wrapped in `.page` and is only used on the page layout.
*/
.page,
.post {
margin-bottom: 4em;
}
/* Blog post or page title */
.page-title,
.post-title,
.post-title a {
color: #303030;
}
.page-title,
.post-title {
margin-top: 0;
}
/* Meta data line below post title */
.post-date {
display: block;
margin-top: -.5rem;
margin-bottom: 1rem;
color: #9a9a9a;
}
/* Related posts */
.related {
padding-top: 2rem;
padding-bottom: 2rem;
border-top: 1px solid #eee;
}
.related-posts {
padding-left: 0;
list-style: none;
}
.related-posts h3 {
margin-top: 0;
}
.related-posts li small {
font-size: 75%;
color: #999;
}
.related-posts li a:hover {
color: #268bd2;
text-decoration: none;
}
.related-posts li a:hover small {
color: inherit;
}
/*
* Pagination
*
* Super lightweight (HTML-wise) blog pagination. `span`s are provide for when
* there are no more previous or next posts to show.
*/
.pagination {
overflow: hidden; /* clearfix */
margin-left: -1rem;
margin-right: -1rem;
font-family: "PT Sans", Helvetica, Arial, sans-serif;
color: #ccc;
text-align: center;
}
/* Pagination items can be `span`s or `a`s */
.pagination-item {
display: block;
padding: 1rem;
border: 1px solid #eee;
}
.pagination-item:first-child {
margin-bottom: -1px;
}
/* Only provide a hover state for linked pagination items */
a.pagination-item:hover {
background-color: #f5f5f5;
}
@media (min-width: 30em) {
.pagination {
margin: 3rem 0;
}
.pagination-item {
float: left;
width: 50%;
}
.pagination-item:first-child {
margin-bottom: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.pagination-item:last-child {
margin-left: -1px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
}
/*
* Reverse layout
*
* Flip the orientation of the page by placing the `.sidebar` and sidebar toggle
* on the right side.
*/
.layout-reverse .sidebar {
left: auto;
right: -14rem;
}
.layout-reverse .sidebar-toggle {
left: auto;
right: 1rem;
}
.layout-reverse #sidebar-checkbox:checked ~ .sidebar,
.layout-reverse #sidebar-checkbox:checked ~ .wrap,
.layout-reverse #sidebar-checkbox:checked ~ .sidebar-toggle {
-webkit-transform: translateX(-14rem);
-ms-transform: translateX(-14rem);
transform: translateX(-14rem);
}
/*
* Themes
*
* Apply custom color schemes by adding the appropriate class to the `body`.
* Based on colors from Base16: http://chriskempson.github.io/base16/#default.
*/
/* Red */
.theme-base-08 .sidebar,
.theme-base-08 .sidebar-toggle:active,
.theme-base-08 #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #ac4142;
}
.theme-base-08 .container a,
.theme-base-08 .sidebar-toggle,
.theme-base-08 .related-posts li a:hover {
color: #ac4142;
}
/* Orange */
.theme-base-09 .sidebar,
.theme-base-09 .sidebar-toggle:active,
.theme-base-09 #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #d28445;
}
.theme-base-09 .container a,
.theme-base-09 .sidebar-toggle,
.theme-base-09 .related-posts li a:hover {
color: #d28445;
}
/* Yellow */
.theme-base-0a .sidebar,
.theme-base-0a .sidebar-toggle:active,
.theme-base-0a #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #f4bf75;
}
.theme-base-0a .container a,
.theme-base-0a .sidebar-toggle,
.theme-base-0a .related-posts li a:hover {
color: #f4bf75;
}
/* Green */
.theme-base-0b .sidebar,
.theme-base-0b .sidebar-toggle:active,
.theme-base-0b #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #90a959;
}
.theme-base-0b .container a,
.theme-base-0b .sidebar-toggle,
.theme-base-0b .related-posts li a:hover {
color: #90a959;
}
/* Cyan */
.theme-base-0c .sidebar,
.theme-base-0c .sidebar-toggle:active,
.theme-base-0c #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #75b5aa;
}
.theme-base-0c .container a,
.theme-base-0c .sidebar-toggle,
.theme-base-0c .related-posts li a:hover {
color: #75b5aa;
}
/* Blue */
.theme-base-0d .sidebar,
.theme-base-0d .sidebar-toggle:active,
.theme-base-0d #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #6a9fb5;
}
.theme-base-0d .container a,
.theme-base-0d .sidebar-toggle,
.theme-base-0d .related-posts li a:hover {
color: #6a9fb5;
}
/* Magenta */
.theme-base-0e .sidebar,
.theme-base-0e .sidebar-toggle:active,
.theme-base-0e #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #aa759f;
}
.theme-base-0e .container a,
.theme-base-0e .sidebar-toggle,
.theme-base-0e .related-posts li a:hover {
color: #aa759f;
}
/* Brown */
.theme-base-0f .sidebar,
.theme-base-0f .sidebar-toggle:active,
.theme-base-0f #sidebar-checkbox:checked ~ .sidebar-toggle {
background-color: #8f5536;
}
.theme-base-0f .container a,
.theme-base-0f .sidebar-toggle,
.theme-base-0f .related-posts li a:hover {
color: #8f5536;
}
/*
* Overlay sidebar
*
* Make the sidebar content overlay the viewport content instead of pushing it
* aside when toggled.
*/
.sidebar-overlay #sidebar-checkbox:checked ~ .wrap {
-webkit-transform: translateX(0);
-ms-transform: translateX(0);
transform: translateX(0);
}
.sidebar-overlay #sidebar-checkbox:checked ~ .sidebar-toggle {
box-shadow: 0 0 0 .25rem #fff;
}
.sidebar-overlay #sidebar-checkbox:checked ~ .sidebar {
box-shadow: .25rem 0 .5rem rgba(0,0,0,.1);
}
/* Only one tweak for a reverse layout */
.layout-reverse.sidebar-overlay #sidebar-checkbox:checked ~ .sidebar {
box-shadow: -.25rem 0 .5rem rgba(0,0,0,.1);
}

62
css/syntax.css Normal file
View file

@ -0,0 +1,62 @@
a.sourceLine { display: inline-block; line-height: 1.25; }
.container .sourceCode a.sourceLine { pointer-events: none; color: #313131;}
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: auto; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
{ position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
{ content: attr(title);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; pointer-events: all; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
/* pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; } */
pre.numberSource { padding: 2rem; } */
div.sourceCode
{ }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */

1
default.nix Normal file
View file

@ -0,0 +1 @@
(import ./release.nix { }).project

12
error/404.rst Normal file
View file

@ -0,0 +1,12 @@
---
layout: default
title: "404: Page not found"
permalink: 404.html
---
404: Page not found
===================
Sorry, we've misplaced that URL or it's pointing to something that doesn't exist. `Head back home`_ to try finding it again.
.. _Head back home: $site-url$

0
hakyll.patch Normal file
View file

85
images/hakyll-logo.svg Normal file
View file

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="221.42857"
height="221.42857"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="logo.svg"
inkscape:export-filename="/home/jasper/Documents/ZuriHac/logo.png"
inkscape:export-xdpi="81.290001"
inkscape:export-ydpi="81.290001">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.4096774"
inkscape:cx="110.71429"
inkscape:cy="110.71429"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1262"
inkscape:window-height="1006"
inkscape:window-x="1287"
inkscape:window-y="7"
inkscape:window-maximized="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-7.8571436,-9.5050393)">
<path
sodipodi:type="arc"
style="fill:#000000;fill-opacity:1;stroke:none"
id="path2820"
sodipodi:cx="52.5"
sodipodi:cy="54.147896"
sodipodi:rx="44.642857"
sodipodi:ry="44.642857"
d="m 97.142857,54.147896 c 0,24.655569 -19.987288,44.642856 -44.642857,44.642856 -24.655569,0 -44.6428566,-19.987287 -44.6428566,-44.642856 0,-24.655569 19.9872876,-44.6428568 44.6428566,-44.6428568 24.655569,0 44.642857,19.9872878 44.642857,44.6428568 z"
transform="matrix(2.304,0,0,2.304,-2.3885719,-4.5374282)" />
<g
style="font-size:211.77316284px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;font-family:Times New Roman;-inkscape-font-specification:'Times New Roman,'"
id="text2816">
<path
d="m 171.48526,157.26037 3.72258,0 c -1e-4,10.892 -1.79245,18.8197 -5.37705,23.78312 -3.51586,4.96343 -7.9278,7.44515 -13.23583,7.44515 -4.34308,0 -8.51374,-1.62001 -12.51199,-4.86003 -3.99839,-3.30895 -7.58308,-12.09835 -10.7541,-26.36824 l -8.89282,-40.12109 -30.814649,69.90169 -19.54352,0 44.257279,-95.339285 c -2.34388,-12.33954 -5.17028,-21.473627 -8.4792,-27.40229 -3.30899,-5.928416 -7.41071,-8.892686 -12.305174,-8.892818 -3.929407,1.32e-4 -7.376233,1.516735 -10.340487,4.549814 -2.895349,2.964397 -4.515357,7.583143 -4.860029,13.856252 l -3.722575,0 C 78.834498,63.67909 80.868125,55.57905 84.728582,49.5125 c 3.860432,-6.135212 8.685987,-9.202886 14.476681,-9.203033 3.722547,1.47e-4 7.238307,1.551218 10.547297,4.653219 3.37785,3.033348 6.27318,8.272523 8.68601,15.717539 2.48167,7.376333 6.30764,22.714706 11.47794,46.015165 l 7.34174,32.77934 c 2.96421,13.58054 6.06635,22.68016 9.30644,27.29889 3.30888,4.54983 7.23826,6.82473 11.78816,6.82472 7.7208,1e-5 12.09827,-5.44597 13.13241,-16.33797"
style=""
id="path2844" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
images/haskell-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

5
index.rst Normal file
View file

@ -0,0 +1,5 @@
---
title: JFDI Collective
---
Welcome. We just do things.

14
jfdic-web.cabal Normal file
View file

@ -0,0 +1,14 @@
name: jfdic-web
version: 0.1.0.0
build-type: Simple
cabal-version: >= 1.10
executable site
main-is: site.hs
build-depends: base == 4.*
, hakyll == 4.14.*
, containers == 0.6.*
, filepath == 1.4.*
, pandoc
ghc-options: -threaded
default-language: Haskell2010

11
jfdic-web.nix Normal file
View file

@ -0,0 +1,11 @@
{ mkDerivation, base, hakyll, stdenv }:
mkDerivation {
pname = "jfdic-web";
version = "0.1.0.0";
src = ./.;
isLibrary = false;
isExecutable = true;
executableHaskellDepends = [ base hakyll ];
license = "unknown";
hydraPlatforms = stdenv.lib.platforms.none;
}

15
js/script.js Normal file
View file

@ -0,0 +1,15 @@
(function(document) {
var toggle = document.querySelector('.sidebar-toggle');
var sidebar = document.querySelector('#sidebar');
var checkbox = document.querySelector('#sidebar-checkbox');
document.addEventListener('click', function(e) {
var target = e.target;
if(!checkbox.checked ||
sidebar.contains(target) ||
(target === checkbox || target === toggle)) return;
checkbox.checked = false;
}, false);
})(document);

26
nix/sources.json Normal file
View file

@ -0,0 +1,26 @@
{
"niv": {
"branch": "master",
"description": "Easy dependency management for Nix projects",
"homepage": "https://github.com/nmattia/niv",
"owner": "nmattia",
"repo": "niv",
"rev": "dd13098d01eaa6be68237e7e38f96782b0480755",
"sha256": "1cfjdbsn0219fjzam1k7nqzkz8fb1ypab50rhyj026qbklqq2kvq",
"type": "tarball",
"url": "https://github.com/nmattia/niv/archive/dd13098d01eaa6be68237e7e38f96782b0480755.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
},
"nixpkgs": {
"branch": "nixpkgs-unstable",
"description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to",
"homepage": "https://github.com/NixOS/nixpkgs",
"owner": "NixOS",
"repo": "nixpkgs-channels",
"rev": "10100a97c8964e82b30f180fda41ade8e6f69e41",
"sha256": "011f36kr3c1ria7rag7px26bh73d1b0xpqadd149bysf4hg17rln",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs-channels/archive/10100a97c8964e82b30f180fda41ade8e6f69e41.tar.gz",
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
}
}

134
nix/sources.nix Normal file
View file

@ -0,0 +1,134 @@
# This file has been generated by Niv.
let
#
# The fetchers. fetch_<type> fetches specs of type <type>.
#
fetch_file = pkgs: spec:
if spec.builtin or true then
builtins_fetchurl { inherit (spec) url sha256; }
else
pkgs.fetchurl { inherit (spec) url sha256; };
fetch_tarball = pkgs: spec:
if spec.builtin or true then
builtins_fetchTarball { inherit (spec) url sha256; }
else
pkgs.fetchzip { inherit (spec) url sha256; };
fetch_git = spec:
builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; };
fetch_builtin-tarball = spec:
builtins.trace
''
WARNING:
The niv type "builtin-tarball" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=tarball -a builtin=true
''
builtins_fetchTarball { inherit (spec) url sha256; };
fetch_builtin-url = spec:
builtins.trace
''
WARNING:
The niv type "builtin-url" will soon be deprecated. You should
instead use `builtin = true`.
$ niv modify <package> -a type=file -a builtin=true
''
(builtins_fetchurl { inherit (spec) url sha256; });
#
# Various helpers
#
# The set of packages used when specs are fetched using non-builtins.
mkPkgs = sources:
let
sourcesNixpkgs =
import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {};
hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
hasThisAsNixpkgsPath = <nixpkgs> == ./.;
in
if builtins.hasAttr "nixpkgs" sources
then sourcesNixpkgs
else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
import <nixpkgs> {}
else
abort
''
Please specify either <nixpkgs> (through -I or NIX_PATH=nixpkgs=...) or
add a package called "nixpkgs" to your sources.json.
'';
# The actual fetching function.
fetch = pkgs: name: spec:
if ! builtins.hasAttr "type" spec then
abort "ERROR: niv spec ${name} does not have a 'type' attribute"
else if spec.type == "file" then fetch_file pkgs spec
else if spec.type == "tarball" then fetch_tarball pkgs spec
else if spec.type == "git" then fetch_git spec
else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec
else if spec.type == "builtin-url" then fetch_builtin-url spec
else
abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
# Ports of functions for older nix versions
# a Nix version of mapAttrs if the built-in doesn't exist
mapAttrs = builtins.mapAttrs or (
f: set: with builtins;
listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set))
);
# fetchTarball version that is compatible between all the versions of Nix
builtins_fetchTarball = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchTarball;
in
if lessThan nixVersion "1.12" then
fetchTarball { inherit url; }
else
fetchTarball attrs;
# fetchurl version that is compatible between all the versions of Nix
builtins_fetchurl = { url, sha256 }@attrs:
let
inherit (builtins) lessThan nixVersion fetchurl;
in
if lessThan nixVersion "1.12" then
fetchurl { inherit url; }
else
fetchurl attrs;
# Create the final "sources" from the config
mkSources = config:
mapAttrs (
name: spec:
if builtins.hasAttr "outPath" spec
then abort
"The values in sources.json should not have an 'outPath' attribute"
else
spec // { outPath = fetch config.pkgs name spec; }
) config.sources;
# The "config" used by the fetchers
mkConfig =
{ sourcesFile ? ./sources.json
, sources ? builtins.fromJSON (builtins.readFile sourcesFile)
, pkgs ? mkPkgs sources
}: rec {
# The sources, i.e. the attribute set of spec name to spec
inherit sources;
# The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers
inherit pkgs;
};
in
mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); }

7
pages/About.rst Normal file
View file

@ -0,0 +1,7 @@
---
title: About
---
We're the spiritual successor to `C@T`_.
.. _C@T:: https://web.archive.org/web/20070102063147/http://cat.org.au/

5
pages/Contact.rst Normal file
View file

@ -0,0 +1,5 @@
---
title: Contact
---
You can contact the JFDI collective via our Matrix room.

View file

@ -0,0 +1,60 @@
---
title: S.P.Q.R.
tags: Mauris, lorem
---
Mauris in lorem nisl. Maecenas tempus facilisis ante, eget viverra nisl
tincidunt et. Donec turpis lectus, mattis ac malesuada a, accumsan eu libero.
Morbi condimentum, tortor et tincidunt ullamcorper, sem quam pretium nulla, id
convallis lectus libero nec turpis. Proin dapibus nisi id est sodales nec
ultrices tortor pellentesque. Vivamus vel nisi ac lacus sollicitudin vulputate
ac ut ligula. Nullam feugiat risus eget eros gravida in molestie sapien euismod.
Nunc sed hendrerit orci. Nulla mollis consequat lorem ac blandit. Ut et turpis
mauris. Nulla est odio, posuere id ullamcorper sit amet, tincidunt vel justo.
Curabitur placerat tincidunt varius. Nulla vulputate, ipsum eu consectetur
mollis, dui nibh aliquam neque, at ultricies leo ligula et arcu. Proin et mi
eget tellus sodales lobortis. Sed tempor, urna vel pulvinar faucibus, lectus
urna vehicula ante, at facilisis dolor odio at lorem. Morbi vehicula euismod
urna, et imperdiet urna ornare vitae.
Sed tincidunt sollicitudin ultrices. In hac habitasse platea dictumst. Morbi
ligula lectus, egestas at ultricies nec, fringilla et tellus. Duis urna lorem,
bibendum a ornare sed, euismod sed nunc. Aliquam tempor massa at velit fringilla
fringilla. Praesent sit amet tempor felis. Maecenas id felis ac velit aliquam
tempor a sit amet orci. Nunc placerat nulla pellentesque sem commodo cursus.
Praesent quis sapien orci, quis ultricies augue. Nam vestibulum sem non augue
semper tincidunt pellentesque ipsum volutpat. Duis congue, nunc a aliquam
luctus, quam ante convallis nisi, ac pellentesque lacus orci vel turpis. Cum
sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
mus. Suspendisse hendrerit nisl eu felis sagittis faucibus. Nunc eu congue
lorem. Quisque non nibh nisi, et ultrices massa. Sed vitae erat vitae nulla
pellentesque fermentum.
Ut diam nunc, consectetur ut ultrices eu, iaculis sed felis. Sed lacinia, odio
et accumsan luctus, arcu ipsum accumsan erat, sit amet malesuada libero lacus et
velit. Donec accumsan tristique tristique. Proin a metus magna, vitae mattis
nisl. Integer a libero ipsum. Mauris faucibus eleifend metus id sodales. Morbi
ornare, nibh nec facilisis imperdiet, turpis sem commodo lorem, id commodo
mauris metus vitae justo. Etiam at pellentesque tortor. Proin mollis accumsan
ligula, nec tempus augue auctor quis. Nulla lacinia, mi quis lobortis auctor,
nisi diam posuere dui, pulvinar feugiat dui libero eget quam. Fusce eu risus
nunc, a consectetur orci. Class aptent taciti sociosqu ad litora torquent per
conubia nostra, per inceptos himenaeos. Maecenas venenatis aliquet orci, a
ultricies sem facilisis eu. Donec dolor purus, porta condimentum convallis nec,
dignissim nec libero.
Etiam rutrum ultricies dui, et interdum metus elementum et. Nulla sapien nunc,
interdum tristique porttitor in, laoreet vitae mi. Ut vehicula auctor mauris sit
amet bibendum. Phasellus adipiscing mattis libero, eget adipiscing erat
dignissim at. Vivamus convallis malesuada metus nec cursus. Ut cursus, lorem
eleifend sollicitudin condimentum, felis tortor sodales augue, ac tempus lacus
ipsum vitae quam. Vestibulum vitae lacus non tortor vehicula iaculis faucibus
quis massa.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus
mus. Duis malesuada neque nec ante porttitor accumsan. Suspendisse potenti.
Aliquam in lacus magna, imperdiet laoreet lectus. Praesent id diam nec ante
commodo rhoncus nec vel augue. Pellentesque tortor massa, dignissim ut sagittis
sed, hendrerit vitae nunc. Nam gravida, urna vitae hendrerit rutrum, felis augue
vulputate tortor, ut varius velit libero nec lectus. In adipiscing massa in est
scelerisque ullamcorper. Vivamus in nisi metus.

View file

@ -0,0 +1,47 @@
---
title: Rosa Rosa Rosam
author: Ovidius
tags: lorem
---
Suspendisse pharetra ullamcorper sem et auctor. Suspendisse vitae tellus eu
turpis dignissim gravida ut ut tortor. Cum sociis natoque penatibus et magnis
dis parturient montes, nascetur ridiculus mus. Morbi aliquam sapien quis nisl
sodales non aliquet nisl iaculis. Curabitur fermentum orci vel sapien
pellentesque id condimentum metus vehicula. Curabitur turpis purus, scelerisque
at interdum quis, placerat sit amet tortor. Aliquam erat volutpat.
Integer posuere felis non arcu suscipit ullamcorper. Nam tempus risus venenatis
orci sagittis eu aliquam ante tincidunt. Aenean vehicula ipsum id sapien
tincidunt commodo. Aliquam erat volutpat. Curabitur vehicula libero ac turpis
cursus consectetur. Praesent posuere egestas purus et dapibus. Mauris egestas,
lectus vitae scelerisque ultricies, metus lorem tempor nisi, sed vehicula tortor
mauris nec urna. Quisque urna tellus, facilisis at mollis eget, adipiscing in
nisl. Proin quam arcu, euismod et imperdiet sed, ultricies sed orci.
Nulla malesuada sem eget lectus scelerisque nec rhoncus metus interdum. In dui
felis, rhoncus id scelerisque eget, vulputate id sem. Nulla facilisi. Vestibulum
eleifend, metus dignissim lacinia ornare, magna nulla vehicula nisi, sed
molestie mauris ipsum vel turpis. Class aptent taciti sociosqu ad litora
torquent per conubia nostra, per inceptos himenaeos. Nulla urna leo, vehicula
eget dignissim a, hendrerit ut risus. Fusce ultricies elementum placerat. Nam at
dolor sed nisi mollis sollicitudin vitae at urna. Vestibulum iaculis adipiscing
eros et mollis.
Phasellus ultricies elit eu risus sagittis eu dictum ante ultrices. Nulla
congue, augue ac placerat tempor, orci mi luctus nisi, at varius ipsum sem sed
eros. Vivamus eget velit eget felis posuere ornare. In sed metus non est iaculis
facilisis dapibus sit amet enim. Aliquam viverra tortor eget neque volutpat in
auctor urna rutrum. Aliquam ligula augue, congue sit amet rutrum in, semper vel
nulla. Sed tempus porttitor faucibus. Donec cursus sodales nulla, quis lacinia
mi vehicula vel. Sed nec purus orci. Nam leo sapien, rutrum a ultrices quis,
placerat vel ligula. Donec massa quam, pellentesque et molestie nec, hendrerit
id mauris. In hac habitasse platea dictumst. Cras quis quam sem. Curabitur in
arcu diam, in interdum mauris.
Proin lorem sapien, iaculis et faucibus nec, dictum sed nunc. Pellentesque in
purus justo. Vestibulum facilisis rutrum nisi, a egestas nunc suscipit sed. Ut
quis tortor a arcu bibendum placerat non sed ante. Praesent orci sem, posuere
sit amet cursus molestie, volutpat ut purus. Curabitur aliquam, purus in
pharetra viverra, lorem leo aliquam tellus, vel consequat felis neque et mauris.
Aliquam erat volutpat.

View file

@ -0,0 +1,51 @@
---
title: Carpe Diem
tags: lorem, quam
---
Fusce tortor quam, egestas in posuere quis, porttitor vel turpis. Donec
vulputate porttitor augue at rhoncus. Proin iaculis consectetur sagittis.
Curabitur venenatis turpis sit amet purus tristique nec posuere risus laoreet.
Nullam nisi sem, dapibus id semper id, egestas vel arcu. Morbi porttitor ipsum
placerat erat consequat sed consequat purus feugiat. Donec auctor elit ut risus
mattis facilisis. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Proin vulputate sapien facilisis leo ornare pulvinar. Fusce tempus massa a risus
semper iaculis. Suspendisse sollicitudin posuere nunc, sit amet rutrum leo
facilisis mattis. Sed ornare auctor dui, vitae rutrum neque auctor sit amet.
Proin ac dui magna. Mauris vehicula interdum augue, nec ultrices libero egestas
quis. Nunc convallis euismod ipsum, id sollicitudin orci consequat ac. Fusce
bibendum congue libero, in rutrum nulla congue non. Cras sit amet risus tortor,
eu pellentesque dui. Phasellus euismod enim non nibh sodales quis consectetur
lorem laoreet. Vivamus a egestas quam. Curabitur in tortor augue, vitae varius
tellus. Integer varius, elit ac gravida suscipit, eros erat pellentesque nisi,
et tristique augue odio id nulla. Aliquam sit amet nunc vel tellus hendrerit
tempus ac vel sem.
Aenean tincidunt sollicitudin sapien ut porttitor. Curabitur molestie adipiscing
lorem vel scelerisque. Donec vitae interdum est. Proin rutrum vulputate
faucibus. Suspendisse sit amet felis odio, non volutpat ante. Sed eu lectus
quam. Curabitur tristique rhoncus est, vel commodo tortor suscipit semper.
Maecenas feugiat vestibulum nisi id facilisis. Nulla non tincidunt libero.
Praesent ultrices interdum commodo. Sed euismod nisl auctor leo ultrices rutrum.
Aliquam nibh felis, congue molestie blandit at, bibendum at eros. Aenean
tincidunt, tortor iaculis placerat sollicitudin, lorem justo tempor diam, et
posuere sapien leo et magna. Quisque vel aliquam mauris.
Proin varius tempus fermentum. Cum sociis natoque penatibus et magnis dis
parturient montes, nascetur ridiculus mus. Sed tincidunt nunc id magna
adipiscing non sollicitudin turpis tempor. Etiam vel elit ipsum, quis euismod
velit. Quisque elementum magna vitae quam venenatis lacinia. Sed at arcu ipsum.
Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos
himenaeos. Donec ut lorem ac sapien cursus lacinia sit amet mollis dolor.
Vivamus tempus odio nec magna faucibus sed hendrerit lorem tempor.
Vestibulum eu nisi arcu. Curabitur nisi risus, fermentum ut lacinia ut, interdum
nec magna. Nunc aliquet gravida massa, eu aliquam lorem faucibus at. Sed
sollicitudin volutpat velit id tempor. In nibh justo, pharetra et pretium
dignissim, tempus in turpis. Phasellus eget lobortis nisl. Phasellus sed
fermentum diam. Nam tempus pharetra odio, quis congue eros imperdiet eu. Aliquam
dui eros, hendrerit et vulputate vel, porta eu eros. Nullam nisi dui, commodo
eget pharetra ut, ornare sit amet nunc. Fusce vel neque urna. Maecenas nulla
ante, egestas at consequat quis, fermentum a enim. Aliquam id tristique urna.
Integer augue justo, scelerisque et consectetur id, rhoncus eget enim.

View file

@ -0,0 +1,59 @@
---
title: Tu Quoque
author: Julius
tags: lorem, quam
---
Vestibulum leo turpis, dignissim quis ultrices sit amet, iaculis ac ligula.
Pellentesque tristique, velit eget scelerisque scelerisque, est dolor ultrices
arcu, quis ullamcorper justo arcu luctus mauris. Integer congue molestie nisi id
posuere. Fusce pellentesque gravida tempus. Integer viverra tortor nec eros
mollis quis convallis sem laoreet. Nulla id libero ac erat varius laoreet. Proin
sed est est. Curabitur lacinia fermentum lorem, elementum malesuada ipsum
malesuada ut. Donec suscipit elit id leo vehicula mattis non sed leo. Morbi
varius eleifend varius. Nulla vestibulum, neque vitae aliquam eleifend, nisi
tellus placerat nunc, quis suscipit elit turpis eu tortor. Etiam euismod
convallis lectus quis venenatis. Phasellus laoreet magna in nibh cursus eu
egestas nulla convallis. Aliquam vel ullamcorper risus. Fusce dictum, massa id
consequat viverra, nulla ante tristique est, a faucibus nisi enim nec dui. Donec
metus ligula, condimentum at porttitor eget, lobortis at quam.
Aenean vel libero in magna ultricies congue in a odio. Donec faucibus rutrum
ornare. Fusce dictum eleifend fermentum. Vestibulum vel nibh a metus porttitor
rhoncus. Pellentesque id quam neque, eget molestie arcu. Integer in elit vel
neque viverra ultricies in eget massa. Nam ut convallis est. Pellentesque eros
eros, sodales non vehicula et, tincidunt ut odio. Cras suscipit ultrices metus
sit amet molestie. Fusce enim leo, vehicula sed sodales quis, adipiscing at
ipsum.
Nunc tempor dignissim enim, sed tincidunt eros bibendum quis. Curabitur et dolor
augue, id laoreet mi. Nulla cursus felis id dui vehicula vitae ornare lorem
blandit. Cras eget dui nec odio volutpat pharetra. Fusce hendrerit justo justo,
vel imperdiet enim. Vivamus elit risus, interdum ultrices accumsan eleifend,
vestibulum vitae sapien. Integer bibendum ullamcorper tristique. Nulla quis odio
lectus, quis eleifend augue. Integer a ligula mauris. Aenean et tempus tortor.
Quisque at tortor mi. Vivamus accumsan feugiat est a blandit. Sed vitae enim ut
dolor semper sodales. Duis tristique, ante et placerat elementum, nulla tellus
pellentesque sapien, quis posuere velit mi eget nulla. Sed vestibulum nunc non
est porttitor ut rutrum nibh semper. Pellentesque habitant morbi tristique
senectus et netus et malesuada fames ac turpis egestas.
Nulla adipiscing ultricies lobortis. Vivamus iaculis nisl vitae tellus laoreet
vitae aliquet lacus mollis. Phasellus ut lacus urna, sed sagittis ante. Etiam
consectetur pretium nisl sed dignissim. Pellentesque convallis, nisl eget
commodo mollis, sem magna consequat arcu, sed pretium ipsum arcu sit amet neque.
Aliquam erat volutpat. Morbi sed mi sed urna vestibulum placerat vitae vel
metus. Fusce ac ante at justo pharetra vehicula. Vivamus vel tortor eget augue
aliquet aliquet at vel odio. Nunc venenatis, magna quis facilisis fringilla,
augue tellus varius neque, in vulputate est eros ut tortor. Duis lorem neque,
aliquam congue posuere id, condimentum non dui. Phasellus ut dui massa,
porttitor suscipit augue. Praesent quis tellus quam, vel volutpat metus. Vivamus
enim est, aliquam in imperdiet et, sagittis eu ligula. Vestibulum hendrerit
placerat orci et aliquet. Cras pharetra, dolor placerat lobortis tempor, metus
odio cursus ligula, et posuere lacus ligula quis dui.
Donec a lectus eu nibh malesuada aliquam. Proin at metus quam, et tincidunt leo.
Quisque lacus justo, scelerisque sodales pulvinar sed, dignissim ut sapien.
Vivamus diam felis, adipiscing sollicitudin ultricies id, accumsan ac felis. In
eu posuere ligula. Suspendisse potenti. Donec porttitor dictum dui id vehicula.
Integer ante velit, congue id dictum et, adipiscing a tortor.

1
shell.nix Normal file
View file

@ -0,0 +1 @@
(import ./release.nix { }).shell

198
site.hs Normal file
View file

@ -0,0 +1,198 @@
--------------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
import Data.Monoid (mappend)
import Data.List (sortBy)
import Data.Ord (comparing)
import Hakyll
import Control.Monad (liftM, forM_)
import System.FilePath (takeBaseName)
--------------------------------------------------------------------------------
main :: IO ()
main = hakyll $ do
match ("images/*" .||. "js/*") $ do
route idRoute
compile copyFileCompiler
match "css/*" $ do
route idRoute
compile compressCssCompiler
match "error/*" $ do
route $ (gsubRoute "error/" (const "") `composeRoutes` setExtension "html")
compile $ pandocCompiler
>>= applyAsTemplate siteCtx
>>= loadAndApplyTemplate "templates/default.html" (baseSidebarCtx <> siteCtx)
match "pages/*" $ do
route $ setExtension "html"
compile $ do
pageName <- takeBaseName . toFilePath <$> getUnderlying
let pageCtx = constField pageName "" `mappend`
baseNodeCtx
let evalCtx = functionField "get-meta" getMetadataKey `mappend`
functionField "eval" (evalCtxKey pageCtx)
let activeSidebarCtx = sidebarCtx (evalCtx <> pageCtx)
pandocCompiler
>>= saveSnapshot "page-content"
>>= loadAndApplyTemplate "templates/page.html" siteCtx
>>= loadAndApplyTemplate "templates/default.html" (activeSidebarCtx <> siteCtx)
>>= relativizeUrls
tags <- buildTags "posts/*" (fromCapture "tags/*.html")
match "posts/*" $ version "meta" $ do
route $ setExtension "html"
compile getResourceBody
match "posts/*" $ do
route $ setExtension "html"
compile $ do
posts <- loadAll ("posts/*" .&&. hasVersion "meta")
let taggedPostCtx = (tagsField "tags" tags) `mappend`
postCtx `mappend`
(relatedPostsCtx posts 3)
pandocCompiler
>>= saveSnapshot "content"
>>= loadAndApplyTemplate "templates/post.html" taggedPostCtx
>>= loadAndApplyTemplate "templates/default.html" (baseSidebarCtx <> siteCtx)
>>= relativizeUrls
create ["archive.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAllSnapshots ("posts/*" .&&. hasNoVersion) "content"
let archiveCtx =
listField "posts" postCtx (return posts) `mappend`
constField "title" "Archive" `mappend`
constField "archive" "" `mappend`
siteCtx
makeItem ""
>>= loadAndApplyTemplate "templates/archive.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" (baseSidebarCtx <> archiveCtx)
>>= relativizeUrls
paginate <- buildPaginateWith postsGrouper "posts/*" postsPageId
paginateRules paginate $ \page pattern -> do
route idRoute
compile $ do
posts <- recentFirst =<< loadAllSnapshots (pattern .&&. hasNoVersion) "content"
let indexCtx =
constField "title" (if page == 1 then "Home"
else "Blog posts, page " ++ show page) `mappend`
listField "posts" postCtx (return posts) `mappend`
constField "home" "" `mappend`
paginateContext paginate page `mappend`
siteCtx
makeItem ""
>>= applyAsTemplate indexCtx
>>= loadAndApplyTemplate "templates/index.html" indexCtx
>>= loadAndApplyTemplate "templates/default.html" (baseSidebarCtx <> indexCtx)
>>= relativizeUrls
match "templates/*" $ compile templateBodyCompiler
create ["atom.xml"] $ do
route idRoute
compile $ do
let feedCtx = postCtx `mappend`
bodyField "description"
posts <- fmap (take 10) . recentFirst =<< loadAllSnapshots ("posts/*" .&&. hasNoVersion) "content"
renderAtom feedConfig feedCtx posts
--------------------------------------------------------------------------------
postsGrouper :: MonadFail m => MonadMetadata m => [Identifier] -> m [[Identifier]]
postsGrouper = liftM (paginateEvery 3) . sortRecentFirst
postsPageId :: PageNumber -> Identifier
postsPageId n = fromFilePath $ if (n == 1) then "index.html" else show n ++ "/index.html"
--------------------------------------------------------------------------------
feedConfig :: FeedConfiguration
feedConfig = FeedConfiguration
{ feedTitle = "JFDI Collective"
, feedDescription = "Just Effing Doing It"
, feedAuthorName = "JFDI Collective"
, feedAuthorEmail = "collective@jfdic.org"
, feedRoot = "https://jfdic.org"
}
--------------------------------------------------------------------------------
siteCtx :: Context String
siteCtx =
baseCtx `mappend`
constField "site_description" "JFDI Collective" `mappend`
constField "site-url" "https://jfdic.org" `mappend`
constField "tagline" "Just Effing Doing It" `mappend`
constField "site-title" "JFDI Collective" `mappend`
constField "copy-year" "2021" `mappend`
constField "github-repo" "https://source.jfdic.org/jfdic/jfdic-web" `mappend`
defaultContext
baseCtx =
constField "baseurl" "http://localhost:8000"
--------------------------------------------------------------------------------
postCtx :: Context String
postCtx =
dateField "date" "%B %e, %Y" `mappend`
defaultContext
tagsRulesVersioned tags rules =
forM_ (tagsMap tags) $ \(tag, identifiers) ->
rulesExtraDependencies [tagsDependency tags] $
create [tagsMakeId tags tag] $
rules tag identifiers
relatedPostsCtx
:: [Item String] -> Int -> Context String
relatedPostsCtx posts n = listFieldWith "related_posts" postCtx selectPosts
where
rateItem ts i = length . filter (`elem` ts) <$> (getTags $ itemIdentifier i)
selectPosts s = do
postTags <- getTags $ itemIdentifier s
let trimmedItems = filter (not . matchPath s) posts
take n . reverse <$> sortOnM (rateItem postTags) trimmedItems
matchPath :: Item String -> Item String -> Bool
matchPath x y = eqOn (toFilePath . itemIdentifier) x y
eqOn :: Eq b => (a -> b) -> a -> a -> Bool
eqOn f x y = f x == f y
sortOnM :: (Monad m, Ord b) => (a -> m b) -> [a] -> m [a]
sortOnM f xs = map fst . sortBy (comparing snd) . zip xs <$> mapM f xs
--------------------------------------------------------------------------------
sidebarCtx :: Context String -> Context String
sidebarCtx nodeCtx =
listField "list_pages" nodeCtx (loadAllSnapshots ("pages/*" .&&. hasNoVersion) "page-content") `mappend`
defaultContext
baseNodeCtx :: Context String
baseNodeCtx =
urlField "node-url" `mappend`
titleField "title" `mappend`
baseCtx
baseSidebarCtx = sidebarCtx baseNodeCtx
evalCtxKey :: Context String -> [String] -> Item String -> Compiler String
evalCtxKey context [key] item = (unContext context key [] item) >>= \cf ->
case cf of
StringField s -> return s
_ -> error $ "Internal error: StringField expected"
getMetadataKey :: [String] -> Item String -> Compiler String
getMetadataKey [key] item = getMetadataField' (itemIdentifier item) key

4
templates/archive.html Normal file
View file

@ -0,0 +1,4 @@
<div class="page">
Here you can find all our previous posts:
$partial("templates/post-list.html")$
</div>

33
templates/default.html Normal file
View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html lang="en-us">
$partial("templates/head.html")$
<body>
$partial("templates/sidebar.html")$
<!-- Wrap is the content to shift when toggling the sidebar. We wrap the
content to avoid any CSS collisions with our real content. -->
<div class="wrap">
<div class="masthead">
<div class="container">
<h3 class="masthead-title">
<a href="$baseurl$" title="Home">$site-title$</a>
<small>$tagline$</small>
</h3>
</div>
</div>
<div class="container content">
$body$
</div>
</div>
<label for="sidebar-checkbox" class="sidebar-toggle"></label>
<script src='$baseurl$/public/js/script.js'></script>
</body>
</html>

35
templates/head.html Normal file
View file

@ -0,0 +1,35 @@
<head>
<!---
<link href="http://gmpg.org/xfn/11" rel="profile">
-->
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<title>
$if(home)$
$site-title$ &middot; $tagline$
$else$
$title$ &middot; $site-title$
$endif$
</title>
$if(url)$
$if(baseurl)$
<link rel="canonical" href="$baseurl$$url$">
$endif$
$endif$
<link rel="stylesheet" href="$baseurl$/css/base.css">
<link rel="stylesheet" href="$baseurl$/css/syntax.css">
<link rel="stylesheet" href="$baseurl$/css/jfdic.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">
<!---
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="{{ '/public/apple-touch-icon-precomposed.png' | absolute_url }}">
<link rel="shortcut icon" href="{{ '/public/favicon.ico' | absolute_url }}">
-->
<link rel="alternate" type="application/rss+xml" title="RSS" href="$baseurl$/atom.xml">
</head>

31
templates/index.html Normal file
View file

@ -0,0 +1,31 @@
<div class="posts">
$for(posts)$
<div class="post">
<h1 class="post-title">
<a href="$url$">
$title$
</a>
</h1>
<span class="post-date">$date$,
$if(author)$
Posted by $author$
$endif$
</span>
$body$
</div>
$endfor$
</div>
<div class="pagination">
$if(previousPageNum)$
<a class="pagination-item newer" href="$previousPageUrl$">Newer</a>
$else$
<span class="pagination-item newer">Newer</span>
$endif$
$if(nextPageNum)$
<a class="pagination-item older" href="$nextPageUrl$">Older</a>
$else$
<span class="pagination-item older">Older</span>
$endif$
</div>

4
templates/page.html Normal file
View file

@ -0,0 +1,4 @@
<div class="page">
<h1 class="page-title">$title$</h1>
$body$
</div>

7
templates/post-list.html Normal file
View file

@ -0,0 +1,7 @@
<ul>
$for(posts)$
<li>
<a href="$url$">$title$</a> - $date$
</li>
$endfor$
</ul>

31
templates/post.html Normal file
View file

@ -0,0 +1,31 @@
<div class="post">
<h1 class="post-title">
<a href="$url$">
$title$
</a>
</h1>
<span class="post-date">$date$,
$if(author)$
Posted by $author$
$endif$
</span>
$body$
</div>
$if(related_posts)$
<div class="related">
<h2>Related posts</h2>
<ul class="related-posts">
$for(related_posts)$
<li>
<h3>
<a href="$url$">
$title$
<small>$date$</small>
</a>
</h3>
</li>
$endfor$
</ul>
</div>
$endif$

38
templates/sidebar.html Normal file
View file

@ -0,0 +1,38 @@
<!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular
styles, `#sidebar-checkbox` for behavior. -->
<input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox">
<!-- Toggleable sidebar -->
<div class="sidebar" id="sidebar">
<div class="sidebar-item">
<p>$site_description$</p>
</div>
<nav class="sidebar-nav">
<a class="sidebar-nav-item$if(home)$ active$endif$" href="$baseurl$">Home</a>
<!--- The code below dynamically generates a sidebar nav of the files in the folder /pages -->
$for(list_pages)$
$if(title)$
<a class="sidebar-nav-item$if(eval(title))$ active$endif$" href="$baseurl$$node-url$">$title$</a>
$endif$
$endfor$
<a class="sidebar-nav-item$if(archive)$ active$endif$" href="$baseurl$/archive.html">Archive</a>
<a class="sidebar-nav-item" href="$github-repo$">GitHub project</a>
</nav>
<div class="sidebar-item">
<p>
&copy; $copy-year$. All rights reserved.
</p>
<p>
<img src="$baseurl$/images/haskell-logo.png" class=logo style="display: inline;"/>
Site created with
<a href="https://jaspervdj.be/hakyll">Hakyll</a>.
</p>
</div>
</div>