Преглед на файлове

lots of metadata things

main
James Fenn преди 2 месеца
родител
ревизия
f0c001314b
променени са 34 файла, в които са добавени 786 реда и са изтрити 453 реда
  1. +6
    -7
      .eleventy.js
  2. +2
    -0
      _data/git.js
  3. +3
    -1
      _data/meta.json
  4. +2
    -2
      _includes/footer.liquid
  5. +27
    -18
      _includes/head.liquid
  6. +0
    -7
      _includes/layouts/default.liquid
  7. +67
    -8
      _includes/layouts/project.liquid
  8. +6
    -0
      _includes/newsletter.liquid
  9. +8
    -0
      assets/css/styles.scss
  10. +5
    -0
      assets/images/ic/markdown-mark.svg
  11. Двоични данни
      favicon.ico
  12. +14
    -0
      meta/ieconfig.njk
  13. +60
    -0
      meta/keybase.njk
  14. +0
    -8
      meta/manifest.json
  15. +25
    -0
      meta/manifest.njk
  16. +10
    -0
      meta/robots.njk
  17. +14
    -0
      meta/sitemap.njk
  18. +57
    -0
      meta/sw.js.njk
  19. +1
    -1
      package.json
  20. +11
    -0
      pages/404.html
  21. +1
    -1
      pages/blog/index.html
  22. +1
    -1
      pages/blog/rss.njk
  23. +1
    -1
      pages/index.html
  24. +0
    -279
      pages/licenses.md
  25. +1
    -0
      pages/links.njk
  26. +11
    -4
      pages/now.md
  27. +408
    -0
      pages/policies.html
  28. +1
    -2
      pages/projects/index.html
  29. +0
    -85
      pages/projects/project.html
  30. +1
    -0
      pages/projects/wiki.html
  31. +12
    -18
      projects/attribouter.html
  32. +9
    -4
      projects/git-rest-wrapper.html
  33. +10
    -5
      projects/ktordocs.html
  34. +12
    -1
      projects/metronome.html

+ 6
- 7
.eleventy.js Целия файл

@@ -1,6 +1,5 @@
const _fs = require("fs");
const _markdown = require("markdown-it");
const _markdownAnchor = require("markdown-it-anchor");
const _yaml = require("js-yaml");
const _moment = require("moment");

@@ -13,22 +12,22 @@ module.exports = function(eleventyConfig) {
eleventyConfig.addLayoutAlias("base", "layouts/base.liquid");
eleventyConfig.addLayoutAlias("page", "layouts/page.liquid");

eleventyConfig.addPassthroughCopy("favicon.ico");
eleventyConfig.addPassthroughCopy("assets");
eleventyConfig.addPassthroughCopy({"assets/images": "images"});
eleventyConfig.addPassthroughCopy({"assets/files": "files"});
eleventyConfig.addPassthroughCopy("browserconfig.xml");
eleventyConfig.addPassthroughCopy("manifest.json");
eleventyConfig.addPassthroughCopy("favicon.ico");

const markdownItRenderer = new _markdown({ html: true }).use(
require('markdown-it-highlightjs')
);
const markdownItRenderer = new _markdown({ html: true })
.use(require('markdown-it-prism'), { plugins: ["autoloader"] })
.use(require("markdown-it-anchor"));

eleventyConfig.addFilter("markdownify", function(str) {
if (typeof str === 'string')
return markdownItRenderer.render(str);
});

eleventyConfig.setLibrary("md", markdownItRenderer);

eleventyConfig.addFilter("where", function(array, prop, value) {
return (array || []).filter((item) => item[prop] == value);
});


+ 2
- 0
_data/git.js Целия файл

@@ -53,11 +53,13 @@ async function getRepoProject(repo) {
} catch (e) {}

let screenshots = (meta.screenshots || []).map((url) => `${rawUrl}/${url}`);
let icon = meta.icon ? `${rawUrl}/${meta.icon}` : null;

let project = {
id: id.toLowerCase(),
repo,
title,
icon,
screenshots,
readme,
hasWiki: false


+ 3
- 1
_data/meta.json Целия файл

@@ -1,8 +1,10 @@
{
"domainurl": "https://jfenn.me",
"name": "James Fenn",
"email": "me@jfenn.me",
"description": "Writer of bad puns and slightly better software. This website contains information about my adventures in programming, current projects, and me.",
"icon": "/assets/images/logo.png",
"icon": "/images/me.jpg",
"image": "/images/headers/snowytrees.jpg",
"links": {
"twitter": "https://twitter.com/fennifith",
"fediverse": "https://is.a.horrific.dev/@james",


+ 2
- 2
_includes/footer.liquid Целия файл

@@ -1,7 +1,7 @@
<footer class="footer">
<div class="container">
<a class="footer-link" href="https://code.horrific.dev/james/jfenn.me">Website Source Code</a>
<a class="footer-link" href="/policies/">Privacy Policy</a>
<a class="footer-link" href="/licenses/">Open Source Licenses</a>
<a class="footer-link" href="/contact/">Contact Me</a>
<a class="footer-link" href="/policies/?web">Privacy Policy</a>
</div>
</footer>

+ 27
- 18
_includes/head.liquid Целия файл

@@ -10,11 +10,17 @@

{% assign head_description = meta.description %}
{% if description %}
{% assign head_description = description %}
{% assign head_description = description | xml_escape %}
{% elsif renderData.description %}
{% assign head_description = renderData.description %}
{% assign head_description = renderData.description | xml_escape %}
{% endif %}

{% assign head_icon = meta.domainurl | append: meta.icon %}
{% if icon %}{% assign head_icon = icon %}{% endif %}

{% assign head_image = meta.domainurl | append: meta.image %}
{% if image %}{% assign head_image = image %}{% endif %}

<meta name="description" content="{{ head_description }}">
<meta name="author" content="{{ meta.author }}">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
@@ -26,23 +32,18 @@

<meta name="application-name" content="{{ meta.name }}">
<meta name="msapplication-TileColor" content="#FFFFFF">
<meta name="msapplication-TileImage" content="/assets/images/ms-icon-144x144.png">
<meta name="msapplication-TileImage" content="/images/favicon-144.png">
<meta name="msapplication-tooltip" content="{{ meta.description }}">
<meta name="msapplication-config" content="/ieconfig.xml">

<link rel="apple-touch-icon" sizes="57x57" href="/assets/images/apple-icon-57x57.png">
<link rel="apple-touch-icon" sizes="60x60" href="/assets/images/apple-icon-60x60.png">
<link rel="apple-touch-icon" sizes="72x72" href="/assets/images/apple-icon-72x72.png">
<link rel="apple-touch-icon" sizes="76x76" href="/assets/images/apple-icon-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/assets/images/apple-icon-114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="/assets/images/apple-icon-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/assets/images/apple-icon-144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/assets/images/apple-icon-152x152.png">
<link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-icon-180x180.png">
<link rel="icon" type="image/png" sizes="192x192" href="/assets/images/android-icon-192x192.png">
<link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="96x96" href="/assets/images/favicon-96x96.png">
<link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
<link rel="apple-touch-icon" sizes="70x70" href="/images/favicon-70.png">
<link rel="apple-touch-icon" sizes="144x144" href="/images/favicon-144.png">
<link rel="apple-touch-icon" sizes="152x152" href="/images/favicon-152.png">
<link rel="icon" type="image/png" sizes="192x192" href="{{ icon | default: '/images/favicon-192.png' }}">
<link rel="icon" type="image/png" sizes="32x32" href="{{ icon | default: '/images/favicon-32.png' }}">
<link rel="icon" type="image/png" sizes="96x96" href="{{ icon | default: '/images/favicon-96.png' }}">
<link rel="icon" type="image/png" sizes="16x16" href="{{ icon | default: '/images/favicon-16.png' }}">
<link rel="shortcut icon" href="{{ icon | default: '/favicon.ico' }}">

<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="white">
@@ -55,11 +56,19 @@
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{{ head_title }}">
<meta name="twitter:description" content="{{ head_description }}">
<meta name="twitter:image" content="https://jfenn.me{{ meta.icon }}">
<meta name="twitter:image" content="{{ head_icon }}">
<meta name="twitter:creator" content="@fennifith">
<meta name="twitter:site" content="@fennifith">

<meta name="og:title" content="{{ head_title }}">
<meta name="og:type" content="website">
<meta name="og:image" content="https://jfenn.me{{ meta.icon }}">
<meta name="profile:first_name" content="James">
<meta name="profile:last_name" content="Fenn">
<meta name="profile:username" content="fennifith">
<meta name="og:image" content="{{ head_image }}">
<meta name="og:url" content="{{ meta.domainurl }}{{ page.url | url }}">
<meta name="og:description" content="{{ head_description }}">
<meta name="og:locale" content="en_US">
<meta name="og:site_name" content="{{ meta.name }}">

<link href="//unpkg.com/prism-themes@1.5.0/themes/prism-ghcolors.css" rel="stylesheet">

+ 0
- 7
_includes/layouts/default.liquid Целия файл

@@ -3,15 +3,8 @@
<html lang="en">
<head>
{% include head.liquid %}
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/styles/atelier-cave-dark.min.css" rel="stylesheet">
</head>
<body class="{% if nav %}nav-container {% endif %}footer-container">
{{ content | safe }}

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/highlight.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/languages/kotlin.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/languages/java.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.8.0/languages/shell.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>

+ 67
- 8
_includes/layouts/project.liquid Целия файл

@@ -1,8 +1,14 @@
---
layout: base
---
<!DOCTYPE html>

{% assign project = git.projects | where: 'id', page.fileSlug | first %}
<html lang="en">
<head>
{% assign project = git.projects | where: 'id', page.fileSlug | first %}
{% include head, title: project.title, description: project.repo.description, icon: project.icon %}
</head>
<body class="nav-container footer-container">
{% include nav %}

<div class="bg-secondary py-5">
<div class="container text-center">
@@ -62,7 +68,7 @@ layout: base
</div>

{% if project.hasWiki %}
<div class="bg-lighter py-5">
<div class="bg-lighter py-4">
<div class="container pb-2">
<div class="row">
<div class="col-12 col-md-auto align-self-center text-center">
@@ -78,11 +84,64 @@ layout: base
</div>
{% endif %}

{% assign sections = content | split: '<hr>' %}
{% for section in sections %}
<div class="bg-{% cycle 'neutral', 'lighter' %} py-4">
<div class="container">
{{ section | safe }}
{% if tags contains "project-deprecated" %}
<div class="bg-danger-5 py-5">
<div class="container">
<div class="row">
<div class="col-12 col-md-auto align-self-center text-center">
<i class="material-icons text-danger" style="font-size: 100px;">error_outline</i>
</div>
<div class="col-12 col-md-8 align-self-center text-center text-md-left">
<h5 class="text-tertiary-1">This project is deprecated!</h5>
<p>Pull requests may still be accepted, but I am no longer actively maintaining it and proper functionality is not guaranteed.</p>
<p>If you would like to fork this project and continue development, please <a href="/contact/">contact me</a> so I can link to your fork from this page.</p>
</div>
</div>
</div>
</div>
{% endif %}

{% capture lastSection %}
<div class="row">
<div class="col-12 col-md-auto align-self-center text-center">
<i class="material-icons" style="font-size: 100px;">source</i>
</div>
<div class="col-12 col-md-8 align-self-center text-center text-md-left">
<h3 class="mb-2">Open Source</h3>
<p class="mt-0 mb-4">Browse the source code, suggest changes, or <a href="/community/">develop it yourself</a>!</p>
<a class="btn btn-primary" href="{{ project.repo.url }}">Git Repo <i class="material-icons" style="padding-bottom: 0.1rem;">chevron_right</i></a>
</div>
</div>

<div id="readme" class="card bg-light border-dark mt-5">
<div class="py-2 px-4 bg-dark">
<a class="link" href="{{ project.repo.url }}">
<i class="link-img material-icons">book</i>
<span class="link-title">README.md</span>
</a>
</div>
<div class="py-2 px-4 text">
{{ project.readme | markdownify }}
</div>
</div>
{% endcapture %}

{% assign contents = content | split: '===' %}
{% if contents.size > 1 %}
{% assign sections = content | append: '===' | append: lastSection | split: '===' %}
{% else %}
{% assign sections = lastSection | split: '===' %}
{% endif %}

{% for section in sections %}
<div class="bg-{% cycle 'neutral', 'lighter' %} py-4">
<div class="container">
{{ section | safe }}
</div>
</div>
{% endfor %}

{% include footer %}

</body>
</html>

+ 6
- 0
_includes/newsletter.liquid Целия файл

@@ -0,0 +1,6 @@
<div class="bg-accent-5">
<div class="container my-5 text-center">
<h3 class="mb-2">Stay up to date!</h3>
<!-- TODO: insert socials -->
</div>
</div>

+ 8
- 0
assets/css/styles.scss Целия файл

@@ -33,6 +33,14 @@ a:focus > code {
filter: contrast(0) brightness(2);
}

pre > code {
line-height: 1.25rem !important;
}

pre > code * {
font-size: 0.8571428571rem !important;
}

* {
animation: none !important;
}

+ 5
- 0
assets/images/ic/markdown-mark.svg Целия файл

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
<path fill="#606060" d="M20.56 18H3.44C2.65 18 2 17.37 2 16.59V7.41C2 6.63 2.65 6 3.44 6H20.56C21.35 6 22 6.63 22 7.41V16.59C22 17.37 21.35 18 20.56 18M3.44 6.94C3.18 6.94 2.96 7.15 2.96 7.41V16.6C2.96 16.85 3.18 17.06 3.44 17.06H20.56C20.82 17.06 21.04 16.85 21.04 16.6V7.41C21.04 7.15 20.82 6.94 20.56 6.94H3.44M4.89 15.19V8.81H6.81L8.73 11.16L10.65 8.81H12.58V15.19H10.65V11.53L8.73 13.88L6.81 11.53V15.19H4.89M16.9 15.19L14 12.09H15.94V8.81H17.86V12.09H19.79L16.9 15.19" />
</svg>

Двоични данни
favicon.ico Целия файл

Преди След

+ 14
- 0
meta/ieconfig.njk Целия файл

@@ -0,0 +1,14 @@
---
permalink: /ieconfig.xml
eleventyExcludeFromCollections: true
---
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square70x70logo src="/images/favicon-70.png"/>
<square150x150logo src="/images/favicon-150.png"/>
<TileColor>#FFFFFF</TileColor>
</tile>
</msapplication>
</browserconfig>

+ 60
- 0
meta/keybase.njk Целия файл

@@ -0,0 +1,60 @@
---
permalink: /keybase.txt
eleventyExcludeFromCollections: true
---
==================================================================
https://keybase.io/jafenn
--------------------------------------------------------------------

I hereby claim:

* I am an admin of https://jfenn.me
* I am jafenn (https://keybase.io/jafenn) on keybase.
* I have a public key ASAqbtXJuDtfshrI2lXMoTYs_cTyYm_RQzLAKySvcfRS1Ao

To do so, I am signing this object:

{
"body": {
"key": {
"eldest_kid": "01202a6ed5c9b83b5fb21ac8da55cca1362cfdc4f2626fd14332c02b24af71f452d40a",
"host": "keybase.io",
"kid": "01202a6ed5c9b83b5fb21ac8da55cca1362cfdc4f2626fd14332c02b24af71f452d40a",
"uid": "e6494057cbb6c22d574adfd416516a19",
"username": "jafenn"
},
"merkle_root": {
"ctime": 1533769511,
"hash": "aea95ec3905ce46e2b9a61f5e7db541dae328e76ee19906f1f56f77a9a39ad2a86302bf4e353bc6432520eaf7772db293a8f4b1d6698473f74101c2ab049cfa3",
"hash_meta": "dcee4f3e0ee1753dd71013901dc84b1ee1d03ca9b049a890ac1371b022f247cf",
"seqno": 3429213
},
"service": {
"entropy": "LQFOrJFJvKWCupiCN7DT8NEe",
"hostname": "jfenn.me",
"protocol": "https:"
},
"type": "web_service_binding",
"version": 2
},
"client": {
"name": "keybase.io go client",
"version": "2.3.0"
},
"ctime": 1533769536,
"expire_in": 504576000,
"prev": "4f89596d003467aadd9d20385d17be293fb955c3d45bb00d2657a23bb9fa99d0",
"seqno": 9,
"tag": "signature"
}

which yields the signature:

hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgKm7Vybg7X7IayNpVzKE2LP3E8mJv0UMywCskr3H0UtQKp3BheWxvYWTESpcCCcQgT4lZbQA0Z6rdnSA4XRe+KT+5VcPUW7ANJleiO7n6mdDEIPdFYV0ArW3Bwf1tjHExw/2mdCDNwhB8V4mGc7uVBy2DAgHCo3NpZ8RAY4GFT1Vm3SAuveWp/kYx7QWBBPrYF5JH9KWD1DPOHthHvoBsL7gcqtfnXV25QFaKnoSnM4YMv/D4/juUFog+BahzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEIFJHLG3y/i8AdDuvEz6LYH8f8x5mLRZDmxTe9V/UJRJXo3RhZ80CAqd2ZXJzaW9uAQ==

And finally, I am proving ownership of this host by posting or
appending to this document.

View my publicly-auditable identity here: https://keybase.io/jafenn

==================================================================

+ 0
- 8
meta/manifest.json Целия файл

@@ -1,8 +0,0 @@
{
"name": "James Fenn",
"short_name": "James Fenn",
"start_url": "/",
"background_color": "#FFFFFF",
"display": "standalone",
"theme_color": "#000000"
}

+ 25
- 0
meta/manifest.njk Целия файл

@@ -0,0 +1,25 @@
---
permalink: /manifest.json
eleventyExcludeFromCollections: true
---
{
"name": "James Fenn",
"short_name": "James Fenn",
"icons": [{
"src": "/images/favicon-96.png",
"sizes": "96x96",
"type": "image/png"
}, {
"src": "/images/favicon-144.png",
"sizes": "144x144",
"type": "image/png"
}, {
"src": "/images/favicon-192.png",
"sizes": "192x192",
"type": "image/png"
}],
"start_url": "/",
"background_color": "#FFFFFF",
"display": "standalone",
"theme_color": "#000000"
}

+ 10
- 0
meta/robots.njk Целия файл

@@ -0,0 +1,10 @@
---
permalink: /robots.txt
eleventyExcludeFromCollections: true
---
User-agent: *
Disallow:
Disallow: /links/*
Disallow: /redirects/*
Disallow: /about/*
Sitemap: https://jfenn.me/sitemap.xml

+ 14
- 0
meta/sitemap.njk Целия файл

@@ -0,0 +1,14 @@
---
permalink: /sitemap.xml
eleventyExcludeFromCollections: true
---
<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{% for page in collections.all %}
<url>
<loc>{{ site.url }}{{ page.url | url }}</loc>
<lastmod>{{ page.date.toISOString() }}</lastmod>
<changefreq>{{ page.data.changeFreq if page.data.changeFreq else "monthly" }}</changefreq>
</url>
{% endfor %}
</urlset>

+ 57
- 0
meta/sw.js.njk Целия файл

@@ -0,0 +1,57 @@
---
permalink: /sw.js
eleventyExcludeFromCollections: true
---
importScripts('https://storage.googleapis.com/workbox-cdn/releases/3.6.1/workbox-sw.js');

if (workbox) {
workbox.precaching.precacheAndRoute([]);

// Cache the Google Fonts stylesheets with a stale while revalidate strategy.
workbox.routing.registerRoute(
/^https:\/\/fonts\.googleapis\.com/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'google-fonts-stylesheets',
}),
);

// Cache the Google Fonts webfont files with a cache first strategy for 1 year.
workbox.routing.registerRoute(
/^https:\/\/fonts\.gstatic\.com/,
workbox.strategies.cacheFirst({
cacheName: 'google-fonts-webfonts',
plugins: [
new workbox.cacheableResponse.Plugin({
statuses: [0, 200],
}),
new workbox.expiration.Plugin({
maxAgeSeconds: 60 * 60 * 24 * 365,
}),
],
}),
);

workbox.routing.registerRoute(
// Cache CSS files
/.*\.css/,
workbox.strategies.staleWhileRevalidate({
cacheName: 'css-cache',
})
);

workbox.routing.registerRoute(
// Cache image files
/.*\.(?:png|jpg|jpeg|svg|gif)/,
workbox.strategies.cacheFirst({
cacheName: 'image-cache',
plugins: [
new workbox.expiration.Plugin({
maxEntries: 100,
maxAgeSeconds: 7 * 24 * 60 * 60,
})
],
})
);
} else {
console.log("Workbox didn't load...");
}

+ 1
- 1
package.json Целия файл

@@ -29,7 +29,7 @@
"js-yaml": "^3.14.0",
"markdown-it": "^10.0.0",
"markdown-it-anchor": "^5.2.5",
"markdown-it-highlightjs": "^3.2.0",
"markdown-it-prism": "^2.1.3",
"moment": "^2.27.0",
"node-fetch": "^2.6.0",
"nodegit": "^0.27.0",


+ 11
- 0
pages/404.html Целия файл

@@ -0,0 +1,11 @@
---
layout: default
title: FOUR HUNDRED AND FOUR
permalink: /404.html
---

<main class="container text text-center pt-5">
<h1>Error 404</h1>
<p>Unfortunately, the page you're looking for doesn't exist. Maybe you made a typo, or maybe the page was moved or deleted.</p>
<p class="mt-5"><a class="btn btn-accent" href="/">Homepage</a></p>
</main>

+ 1
- 1
pages/blog/index.html Целия файл

@@ -24,7 +24,7 @@ permalink: /blog/
</div>

{% assign year = "" %}
{% for blog in collections.blog %}
{% for blog in collections.blog reversed %}
{% assign year2 = blog.date | date: "%Y" %}
{% if year != year2 %}
{% assign year = year2 %}


+ 1
- 1
pages/blog/rss.njk Целия файл

@@ -21,7 +21,7 @@ metadata:
<name>{{ meta.name }}</name>
<email>{{ meta.email }}</email>
</author>
{%- for post in collections.blog %}
{%- for post in collections.blog -%}
{% set absolutePostUrl %}{{ post.url | url | absoluteUrl(metadata.url) }}{% endset %}
<entry>
<title>{{ post.data.title }}</title>


+ 1
- 1
pages/index.html Целия файл

@@ -22,7 +22,7 @@ permalink: /

{% assign links = "twitter fediverse github linkedin" | split: " " %}
{% for link in links %}
<a class="link" href="{{ meta.links[link] }}">
<a rel="me" class="link" href="{{ meta.links[link] }}">
<img class="link-img" src="/images/ic/{{ link }}.svg">
</a>
{% endfor %}


+ 0
- 279
pages/licenses.md Целия файл

@@ -1,279 +0,0 @@
---
layout: page
permalink: /licenses/
---

<div class="text">

# Open Source Licenses

This page lists all (I hope) of the open source projects that are used to create, update, and maintain my personal site.

## [11ty](https://11ty.dev/)

```
MIT License

Copyright (c) 2020 Zach Leatherman @zachleat

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [NodeJS](https://nodejs.org/)

```
Copyright Node.js contributors. All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to
deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
```

## [then-request](https://github.com/then/then-request)

A request library that returns promises.

```
Copyright (c) 2014 Forbes Lindesay

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
```

## [cheerio](https://github.com/cheeriojs/cheerio)

A fast, flexible, and lean implementation of core jQuery designed specifically for the server.

```
MIT License

Copyright (c) 2016 Matt Mueller

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [instant.page](https://github.com/instantpage/instant.page)

A small library that preloads linked pages before a user clicks on them.

```
MIT License

Copyright (C) 2019 Alexandre Dieulot

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [lozad.js](https://github.com/ApoorvSaxena/lozad.js)

Highly performant, light and configurable lazy loader in pure JS with no dependencies for images, iframes and more, using the IntersectionObserver API.

```

The MIT License (MIT)

Copyright (c) 2017 Apoorv Saxena

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [git-clone](https://github.com/jaz303/git-clone)

A NodeJS interface to clone a git repository via shell commands.

```
Copyright 2014 Jason Frame

Permission to use, copy, modify, and/or distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright notice
and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
```

## [mdjavadoc](https://github.com/TheAndroidMaster/mdjavadoc)

A script that generates markdown javadocs primarily for use in Jekyll and GitHub Pages.

```
MIT License

Copyright (c) 2018 James Fenn

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [js-yaml](https://github.com/nodeca/js-yaml)

An implementation of [YAML](http://yaml.org/), a human-friendly data serialization language, for JavaScript.

```
(The MIT License)

Copyright (C) 2011-2015 by Vitaly Puzrin

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```

## [Highlight.js](https://highlightjs.org/)

Highlight.js is a syntax highlighter written in JavaScript. It works in the browser as well as on the server. It works with pretty much any markup, doesn’t depend on any framework, and has automatic language detection.

```
Copyright (c) 2006, Ivan Sagalaev
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of highlight.js nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
```

</div>

+ 1
- 0
pages/links.njk Целия файл

@@ -3,6 +3,7 @@ pagination:
data: meta.links
size: 1
permalink: "links/{{ pagination.items[0] }}.html"
eleventyExcludeFromCollections: true
---

<!DOCTYPE html>


+ 11
- 4
pages/now.md Целия файл

@@ -1,11 +1,12 @@
---
layout: page
layout: base
permalink: /now/
---

<div class="text">
<div style="height: 300px; background-image: url('/images/headers/snowytrees.jpg'); background-size: cover; background-position: center bottom; background-repeat: no-repeat;"></div>
<div class="container text">

This is a [now page](https://nownownow.com/about). It's a simple way to describe everything currently happening in my life. Last updated on 2020-12-08.
This is a [now page](https://nownownow.com/about). It's a simple way to share everything currently happening in my life. I last updated it on 2020-12-08.

## What am I doing now?

@@ -13,6 +14,12 @@ This is a [now page](https://nownownow.com/about). It's a simple way to describe
- taking CS classes at the [University of Pittsburgh](https://www.pitt.edu/)
- building websites, software, and website-managing software for [Trevian International](https://trevian.xyz/)
- [playing Minecraft](https://minecraft.horrific.dev/) with a group of friends and pondering [confusing redstone mechanics](https://minecraft.gamepedia.com/Tutorials/Quasi-connectivity)
- organizing things at [horrific.dev](https://horrific.dev/)
- sipping chai tea and listening to [65daysofstatic](https://65daysofstatic.bandcamp.com/music)

### Groups I'm involved with

[Unicorn Utterances](https://unicorn-utterances.com/) is a collaborative blog site that provides helpful resources for a variety of computer science-related topics.

[Horrific.Dev](https://horrific.dev/) is a small collective of individual developers and enthusiasts with a focus on independent services, software, and technology.

</div>

+ 408
- 0
pages/policies.html Целия файл

@@ -0,0 +1,408 @@
---
permalink: /policies/
---

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<meta name="description" content="View privacy policies for products by James Fenn.">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="Privacy Policies" />
<title>Privacy Policies</title>
<meta name="theme-color" content="#BDBDBD">
<meta name="mobile-web-app-capable" content="yes">
<link rel="manifest" href="manifest.json">
<meta name="application-name" content="Privacy Policies">
<meta name="msapplication-TileColor" content="#000000">
<meta name="msapplication-tooltip" content="Privacy Policies">
<meta name="msapplication-config" content="/ieconfig.xml">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="icon" sizes="16x16" href="/favicon.ico">
<link rel="icon" sizes="24x24" href="/images/favicon-24.ico">
<link rel="icon" sizes="32x32" href="/images/favicon-32.ico">
<link rel="icon" sizes="48x48" href="/images/favicon-48.ico">
<link rel="icon" sizes="64x64" href="/images/favicon-48.ico">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="Privacy Policies">
<link rel="apple-touch-icon-precomposed" href="/images/favicon-152.png">
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
* {
font-family: 'Roboto Slab', serif;
animation-name: fadeIn;
animation-duration: .3s;
animation-delay: .1s;
animation-timing-function: ease-out;
animation-fill-mode: forwards;
opacity: 0;
}
@keyframes fadeIn {
from {opacity: 0;}
to {opacity: 1;}
}
body {
padding: 0px;
margin: 0px;
background-color: #F5F5F5;
}

header, footer {
background-color: #E0E0E0;
padding: 2em;
}

main {
background-color: #FFFFFF;
padding: 2em;
}
p > .material-icons,
a > .material-icons {
transform: translateY(5px);
}

.button {
background-color: #C4C4C4;
color: #000000;
display: inline-block;
padding-left: 1.5em;
padding-right: 1.5em;
padding-top: .5em;
padding-bottom: calc(.5em + 5px);
border-radius: .25em;
font-weight: bold;
transition: background-color .25s;
user-select: none;
text-decoration: none;
cursor: pointer;
}

.button:hover {
background-color: #B2B2B2;
}

#policy {
display: none;
}

@media(min-width: 1000px) {
body {
padding: calc(10% + 2em);
}
}
</style>
</head>

<body>
<header>
<h2>Privacy Policies</h2>
<a id="back" class="button" href="/policies/">
<i class="material-icons">arrow_back</i> View All
</a>
</header>
<main>
<p id="home"></p>
<div id="policy">
James Fenn built the ${name} service as a ${price} and ${oss} ${type}. This service is
provided by James Fenn at no cost and is intended for use as is.
<br><br>
This page is used to inform ${type} users of my policies regarding the collection, use,
and disclosure of any personal information that this ${type} collects during the use of
my service.
<br><br>
If you choose to use my service, then you agree to the collection and use of information
in relation to this policy. The personal information that I collect is used to provide
and improve the service. I will not use or share your information with any party except
as described in this privacy policy.
<h3>Information Collection and Use</h3>
For a better experience during the use of my service, I may ask that you provide me with
certain personally identifiable information described below. The information that I request
is ${use}.
<ul>
${data::<li>I may request your ${info} in order to ${inorderto}.</li>::}
</ul>
<h3>Cookies</h3>
Cookies are files with a small amount of data that are commonly used as anonymous unique
identifiers. These are sent to your browser from websites that you visit and are stored on your
device's internal memory.
<br><br>
This service ${cookies:usage}. These "cookies" are ${cookies:use}. You have the option to either
accept or refuse these cookies and know when a cookie is being sent to your device. If you choose
to refuse these cookies, you will not be invited to my annual bake sale.
<h3>Security</h3>
I value your trust in providing me with yor personal information, and as such I am striving to use
commercially acceptable means of protecting it. However, please be aware that no method of transmission
over the internet or method of electronic storage is 100% secure, and I cannot guarantee its absolute
security.
<br><br>
Additionally, in the event that someone in my near vicinity visits the webpage located at
<a href="https://youtu.be/dQw4w9WgXcQ">https://youtu.be/dQw4w9WgXcQ</a> with their speakers at their
interpretation of "full blast", I may abandon any security maintenance activities that I happen to
be in the process of performing in order to substitute that with my interpretation of "appreciating my jam".
<h3>Links to Other Services</h3>
This service may contain links to other websites and applications not developed by me. If you open a
third-party link, you will be directed to that service. Note that these services are not operated by
me. Therefore, I strongly advise you to review the Privacy Policy of these services. I have no control
over and assume no responsibility for the content, privacy policies, or practices of any third-party sites
or services.
<h3>Children's Privacy</h3>
This privacy policy does not address anyone under the age of 13. I do not knowingly collect personally
identifiable information from children under 13. In the case that I discover that a child under 13 has
provided me with personal information, any relevant information will be immediately removed from my
servers. If you are a parent or guardian and you are aware that your child has provided me with personal
information, please contact me so that I am able to perform the necessary actions.
<h3>Changes to this Privacy Policy</h3>
I may update this privacy policy from time to time. Thus, you are advised to review this page periodically
for any changes. I will notify you of any changes by posting the new privacy policy on this page. These changes
are effective immediately after they are posted on this page.
<h3>Contact Me</h3>
If you have any questions about this privacy policy, please do not hesitate to contact me at
<a href="mailto:policies@jfenn.me">policies@jfenn.me</a>.
<br>
<br>
<br>
This privacy policy was last updated on ${lastUpdated}.
</div>
</main>
<footer>
This privacy policy page is loosely based on the
<a href="https://app-privacy-policy-generator.firebaseapp.com/">App Privacy Policy Generator</a>, which is derived
from <a href="https://privacypolicytemplate.net/">privacypolicytemplate.net</a>.
</footer>
<script>
var homeElement = document.getElementById("home");
var policyElement = document.getElementById("policy");
var backElement = document.getElementById("back");
var policies = {
web: {
name: "jfenn.me",
price: "free",
oss: "partially open source",
type: "website",
use: "retained on your device and is not collected by me in any way",
data: [
{
info: "language",
inorderto: "provide appropriately translated text for users that may not easily understand English"
}
],
cookies: {
usage: "only uses these \"cookies\" to store the most recent date of access along with temporary cached data",
use: "used only to display relevant information to the user and to update that information once the website determines that it has gone out of date"
},
lastUpdated: "June 6, 2018"
},
status: {
name: "Status",
price: "free",
oss: "open source",
type: "app",
use: "retained on your device and is not collected by me in any way",
data: [
{
info: "notifications",
inorderto: "display customizable heads-up popups and notification icons in the status bar"
},
{
info: "internet connection details",
inorderto: "display network information in the status bar"
},
{
info: "bluetooth data",
inorderto: "display a bluetooth icon in the status bar when bluetooth is enabled"
},
{
info: "location data",
inorderto: "display a GPS icon in the status bar when your device has a fix on your location"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "June 6, 2018"
},
chargescreen: {
name: "Charge Screen",
price: "free",
oss: "open source",
type: "app",
use: "retained on your device and is not collected by me in any way",
data: [
{
info: "device statistics",
inorderto: "display the current battery percentage and estimated charge time"
},
{
info: "phone state",
inorderto: "prevent the app from interfering with incoming calls"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "June 6, 2018"
},
simplecamera: {
name: "Simple Camera",
price: "free",
oss: "open source",
type: "app",
use: "retained on your device and is not collected by me in any way",
data: [
{
info: "device\'s camera input",
inorderto: "capture and store images and make them accessible to other applications on your device"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "June 6, 2018"
},
rocket: {
name: "Rocket",
price: "free",
oss: "open source",
type: "app",
use: "retained on your device and is not collected by me in any way",
data: [
{
info: "name",
inorderto: "display your high score on a leaderboard"
},
{
info: "email",
inorderto: "connect to your account using <a href=\"https://policies.google.com/privacy?hl=en&gl=us\">Google Play Services</a>"
},
{
info: "profile picture",
inorderto: "display your high score on a leaderboard along with your profile picture"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "June 6, 2018"
},
pacomplainter: {
name: "Port Authority Feedback Reporter",
price: "free",
oss: "open source",
type: "app",
use: "shared only with the Pittsburgh Port Authority and is not collected by me in any way",
data: [
{
info: "name",
inorderto: "complete the feedback form"
},
{
info: "email",
inorderto: "complete the feedback form"
},
{
info: "phone number",
inorderto: "complete the feedback form"
},
{
info: "location",
inorderto: "complete the feedback form"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "June 6, 2018"
},
cronhubclient: {
name: "CronHub Monitor",
price: "free",
oss: "open source",
type: "app",
use: "shared only with cronhub.io and is not collected by me in any way",
data: [
{
info: "Cronhub API key",
inorderto: "access information from cronhub.io"
}
],
cookies: {
usage: "does not use these \"cookies\" explicitly. However, the app may use third party code and libraries that use \"cookies\" to collect information and improve their services",
use: "stored on your device and are not accessed by me in any way"
},
lastUpdated: "August 21, 2018"
}
}

function format(data, obj, prefix) {
console.log(obj);
if (obj.constructor == Object) {
for (var key in obj) {
if (obj[key].constructor == Array) {
var index = data.indexOf("${" + (prefix ? prefix + ":" + key : key) + "::");
while (index >= 0) {
var replacement = "";
var text = data.substring(index + 2);
text = text.substring(text.indexOf("::") + 2);
text = text.substring(0, text.indexOf("::"));
for (var i = 0; i < obj[key].length; i++)
replacement += format(text, obj[key][i]);
data = data.substring(0, index) + replacement + data.substring(index + text.length + 11);
index = data.indexOf("${" + (prefix ? prefix + ":" + key : key) + "::");
}
} else if (obj[key].constructor == Object) {
data = format(data, obj[key], prefix ? prefix + ":" + key : key);
} else {
data = data.replace(new RegExp("(\\$\\{)(" + (prefix ? prefix + ":" : "") + key + ")(\\})", "g"), obj[key]);
}
}
}

return data;
}

window.onpopstate = function(e) {
window.location.reload();
};

for (var key in policies) {
homeElement.innerHTML += "<a href=\"?" + key + "\">" + policies[key].name + "</a><br><br>";
}

var page = window.location.search.substring(1);
var isPage;
for (var key in policies) {
if (page == key) {
isPage = true;
homeElement.style.display = "none";
policyElement.style.display = "block";
backElement.style.display = "inline-block";

policyElement.innerHTML = format(policyElement.innerHTML, policies[key]);
break;
}
}
if (!isPage) {
shouldAddEntry = true;
homeElement.style.display = "block";
policyElement.style.display = "none";
backElement.style.display = "none";
}
</script>
</body>

</html>

+ 1
- 2
pages/projects/index.html Целия файл

@@ -13,8 +13,7 @@ permalink: /projects/
</p>
<p>
Actually, there is a lot of discourse about how such "indie software" should
be shared with the community, and I've been experimenting with my own
solutions. You can read more about that <a href="/community/">here</a>.
be shared with the community. You can read more about that <a href="/community/">here</a>.
</p>
</div>
</div>


+ 0
- 85
pages/projects/project.html Целия файл

@@ -1,85 +0,0 @@
---
layout: base
pagination:
data: git.projects
size: 1
permalink: "projects2/{{ pagination.items[0].id }}/index.html"
---

{% for project in pagination.items %}
<div class="bg-secondary py-5">
<div class="container text-center">
<h1 class="text-light" style="text-shadow: 0 0 20px #82a7ce;">{{ project.title }}</h1>
<p class="mt-0 text-light-2">{{ project.repo.description }}</p>
</div>

<div class="mt-2 text-center">
<a class="link link-chip" href="{{ project.repo.url }}">
<img class="link-img" src="https://jfenn.me/images/ic/git.png"/>
<span class="link-title">Git Repo</span>
</a>
<a class="link link-chip" href="{{ project.repo.url }}/issues">
<img class="link-img" src="https://jfenn.me/images/ic/bug.svg"/>
<span class="link-title">Bug Tracker</span>
</a>
{% if project.repo.websiteUrl %}
<a class="link link-chip" href="{{ project.repo.websiteUrl }}">
{% if project.repo.websiteUrl contains "play.google.com" %}
<img class="link-img" src="https://jfenn.me/images/ic/play-store.svg"/>
<span class="link-title">Google Play</span>
{% else %}
<i class="link-img material-icons">link</i>
<span class="link-title">Website</span>
{% endif %}
</a>
{% endif %}
</div>
</div>
<div class="bg-dark py-3">
<div class="container">
<div class="row pt-3">
{% if project.hasWiki %}
<div class="col col-12 col-md-6 mb-3">
<div class="card card-accent h-100" onclick="location.href = './wiki/';">
<a class="card-title" href="./wiki/">
<i class="material-icons">book</i>
Wiki
</a>
<div class="card-body">
<span>Find helpful information about this project - tutorials, guides, documentation, and more!</span>
</div>
</div>
</div>
{% endif %}
<div class="col col-12 col-md-6 mb-3">
<div class="card card-accent h-100" onclick="location.href = '/community/';">
<a class="card-title" href="/community/">
<i class="material-icons">people</i>
Contributing
</a>
<div class="card-body">
<span>Interested in working with this project or volunteering to help? Get started here!</span>
</div>
</div>
</div>
<div class="col col-12 col-md-6 mb-3">
<div class="card card-accent h-100" onclick="location.href = '/contact/';">
<a class="card-title" href="/contact/">
<i class="material-icons">email</i>
Contact Me
</a>
<div class="card-body">
<span>Have any questions or concerns? Don't hesitate to reach out! (prompt replies not guaranteed)</span>
</div>
</div>
</div>
</div>
</div>
</div>

<main class="container">
<div class="text">
{{ project.readme | markdownify }}
</div>
</main>
{% endfor %}

+ 1
- 0
pages/projects/wiki.html Целия файл

@@ -3,6 +3,7 @@ layout: base
pagination:
data: git.wikis
size: 1
addAllPagesToCollections: true
permalink: "projects/{{ pagination.items[0].id }}/wiki/{{ pagination.items[0].page }}.html"
---



+ 12
- 18
projects/attribouter.html Целия файл

@@ -4,11 +4,9 @@ tags: project-tool
---

<div class="row">
<div class="col-6 col-lg-3 order-lg-2 text text-right">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributors.png?raw=true">
</div>
<div class="col-6 col-lg-3 order-lg-3 text text-left">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributor.png?raw=true">
<div class="col-12 col-lg-6 order-lg-2 text text-center text-lg-right">
<img class="my-2 mr-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributors.png?raw=true">
<img class="my-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributor.png?raw=true">
</div>
<div class="col-12 col-lg-6 py-3 align-self-center text-center text-lg-left">
<h3>Contributor Profiles</h3>
@@ -16,14 +14,12 @@ tags: project-tool
</div>
</div>

<hr>
===

<div class="row">
<div class="col-6 col-lg-3 text text-right">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-licenses.png?raw=true">
</div>
<div class="col-6 col-lg-3 text text-left">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-license.png?raw=true">
<div class="col-12 col-lg-6 text text-center text-lg-left">
<img class="my-2 mr-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-licenses.png?raw=true">
<img class="my-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-license.png?raw=true">
</div>
<div class="col-12 col-lg-6 py-3 align-self-center text-center text-lg-left">
<h3>License Information</h3>
@@ -31,14 +27,12 @@ tags: project-tool
</div>
</div>

<hr>
===

<div class="row">
<div class="col-6 col-lg-3 order-lg-2 text text-right">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-night.png?raw=true">
</div>
<div class="col-6 col-lg-3 order-lg-3 text text-left">
<img class="mt-3 my-lg-3" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributors.png?raw=true">
<div class="col-12 col-lg-6 order-lg-2 text text-center text-lg-right">
<img class="my-2 mr-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-night.png?raw=true">
<img class="my-2" style="width: 200px;" src="https://github.com/fennifith/Attribouter/raw/main/.github/images/attribouter-contributors.png?raw=true">
</div>
<div class="col-12 col-lg-6 py-3 align-self-center text-center text-lg-left">
<h3>Night Theme</h3>
@@ -46,7 +40,7 @@ tags: project-tool
</div>
</div>

<hr>
===

<div class="row">
<div class="col-12 col-lg-3 text-center">


+ 9
- 4
projects/git-rest-wrapper.html Целия файл

@@ -9,17 +9,22 @@ tags: project-tool
<p class="mt-0">Written in Kotlin, the library has seamless compatibility with JavaScript, NodeJS, JVM, and Android platforms. </p>
</div>

<hr>
===

<div class="row">
<div class="col-12 col-lg-8 order-lg-2">
<pre><code>{
{% capture codeblock %}
```json
{
"id": "user",
"name": "User Human",
"url": "https://code.horrific.dev/user",
"avatarUrl": "https://example.com/photo.png",
"websiteUrl": "https://example.com"
}</code></pre>
}
```
{% endcapture %}
{{ codeblock | markdownify }}
</div>
<div class="col-12 col-lg-4 py-3 align-self-center text-center text-lg-left">
<h3>Consistent data representation</h3>
@@ -27,7 +32,7 @@ tags: project-tool
</div>
</div>

<hr>
===

<div class="row">
<div class="col-12 col-lg-4 order-lg-2 text-center">


+ 10
- 5
projects/ktordocs.html Целия файл

@@ -9,18 +9,23 @@ tags: project-tool
<p class="mt-0">Provide comprehensive API documentation with minimal effort!</p>
</div>

<hr>
===

<div class="row">
<div class="col-12 col-lg-8 order-lg-2">
<pre><code>get("/api/v1/example") {
{% capture codeblock %}
```kt
get("/api/v1/example") {
docs {
title = "Hello World"
desc = "Says hello to the world."
}

call.respondText("Hello world!")
}</code></pre>
}
```
{% endcapture %}
{{ codeblock | markdownify }}
</div>
<div class="col-12 col-lg-4 py-3 align-self-center text-center text-lg-left">
<h3>Minimal API</h3>
@@ -28,11 +33,11 @@ tags: project-tool
</div>
</div>

<hr>
===

<div class="row">
<div class="col-12 col-lg-4 order-lg-2 align-self-center text-center">
<img class="mt-3 m-lg-3" style="width: 150px;" src="/images/ic/markdown-mark.png">
<img class="mt-3 m-lg-3" style="width: 150px;" src="/images/ic/markdown-mark.svg">
</div>
<div class="col-12 col-lg-8 py-3 align-self-center text-center text-lg-left">
<h3>Markdown Support</h3>


+ 12
- 1
projects/metronome.html Целия файл

@@ -3,6 +3,17 @@ layout: layouts/project
tags: project-app
---

Hello
<h3>Tempo Slider</h3>
<p>Swipe in either direction to change the tempo, or press the arrows for a more precise adjustment.</p>

<h3>Emphasized Beats</h3>
<p>Use the +/- buttons to add or remove beats, then select them to add emphasis.</p>

<h3>Multiple Sounds</h3>
<p>Use the dropdown menu at the top of the screen to select a sound.</p>

<h3>Bookmarks</h3>
<p>Press the bookmark icon in the bottom right of the screen to save a tempo for easy access.</p>

<h3>Themes</h3>
<p>Change the theme of the application with the dropdown at the bottom of the about section.</p>

Зареждане…
Отказ
Запис