Migrate to simple Phoenix application.
|
@ -1,2 +0,0 @@
|
|||
---
|
||||
BUNDLE_FORCE_RUBY_PLATFORM: "true"
|
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
import_deps: [:phoenix],
|
||||
plugins: [Phoenix.LiveView.HTMLFormatter],
|
||||
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"]
|
||||
]
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
STAGED=$(
|
||||
git --no-pager diff --name-only --no-color --cached --diff-filter=d |
|
||||
# Remove quotations used to surrounding filenames with special characters.
|
||||
sed -e "s/^\"//" -e "s/\"$//g"
|
||||
)
|
||||
|
||||
MIX_TARGETS=()
|
||||
WEB_TARGETS=()
|
||||
while IFS= read -r FILENAME
|
||||
do
|
||||
if [[ "$FILENAME" =~ .*\.exs?$ ]]; then
|
||||
MIX_TARGETS+=("${FILENAME}")
|
||||
elif [[ "$FILENAME" =~ .*\.jsx?$ ]] || [[ "$FILENAME" =~ .*\.tsx?$ ]]; then
|
||||
WEB_TARGETS+=("${FILENAME}")
|
||||
fi
|
||||
done <<< "$STAGED"
|
||||
|
||||
if (( ${#MIX_TARGETS[@]} )); then
|
||||
mix format "${MIX_TARGETS[@]}"
|
||||
git add "${MIX_TARGETS[@]}"
|
||||
fi
|
||||
|
||||
if (( ${#WEB_TARGETS[@]} )); then
|
||||
prettier --write "${WEB_TARGETS[@]}"
|
||||
git add "${WEB_TARGETS[@]}"
|
||||
fi
|
|
@ -1,8 +1,42 @@
|
|||
# The directory Mix will write compiled artifacts to.
|
||||
/_build/
|
||||
|
||||
# If you run "mix test --cover", coverage assets end up here.
|
||||
/cover/
|
||||
|
||||
# The directory Mix downloads your dependencies sources to.
|
||||
/deps/
|
||||
|
||||
# Where 3rd-party dependencies like ExDoc output generated docs.
|
||||
/doc/
|
||||
|
||||
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||
/.fetch
|
||||
|
||||
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||
erl_crash.dump
|
||||
|
||||
# Also ignore archive artifacts (built via "mix archive.build").
|
||||
*.ez
|
||||
|
||||
# Temporary files, for example, from tests.
|
||||
/tmp/
|
||||
|
||||
# Ignore package tarball (built via "mix hex.build").
|
||||
portfolio-*.tar
|
||||
|
||||
# Ignore assets that are produced by build tools.
|
||||
/priv/static/assets/
|
||||
|
||||
# Ignore digested assets cache.
|
||||
/priv/static/cache_manifest.json
|
||||
|
||||
# In case you use Node.js/npm, you want to ignore these.
|
||||
npm-debug.log
|
||||
/assets/node_modules/
|
||||
|
||||
# Directory used by `direnv` to hold `use flake`-generated profiles.
|
||||
/.direnv/
|
||||
|
||||
# A symlink produced by default when running `nix build`.
|
||||
/result
|
||||
|
||||
# The jekyll-produced static bundle.
|
||||
_site/
|
||||
|
|
25
404.html
|
@ -1,25 +0,0 @@
|
|||
---
|
||||
permalink: /404.html
|
||||
layout: default
|
||||
---
|
||||
|
||||
<style type="text/css" media="screen">
|
||||
.container {
|
||||
margin: 10px auto;
|
||||
max-width: 600px;
|
||||
text-align: center;
|
||||
}
|
||||
h1 {
|
||||
margin: 30px 0;
|
||||
font-size: 4em;
|
||||
line-height: 1;
|
||||
letter-spacing: -1px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container">
|
||||
<h1>404</h1>
|
||||
|
||||
<p><strong>Page not found :(</strong></p>
|
||||
<p>The requested page could not be found.</p>
|
||||
</div>
|
14
Gemfile
|
@ -1,14 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "jekyll", "~> 4.3.2"
|
||||
gem "lagrange", "~> 4.0"
|
||||
|
||||
# If you have any plugins, put them here!
|
||||
group :jekyll_plugins do
|
||||
gem "jekyll-feed", "~> 0.12"
|
||||
gem "jekyll-seo-tag", "~> 2.8"
|
||||
gem "jekyll-sitemap", "~> 1.4"
|
||||
gem "jekyll-paginate-v2", "~> 3.0"
|
||||
end
|
92
Gemfile.lock
|
@ -1,92 +0,0 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
addressable (2.8.6)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.2.2)
|
||||
em-websocket (0.5.3)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0)
|
||||
eventmachine (1.2.7)
|
||||
ffi (1.16.3)
|
||||
forwardable-extended (2.6.0)
|
||||
google-protobuf (3.25.1)
|
||||
http_parser.rb (0.8.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jekyll (4.3.2)
|
||||
addressable (~> 2.4)
|
||||
colorator (~> 1.0)
|
||||
em-websocket (~> 0.5)
|
||||
i18n (~> 1.0)
|
||||
jekyll-sass-converter (>= 2.0, < 4.0)
|
||||
jekyll-watch (~> 2.0)
|
||||
kramdown (~> 2.3, >= 2.3.1)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
liquid (~> 4.0)
|
||||
mercenary (>= 0.3.6, < 0.5)
|
||||
pathutil (~> 0.9)
|
||||
rouge (>= 3.0, < 5.0)
|
||||
safe_yaml (~> 1.0)
|
||||
terminal-table (>= 1.8, < 4.0)
|
||||
webrick (~> 1.7)
|
||||
jekyll-feed (0.17.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-paginate (1.1.0)
|
||||
jekyll-paginate-v2 (3.0.0)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
jekyll-sass-converter (3.0.0)
|
||||
sass-embedded (~> 1.54)
|
||||
jekyll-seo-tag (2.8.0)
|
||||
jekyll (>= 3.8, < 5.0)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
lagrange (4.0.0)
|
||||
jekyll (~> 4.2)
|
||||
jekyll-feed (~> 0.6)
|
||||
jekyll-paginate (~> 1.1)
|
||||
jekyll-seo-tag (~> 2.6)
|
||||
jekyll-sitemap (~> 1.3)
|
||||
liquid (4.0.4)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.4.0)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (5.0.4)
|
||||
rake (13.1.0)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.6)
|
||||
rouge (4.2.0)
|
||||
safe_yaml (1.0.5)
|
||||
sass-embedded (1.69.5)
|
||||
google-protobuf (~> 3.23)
|
||||
rake (>= 13.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
unicode-display_width (2.5.0)
|
||||
webrick (1.8.1)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
jekyll (~> 4.3.2)
|
||||
jekyll-feed (~> 0.12)
|
||||
jekyll-paginate-v2 (~> 3.0)
|
||||
jekyll-seo-tag (~> 2.8)
|
||||
jekyll-sitemap (~> 1.4)
|
||||
lagrange (~> 4.0)
|
||||
|
||||
BUNDLED WITH
|
||||
2.4.22
|
102
README.md
|
@ -1,29 +1,95 @@
|
|||
# Jekyll Flake Template
|
||||
# Portfolio
|
||||
|
||||
This is a template for bootstrapping a [Jekyll](https://jekyllrb.com/)-based
|
||||
project (version 4.3.2) with the [lagrange](https://github.com/LeNPaul/Lagrange)
|
||||
theme (version 4.0). [direnv](https://direnv.net/) can be used to launch a dev
|
||||
shell upon entering this directory (refer to `.envrc`). Otherwise run via:
|
||||
This is my main personal website. It uses Elixir (version 1.15.7, Erlang/OTP
|
||||
25) and the [Phoenix](https://www.phoenixframework.org/) (version 1.7.10)
|
||||
framework. [direnv](https://direnv.net/) can be used to launch a dev shell upon
|
||||
entering this directory (refer to `.envrc`). Otherwise run via:
|
||||
```bash
|
||||
$ nix develop
|
||||
```
|
||||
Start the server by running:
|
||||
```
|
||||
$ jekyll serve [--watch]
|
||||
|
||||
## Quickstart
|
||||
|
||||
Run the Phoenix setup command and then start the local server:
|
||||
```bash
|
||||
$ mix deps.get
|
||||
$ mix assets.setup
|
||||
$ mix phx.server
|
||||
```
|
||||
|
||||
## Building
|
||||
## Blog
|
||||
|
||||
Dependencies are managed using [bundix](https://github.com/nix-community/bundix).
|
||||
If you make any changes to the `Gemfile`, run the following:
|
||||
Blog posts exist under the nested `blog_html/` directory. Markdown files are
|
||||
converted to HTML using pandoc (version 3.1.9). For example,
|
||||
```bash
|
||||
$ bundix -l
|
||||
$ cd lib/portfolio_web/controllers/blog_html
|
||||
$ pandoc \
|
||||
> --to=html \
|
||||
> --toc \
|
||||
> --template=template.html \
|
||||
> --output tagless_final_parsing.html.heex \
|
||||
> tagless_final_parsing.md
|
||||
```
|
||||
This will update the `Gemfile.lock` and `gemset.nix` files. Afterward you can
|
||||
run:
|
||||
|
||||
Styling is maintained within the `blog.css` file. This file is generated by
|
||||
copying the CSS made within a standalone invocation of `pandoc`. For example,
|
||||
```bash
|
||||
$ nix build
|
||||
$ pandoc --standalone --output output.html --highlight-style=zenburn
|
||||
```
|
||||
Note that we need the `.bundle/config` file to workaround issues bundix has with
|
||||
pre-built, platform-specific gems. Refer to
|
||||
[PR #68](https://github.com/nix-community/bundix/pull/68) for more details.
|
||||
|
||||
## Dependencies
|
||||
|
||||
### Backend
|
||||
|
||||
Mix dependencies are packaged using [mix2nix](https://github.com/ydlr/mix2nix).
|
||||
After updating your `mix.lock` file, make sure to re-run the following:
|
||||
```bash
|
||||
$ mix2nix > deps.nix
|
||||
```
|
||||
As of now, `mix2nix` cannot handle git dependencies found inside the `mix.lock`
|
||||
file. If you have git dependencies, add them manually or use
|
||||
[FODs](https://nixos.org/manual/nixpkgs/stable/#packaging-beam-applications).
|
||||
|
||||
### Frontend
|
||||
|
||||
Frontend dependencies (i.e. assets found in the `/assets` folder) are packaged
|
||||
using [node2nix](https://github.com/svanderburg/node2nix). You can generate the
|
||||
relevant nix files for import using the following sequence of commands:
|
||||
```bash
|
||||
$ cd assets
|
||||
$ rm -r node_modules # If this directory exists.
|
||||
$ node2nix -l
|
||||
```
|
||||
In the above, we must remove `node_modules` (if it exists). Otherwise the
|
||||
node packages will be included in the Nix build, influencing the outcome of
|
||||
`node2nix`. The above generates three files:
|
||||
|
||||
* `node-packages.nix`
|
||||
* Captures the packages that can be deployed (including all its required
|
||||
dependencies)
|
||||
* `node-env.nix`
|
||||
* Contains build logic
|
||||
* `default.nix`
|
||||
* A composition expression allowing users to deploy the package. For an
|
||||
example of this deployment, refer to `flake.nix`
|
||||
|
||||
NOTE: Do not update the lock version used in `assets`. `node2nix` currently only
|
||||
supports lock versions 1 and 2.
|
||||
|
||||
## Language Server
|
||||
|
||||
The [elixir-ls](https://github.com/elixir-lsp/elixir-ls) LSP (version 0.17.10)
|
||||
and [typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
|
||||
(version 4.1.2) is included in this flake.
|
||||
|
||||
## Formatting
|
||||
|
||||
Formatting depends on [prettier](https://prettier.io/) (version 3.1.0) and the
|
||||
`mix format` task. A `pre-commit` hook is included in `.githooks` that can be
|
||||
used to format all `*.exs?`, `*.jsx?`, and `*.tsx?` files prior to commit.
|
||||
Install via:
|
||||
```bash
|
||||
$ git config --local core.hooksPath .githooks/
|
||||
```
|
||||
If running [direnv](https://direnv.net/), this hook is installed automatically
|
||||
when entering the directory.
|
||||
|
|
66
_config.yml
|
@ -1,66 +0,0 @@
|
|||
# Welcome to Jekyll!
|
||||
#
|
||||
# This config file is meant for settings that affect your whole blog, values
|
||||
# which you are expected to set up once and rarely edit after that. If you find
|
||||
# yourself editing this file very often, consider using Jekyll's data files
|
||||
# feature for the data you need to update frequently.
|
||||
#
|
||||
# For technical reasons, this file is *NOT* reloaded automatically when you use
|
||||
# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
|
||||
#
|
||||
# If you need help with YAML syntax, here are some quick references for you:
|
||||
# https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml
|
||||
# https://learnxinyminutes.com/docs/yaml/
|
||||
#
|
||||
# Site settings
|
||||
# These are used to personalize your new site. If you look in the HTML files,
|
||||
# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
|
||||
# You can create any custom variable you would like, and they will be accessible
|
||||
# in the templates via {{ site.myvariable }}.
|
||||
|
||||
title: Joshua Potter
|
||||
description: My portfolio
|
||||
author: Joshua Potter
|
||||
github_username: jrpotter
|
||||
|
||||
theme: lagrange
|
||||
plugins:
|
||||
- jekyll-feed
|
||||
- jekyll-paginate-v2
|
||||
- jekyll-seo-tag
|
||||
- jekyll-sitemap
|
||||
|
||||
pagination:
|
||||
enabled: true
|
||||
per_page: 8
|
||||
permalink: '/page/:num/'
|
||||
limit: 0
|
||||
sort_field: 'date'
|
||||
sort_reverse: true
|
||||
|
||||
markdown: kramdown
|
||||
highlighter: route
|
||||
permalink: /:title
|
||||
|
||||
hide_post_share: true
|
||||
hide_related_posts: true
|
||||
|
||||
# Exclude from processing.
|
||||
# The following items will not be processed, by default.
|
||||
# Any item listed under the `exclude:` key here will be automatically added to
|
||||
# the internal "default list".
|
||||
#
|
||||
# Excluded items can be processed by explicitly listing the directories or
|
||||
# their entries' file path in the `include:` list.
|
||||
#
|
||||
# exclude:
|
||||
# - .sass-cache/
|
||||
# - .jekyll-cache/
|
||||
# - gemfiles/
|
||||
# - Gemfile
|
||||
# - Gemfile.lock
|
||||
# - node_modules/
|
||||
# - vendor/bundle/
|
||||
# - vendor/cache/
|
||||
# - vendor/gems/
|
||||
# - vendor/ruby/
|
|
@ -1,18 +0,0 @@
|
|||
menu:
|
||||
- name: "Home"
|
||||
- name: "Projects"
|
||||
url: "projects.html"
|
||||
- name: "Archive"
|
||||
url: "archive.html"
|
||||
|
||||
social:
|
||||
- icon: "github"
|
||||
link: "https://github.com/jrpotter"
|
||||
- icon: "rss-square"
|
||||
link: "https://blog.jrpotter.com"
|
||||
- icon: "book"
|
||||
link: "https://bookshelf.jrpotter.com"
|
||||
- icon: "linkedin"
|
||||
link: "https://www.linkedin.com/in/jrpotter2112/"
|
||||
- icon: "hdd-o"
|
||||
link: "https://www.zotero.org/jrpotter2112/library"
|
|
@ -1,4 +0,0 @@
|
|||
<footer class="footer">
|
||||
{% include social-icons.html %}
|
||||
<div class="footer-description"><a href="{{ site.github.url }}/">© 2023 {{ site.title }}</a></div>
|
||||
</footer>
|
|
@ -1,29 +0,0 @@
|
|||
<head>
|
||||
<title>Portfolio • Joshua Potter</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="{{ site.github.url }}/assets/css/main.css">
|
||||
<link rel="stylesheet" href="{{ site.github.url }}/assets/css/syntax.css">
|
||||
<!-- Use Atom -->
|
||||
{% feed_meta %}
|
||||
<!-- Use RSS-2.0 -->
|
||||
<!--<link href="{{ site.github.url }}/rss-feed.xml" type="application/rss+xml" rel="alternate" title="{{ site.title }} | {{ site.description }}"/>
|
||||
//-->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700%7CPT+Sans:400">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Quattrocento+Sans">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<script type="text/javascript" async
|
||||
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML">
|
||||
MathJax.Hub.Config({
|
||||
tex2jax: {
|
||||
inlineMath: [['$', '$'], ['\\(', '\\)']]
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% if jekyll.environment == "production" %}
|
||||
<!-- Analytics -->
|
||||
{% endif %}
|
||||
<!-- Use Jekyll SEO plugin -->
|
||||
{% seo %}
|
||||
</head>
|
|
@ -1,32 +0,0 @@
|
|||
{% if paginator.total_pages > 1 %}
|
||||
<nav aria-label="Page Navigation">
|
||||
<ul class="pagination">
|
||||
<!-- left arrow -->
|
||||
{% if paginator.previous_page %}
|
||||
{% assign prev_url = paginator.previous_page_path | prepend: site.baseurl %}
|
||||
{% else %}
|
||||
{% assign prev_url = '' %}
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item {% unless paginator.previous_page %}disabled{% endunless %}">
|
||||
<a class="page-link" href="{{ prev_url }}" aria-label="previous-page">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<!-- right arrow -->
|
||||
{% if paginator.next_page_path %}
|
||||
{% assign next_url = paginator.next_page_path | prepend: site.baseurl %}
|
||||
{% else %}
|
||||
{% assign next_url = '#' %}
|
||||
{% endif %}
|
||||
|
||||
<li class="page-item {% unless paginator.next_page_path %}disabled{% endunless %}">
|
||||
<a class="page-link" href="{{ next_url }}" aria-label="next-page">
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<!-- .pagination -->
|
||||
{% endif %}
|
|
@ -1,28 +0,0 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<ul class="posts-container">
|
||||
{% for post in site.posts %}
|
||||
{% unless post.next %}
|
||||
<h3>{{ post.date | date: '%Y' }}</h3>
|
||||
{% else %}
|
||||
{% capture year %}{{ post.date | date: '%Y' }}{% endcapture %}
|
||||
{% capture nyear %}{{ post.next.date | date: '%Y' }}{% endcapture %}
|
||||
{% if year != nyear %}
|
||||
<hr />
|
||||
<h3>{{ post.date | date: '%Y' }}</h3>
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
<li itemscope>
|
||||
<div class="post-tags">
|
||||
<a href="{{ site.github.url }}{{ post.url }}">{{ post.title }}</a>
|
||||
{% for tag in post.tags %}
|
||||
<div class="{{ tag }}">{{ tag }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<p>{{ post.content | strip_html }}</p>
|
||||
<p class="post-date"><span><i class="fa fa-calendar" aria-hidden="true"></i> {{ post.date | date: "%B %-d" }}</span></p>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{% if paginator.page_path contains "index" %}
|
||||
<p class="home-description">
|
||||
Most applications listed below are served from <a href="https://nixos.org/">NixOS</a>
|
||||
machines hosted on <a href="https://www.digitalocean.com/">Digital Ocean</a>.
|
||||
Configuration files for each of my machines can be found <a href="https://git.jrpotter.com/r/nixos-configuration">here</a>.
|
||||
If interested in starting a similar hosting solution, consider getting a $200
|
||||
credit using my <a href="https://m.do.co/c/c65b89434c1b">referral link</a>.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
{% for post in paginator.posts %}
|
||||
<div class="posts-container">
|
||||
<h1>
|
||||
<a href="{{ post.href }}">{{ post.title }}</a>
|
||||
</h1>
|
||||
{% if post.image %}
|
||||
<div class="thumbnail-container">
|
||||
<a href="{{ post.href }}">
|
||||
<img src="{{ site.github.url }}/assets/img/{{ post.image }}">
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<p>
|
||||
<div class="post-tags">
|
||||
{% for tag in post.tags %}
|
||||
<div class="{{ tag }}">{{ tag }}</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<p>{{ post.content }}</p>
|
||||
<span class="post-date">
|
||||
{% if post.href %}
|
||||
<a href="{{ post.href }}">{{ post.href }}</a> -
|
||||
{% endif %}
|
||||
<i class="fa fa-calendar" aria-hidden="true"></i>
|
||||
{{ post.date | date_to_string }}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
{% include post-paginator.html %}
|
|
@ -1,33 +0,0 @@
|
|||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
<h1>
|
||||
{% if page.href %}
|
||||
<a href="{{ page.href }}">{{ page.title }}</a>
|
||||
{% else %}
|
||||
{{ page.title }}
|
||||
{% endif %}
|
||||
</h1>
|
||||
{% if page.image %}
|
||||
<div class="page-image-container">
|
||||
<a href="{{ page.href }}">
|
||||
<img src="{{ site.github.url }}/assets/img/{{ page.image }}">
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
<article>
|
||||
{{ content }}
|
||||
</article>
|
||||
{% if site.hide_post_date != true %}
|
||||
{% include post-date.html %}
|
||||
{% endif %}
|
||||
{% if site.hide_post_share != true %}
|
||||
{% include social-sharing.html %}
|
||||
{% endif %}
|
||||
{% if site.hide_related_posts != true %}
|
||||
{% include related-posts.html %}
|
||||
{% endif %}
|
||||
{% if site.data.settings.disqus.comments %}
|
||||
{% include disqus.html %}
|
||||
{% endif %}
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Mini Java
|
||||
categories: project
|
||||
tags: [compiler, java]
|
||||
href: "https://git.jrpotter.com/r/mini-java"
|
||||
image: java.png
|
||||
---
|
||||
|
||||
A Java implemention of a subset of Java. Generates code that targets mJAM, an
|
||||
abstract machine included in the source that supports running `miniJava`. In
|
||||
particular, this implementation supports various primitives, array types, and,
|
||||
to a certain degree, classes.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Fifth
|
||||
categories: project
|
||||
tags: [cellular-automata, python]
|
||||
href: "https://git.jrpotter.com/r/fifth"
|
||||
image: conway-gol.jpg
|
||||
---
|
||||
|
||||
A library for parsing various rulesets for cellular automata machines (CAMs).
|
||||
The parsed CAM is displayed using [matplotlib](https://matplotlib.org). For
|
||||
instance, this library parses ruleset `B3/S23` and then produces a running
|
||||
visualization of Conway's Game of Life.
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Pong
|
||||
categories: project
|
||||
tags: [fpga, mips-assembly, verilog]
|
||||
href: "https://git.jrpotter.com/r/pong"
|
||||
image: pong.jpg
|
||||
---
|
||||
|
||||
An implementation of the classic pong video game, written from scratch on an
|
||||
Artix FPGA using System Verilog. This works on a custom ALU intended to process
|
||||
an arbitrary MIPS program with modified memory configuration: `.text 0x0000`
|
||||
and `.data 0x2000`. A memory mapped IO scheme is used to draw to the monitor and
|
||||
interact with the keyboard.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Highlight Plugin
|
||||
categories: project
|
||||
tags: [vim]
|
||||
href: "https://git.jrpotter.com/r/vim-highlight"
|
||||
image: vim.png
|
||||
---
|
||||
|
||||
A small Vim plugin that maintains a custom registry for manipulating highlights.
|
||||
This registry allows highlighting different keywords without overriding previous
|
||||
searches. Includes a small snippet for including the active highlight from
|
||||
within the statusline.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Join Plugin
|
||||
categories: project
|
||||
tags: [vim]
|
||||
href: "https://git.jrpotter.com/r/vim-join"
|
||||
image: vim.png
|
||||
---
|
||||
|
||||
A small Vim plugin that joins a number of lines together and then breaks them
|
||||
again with respect to the `textwidth` parameter. This enables re-flowing a set
|
||||
of lines similar in manner to `fold` or `fmt`.
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bill Gates and Honey
|
||||
categories: other
|
||||
tags: [podcast]
|
||||
href: "https://open.spotify.com/episode/2CaNBdpgZofhXDGCs2QsPW"
|
||||
image: would-you-blabber.png
|
||||
---
|
||||
|
||||
In our first episode of Would You Blabber, we discuss honey, truck drivers, and
|
||||
hurting those more fortunate than us.
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bubbles and Funny Bones
|
||||
categories: other
|
||||
tags: [podcast]
|
||||
href: "https://open.spotify.com/episode/0MeLBj9jw3lPXBxRKevODo"
|
||||
image: would-you-blabber.png
|
||||
---
|
||||
|
||||
In this episode of Would You Blabber, we discuss bubble boys and precognition.
|
|
@ -1,10 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bananas, Buildings, and Batman
|
||||
categories: other
|
||||
tags: [podcast]
|
||||
href: "https://open.spotify.com/episode/3XrpanmTQiZhXjYqLP3dBd"
|
||||
image: would-you-blabber.png
|
||||
---
|
||||
|
||||
Bananas, buildings, and Batman!
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Huh, Huh, and Huh ft. Kenny Yi
|
||||
categories: other
|
||||
tags: [podcast]
|
||||
href: "https://open.spotify.com/episode/44oNp0ctwyk590298xWHwA"
|
||||
image: would-you-blabber.png
|
||||
---
|
||||
|
||||
In this episode of Would You Blabber, we explore the world of glogging, huh-ing,
|
||||
and old soft-serve ice cream.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Postlude
|
||||
categories: project
|
||||
tags: [haskell]
|
||||
href: "https://git.jrpotter.com/r/postlude"
|
||||
image: haskell.png
|
||||
---
|
||||
|
||||
An example of a custom-rolled [Prelude](https://hackage.haskell.org/package/base-4.19.0.0/docs/Prelude.html).
|
||||
Serves as a fairly comprehensive list of imports I found relevant across the
|
||||
various Haskell projects I worked on as well as a demonstration on how
|
||||
forwarding imports with Haskell works.
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Looped
|
||||
categories: home
|
||||
tags: [python, swift, kotlin, vue]
|
||||
image: looped.png
|
||||
---
|
||||
|
||||
VP of engineering at Looped, the "Ultimate Virtual Venue". Featured on
|
||||
[Forbes](https://www.forbes.com/sites/ericfuller/2021/01/06/loopedthe-app-helping-fans-mingle-and-meet-artists-personally-during-live-streamed-events)
|
||||
and [TechCrunch](https://techcrunch.com/2021/03/02/looped-raises-7-7m-to-expand-its-interactive-live-event-platform).
|
||||
Led development on the Kotlin-based [Android app](https://play.google.com/store/apps/details?id=com.vipvr.android)
|
||||
(50K+ downloads, 4.5 star review), the Swift-based iOS app (100K+ downloads,
|
||||
4.8 star review), the Vue-based web app, and the Django-based backend.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Blog
|
||||
categories: home
|
||||
tags: [jekyll, nix, ruby]
|
||||
href: "https://blog.jrpotter.com"
|
||||
image: jekyll.png
|
||||
---
|
||||
|
||||
I occasionally write about (usually) technical concepts in my blog. Originally
|
||||
powered by Github Pages, I've since moved the [Jekyll](https://jekyllrb.com/)-based
|
||||
project to a self-hosting solution. Theming is provided by
|
||||
[Chirpy](https://github.com/cotes2020/jekyll-theme-chirpy).
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Homesync
|
||||
categories: project
|
||||
tags: [git, nix, rust]
|
||||
href: "https://git.jrpotter.com/r/homesync"
|
||||
image: git-branches.png
|
||||
---
|
||||
|
||||
An experimental Rust-based project for automatically syncing files across your
|
||||
desktop to a git repository. Allows upstream and downstream syncing with a
|
||||
single command, without any need to copy files manually to and from a git
|
||||
repository. Separately, a daemon can be spawned that watches files for changes
|
||||
and pushes/pulls them as they happen.
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Anki Synonyms
|
||||
categories: project
|
||||
tags: [anki, python]
|
||||
href: "https://git.jrpotter.com/r/anki-synonyms"
|
||||
image: anki.png
|
||||
---
|
||||
|
||||
An [Anki](https://apps.ankiweb.net/) plugin for specifying synonyms within
|
||||
flashcard question and answer prompts.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bookshelf
|
||||
categories: home
|
||||
tags: [latex, lean, nix]
|
||||
href: "https://bookshelf.jrpotter.com"
|
||||
image: lean.svg
|
||||
---
|
||||
|
||||
A collection of books I am actively studying. Usually mathematics or
|
||||
computer-science based, I aim to prove concepts as I encounter them using the
|
||||
[Lean](https://lean-lang.org/) interactive theorem prover. All proofs are also
|
||||
available in [LaTeX](https://www.latex-project.org/).
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: We're the Crew
|
||||
categories: other
|
||||
tags: [music]
|
||||
href: "https://gusvieweg.bandcamp.com/track/were-the-crew"
|
||||
image: smash-rap.jpg
|
||||
---
|
||||
|
||||
A Smash Bros. Ultimate rap made in collaboration with my friend
|
||||
[Gus](https://www.gusvieweg.com/) and fiancée Brittany.
|
||||
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bootstrap
|
||||
categories: project
|
||||
tags: [c, nix]
|
||||
href: "https://git.jrpotter.com/r/bootstrap"
|
||||
image: shoelaces.jpg
|
||||
---
|
||||
|
||||
A C-based CLI for initializing projects in a flexible but deterministic way.
|
||||
Originally motivated to serve as a better alternative to [Nix flake templates](https://github.com/NixOS/templates),
|
||||
`bootstrap` allows you to provide different parameters to custom initialization
|
||||
scripts akin to `npm init`, `django-admin startproject`, etc.
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: BoardWise
|
||||
categories: home
|
||||
tags: [elixir, react, nix]
|
||||
href: "https://boardwise.gg"
|
||||
image: boardwise.svg
|
||||
---
|
||||
|
||||
A [Phoenix](https://www.phoenixframework.org/)- and
|
||||
[React](https://react.dev/)-based project that provides an interface for finding
|
||||
chess coaches. This serves as an alternative to those found on
|
||||
[Lichess](https://lichess.org/coach) and [Chess.com](https://www.chess.com/coaches).
|
||||
Based on the [Tailwind Studio](https://tailwindui.com/templates/studio) theme.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: NixOS Configuration
|
||||
categories: project
|
||||
tags: [lua, nix]
|
||||
href: "https://git.jrpotter.com/r/nixos-configuration"
|
||||
image: nix.png
|
||||
---
|
||||
|
||||
The [nix](https://nixos.org) configuration files used to declaratively describe
|
||||
my local and remote machines. The site you are on now is declared within this
|
||||
project!
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Bookshelf Doc Generator
|
||||
categories: project
|
||||
tags: [latex, lean]
|
||||
href: "https://git.jrpotter.com/r/bookshelf-doc"
|
||||
image: lean.svg
|
||||
---
|
||||
|
||||
A fork of [doc-gen4](https://github.com/leanprover/doc-gen4) tightly coupled to
|
||||
my [bookshelf](https://git.jrpotter.com/r/bookshelf) project. This augments the
|
||||
`:docs` facet to convert LaTeX files into PDFs and then list them in the
|
||||
generated navbar.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Forgejo
|
||||
categories: home
|
||||
tags: [git, nix]
|
||||
href: "https://git.jrpotter.com"
|
||||
image: forgejo.svg
|
||||
---
|
||||
|
||||
A self-hosted [forgejo](https://forgejo.org/) instance. For the most part, my
|
||||
[GitHub](https://github.com) repositories are a mirror of those found here.
|
||||
There do exist a few repos though that live exclusively on either site.
|
|
@ -1,12 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Sketchbook Shuffle
|
||||
categories: other
|
||||
tags: [art]
|
||||
href: "https://www.twobeeindustries.com/playing-card-instructions"
|
||||
image: joker-card.png
|
||||
---
|
||||
|
||||
My contribution to a collective art project in which different members of the
|
||||
community choose a playing card to design. I designed the red joker. Once all
|
||||
cards are submitted, a deck will be printed for purchase.
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Notebook
|
||||
categories: home
|
||||
tags: [nix, quartz]
|
||||
href: "https://notebook.jrpotter.com"
|
||||
image: quartz.png
|
||||
---
|
||||
|
||||
A static site generated with [Quartz](https://quartz.jzhao.xyz/). Contains a
|
||||
collection of my transcribed notes, primarily Markdown managed using
|
||||
[Obsidian](https://obsidian.md/). Hidden are a collection of
|
||||
[Anki](https://apps.ankiweb.net/) flashcards.
|
|
@ -1,15 +0,0 @@
|
|||
---
|
||||
layout: post
|
||||
title: Hide and Seek
|
||||
categories: home
|
||||
tags: [elixir, phoenix, react]
|
||||
href: "https://hideandseek.live"
|
||||
image: hide-and-seek.png
|
||||
---
|
||||
|
||||
Realtime hide-and-seek application for the town of Fort Collins, built using
|
||||
[Phoenix](https://www.phoenixframework.org/) and [React](https://react.dev/).
|
||||
Group up with friends, designate a hider, and allow the rest of the group to
|
||||
find the hider in a city-wide search. Use various clues to narrow down the
|
||||
search space at the cost of potentially giving the hider means of thwarting the
|
||||
search.
|
|
@ -1,6 +0,0 @@
|
|||
@import "base",
|
||||
"code",
|
||||
"default",
|
||||
"home",
|
||||
"post",
|
||||
"social-icons"
|
|
@ -1,33 +0,0 @@
|
|||
.home-description, .posts-container {
|
||||
padding-bottom: 25px;
|
||||
}
|
||||
|
||||
.thumbnail-container {
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 220px;
|
||||
}
|
||||
}
|
||||
|
||||
ul.pagination {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
justify-content: center;
|
||||
|
||||
li.disabled {
|
||||
opacity: 0.5;
|
||||
|
||||
.page-link i {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
|
||||
.page-link i {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
.page-image-container {
|
||||
text-align: center;
|
||||
|
||||
img {
|
||||
width: auto;
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-tags {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
|
||||
div {
|
||||
background: #e0e0e0;
|
||||
border-radius: 999px;
|
||||
padding: 2px 8px;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.post-date {
|
||||
display: block;
|
||||
margin-top: 3px;
|
||||
margin-bottom: 1rem;
|
||||
color: $light-gray-color;
|
||||
font-family: $sans-serif-font-family;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
@media (max-width: $elements-responsive-width) {
|
||||
.posts h1 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.related {
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.related-posts {
|
||||
padding-left: 0px;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.related-posts a {
|
||||
text-decoration: none;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
Social media icons
|
||||
*/
|
||||
|
||||
.social-icons a, .sharing-icons a {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
@mixin social-media-icon($color, $transition){
|
||||
-webkit-transition: $transition;
|
||||
-o-transition: $transition;
|
||||
-ms-transition: $transition;
|
||||
-moz-transition: $transition;
|
||||
transition: $transition;
|
||||
&:hover{
|
||||
color: $color;
|
||||
}
|
||||
}
|
||||
|
||||
.sharing-icons {
|
||||
.fa-envelope {
|
||||
padding: 5px;
|
||||
@include social-media-icon($envelope-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-twitter {
|
||||
padding: 5px;
|
||||
@include social-media-icon($twitter-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-instagram {
|
||||
padding: 5px;
|
||||
@include social-media-icon($instagram-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-github {
|
||||
padding: 5px;
|
||||
@include social-media-icon($github-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-linkedin {
|
||||
padding: 5px;
|
||||
@include social-media-icon($linkedin-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-facebook {
|
||||
padding: 5px;
|
||||
@include social-media-icon($facebook-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-pinterest {
|
||||
padding: 5px;
|
||||
@include social-media-icon($pinterest-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-medium {
|
||||
padding: 5px;
|
||||
@include social-media-icon($medium-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-codepen {
|
||||
padding: 5px;
|
||||
@include social-media-icon($codepen-color, $icon-transition-time);
|
||||
}
|
||||
|
||||
.fa-rss-square {
|
||||
padding: 5px;
|
||||
@include social-media-icon($rss-color, $icon-transition-time);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
/* Links */
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
text-decoration: underline;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
/* Table of contents */
|
||||
|
||||
#TOC li {
|
||||
padding-top: 0.5rem;
|
||||
}
|
||||
|
||||
#TOC .h3 {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
#TOC .h4 {
|
||||
margin-left: 2rem;
|
||||
}
|
||||
|
||||
/* Headers */
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
padding: 0.5rem 0;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
h1 {
|
||||
border-bottom: 1px dashed white;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
h2, h3, h4 {
|
||||
border-bottom: 1px dotted white;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.75rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
|
||||
/* Figures */
|
||||
|
||||
figure {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
figure img {
|
||||
margin: 0 auto;
|
||||
max-width: 768px;
|
||||
}
|
||||
|
||||
/* Footnote */
|
||||
|
||||
#footnotes {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
#footnotes ol {
|
||||
padding-top: 1rem;
|
||||
padding-left: 1rem;
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
/* Syntax highlighting */
|
||||
|
||||
code {
|
||||
font-family: Menlo, Monaco, 'Lucida Console', Consolas, monospace;
|
||||
font-size: 85%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
border-left: 1px solid gray;
|
||||
padding-left: 1rem;
|
||||
margin: 1em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
padding: 0;
|
||||
overflow: visible;
|
||||
overflow-wrap: normal;
|
||||
}
|
||||
|
||||
.sourceCode {
|
||||
background-color: transparent;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
code span.al { color: #ffcfaf; } /* Alert */
|
||||
code span.an { color: #7f9f7f; font-weight: bold; } /* Annotation */
|
||||
code span.at { } /* Attribute */
|
||||
code span.bn { color: #dca3a3; } /* BaseN */
|
||||
code span.bu { } /* BuiltIn */
|
||||
code span.cf { color: #f0dfaf; } /* ControlFlow */
|
||||
code span.ch { color: #dca3a3; } /* Char */
|
||||
code span.cn { color: #dca3a3; font-weight: bold; } /* Constant */
|
||||
code span.co { color: #7f9f7f; } /* Comment */
|
||||
code span.cv { color: #7f9f7f; font-weight: bold; } /* CommentVar */
|
||||
code span.do { color: #7f9f7f; } /* Documentation */
|
||||
code span.dt { color: #dfdfbf; } /* DataType */
|
||||
code span.dv { color: #dcdccc; } /* DecVal */
|
||||
code span.er { color: #c3bf9f; } /* Error */
|
||||
code span.ex { } /* Extension */
|
||||
code span.fl { color: #c0bed1; } /* Float */
|
||||
code span.fu { color: #efef8f; } /* Function */
|
||||
code span.im { } /* Import */
|
||||
code span.in { color: #7f9f7f; font-weight: bold; } /* Information */
|
||||
code span.kw { color: #f0dfaf; } /* Keyword */
|
||||
code span.op { color: #f0efd0; } /* Operator */
|
||||
code span.ot { color: #efef8f; } /* Other */
|
||||
code span.pp { color: #ffcfaf; font-weight: bold; } /* Preprocessor */
|
||||
code span.sc { color: #dca3a3; } /* SpecialChar */
|
||||
code span.ss { color: #cc9393; } /* SpecialString */
|
||||
code span.st { color: #cc9393; } /* String */
|
||||
code span.va { } /* Variable */
|
||||
code span.vs { color: #cc9393; } /* VerbatimString */
|
||||
code span.wa { color: #7f9f7f; font-weight: bold; } /* Warning */
|
|
@ -0,0 +1,17 @@
|
|||
# This file has been generated by node2nix 1.11.1. Do not edit!
|
||||
|
||||
{pkgs ? import <nixpkgs> {
|
||||
inherit system;
|
||||
}, system ? builtins.currentSystem, nodejs ? pkgs."nodejs_14"}:
|
||||
|
||||
let
|
||||
nodeEnv = import ./node-env.nix {
|
||||
inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript;
|
||||
inherit pkgs nodejs;
|
||||
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
|
||||
};
|
||||
in
|
||||
import ./node-packages.nix {
|
||||
inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit;
|
||||
inherit nodeEnv;
|
||||
}
|
Before Width: | Height: | Size: 29 KiB |
|
@ -1,5 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 25 25" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M 12.5 0 H 20 Q 25 0, 25 5 V 12.5 H 12.5 Z" fill="rgb(10 10 10)"></path>
|
||||
<path d="M 0 20 Q 0 25, 5 25 H 12.5 V 12.5 H 0 Z" fill="rgb(10 10 10)"></path>
|
||||
</svg>
|
Before Width: | Height: | Size: 272 B |
Before Width: | Height: | Size: 194 KiB |
|
@ -1,40 +0,0 @@
|
|||
<svg viewBox="0 0 212 212" xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
>
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="https://codeberg.org/forgejo/governance/src/branch/main/branding#logo">
|
||||
<dc:title>Forgejo logo</dc:title>
|
||||
<cc:creator rdf:resource="https://caesarschinas.com/"><cc:attributionName>Caesar Schinas</cc:attributionName></cc:creator>
|
||||
<cc:license rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<style type="text/css">
|
||||
circle {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-width: 15;
|
||||
}
|
||||
path {
|
||||
fill: none;
|
||||
stroke: #000;
|
||||
stroke-width: 25;
|
||||
}
|
||||
.orange {
|
||||
stroke:#ff6600;
|
||||
}
|
||||
.red {
|
||||
stroke:#d40000;
|
||||
}
|
||||
</style>
|
||||
<g transform="translate(6,6)">
|
||||
<path d="M58 168 v-98 a50 50 0 0 1 50-50 h20" class="orange" />
|
||||
<path d="M58 168 v-30 a50 50 0 0 1 50-50 h20" class="red" />
|
||||
<circle cx="142" cy="20" r="18" class="orange" />
|
||||
<circle cx="142" cy="88" r="18" class="red" />
|
||||
<circle cx="58" cy="180" r="18" class="red" />
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 299 KiB |
|
@ -1,314 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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="300"
|
||||
height="150"
|
||||
viewBox="0 0 240 120"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="1.0.2 (e86c870879, 2021-01-15)"
|
||||
sodipodi:docname="lean_logo.svg">
|
||||
<metadata
|
||||
id="metadata113">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1418"
|
||||
id="namedview111"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="223.20569"
|
||||
inkscape:cy="58.300704"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="surface1"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<sodipodi:guide
|
||||
position="70.622896,28.982703"
|
||||
orientation="0,-1"
|
||||
id="guide193" />
|
||||
<sodipodi:guide
|
||||
position="55.91963,99.309873"
|
||||
orientation="0,-1"
|
||||
id="guide205" />
|
||||
<sodipodi:guide
|
||||
position="63.7,64.3"
|
||||
orientation="0,-1"
|
||||
id="guide207" />
|
||||
<sodipodi:guide
|
||||
position="57.515625,28.982703"
|
||||
orientation="0,-1"
|
||||
id="guide209" />
|
||||
<sodipodi:guide
|
||||
position="57.403125,27.453125"
|
||||
orientation="0,-1"
|
||||
id="guide211" />
|
||||
<sodipodi:guide
|
||||
position="9.834375,27.071875"
|
||||
orientation="1,0"
|
||||
id="guide213" />
|
||||
<sodipodi:guide
|
||||
position="11.771875,28.396875"
|
||||
orientation="1,0"
|
||||
id="guide215" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<g
|
||||
id="g6">
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph0-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m -5.140625,0 -180.499995,0 0,-262.4375 180.499995,0 z M -178.125,-250.15625 l 0,237.09375 79.171875,-118.75 z m 5.14063,243.03125 154.781245,0 -77.1875,-117.5625 z m 77.593745,-131.8125 77.1875,-116.375 -154.781245,0 z m 3.5625,7.125 79.15625,118.75 0,-237.09375 z"
|
||||
id="path9"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph0-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m -24.9375,-135.375 -143.29687,0 0,-6.32812 143.29687,0 0,-129.04688 -146.45312,0 0,-5.9375 152.781245,0 0,276.6875 -153.578125,0 0,-5.9375 147.25,0 z"
|
||||
id="path12"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph1-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.140625,0 180.499995,0 0,-262.4375 -180.499995,0 z M 178.125,-250.15625 l 0,237.09375 -79.171875,-118.75 z m -5.14063,243.03125 -154.781245,0 77.1875,-117.5625 z m -77.593745,-131.8125 -77.1875,-116.375 154.781245,0 z m -3.5625,7.125 -79.15625,118.75 0,-237.09375 z"
|
||||
id="path15"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph1-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 24.9375,0 0,-264.40625 L 207.8125,0 l 6.32812,0 0,-277.07812 -5.9375,0 0,265.999995 -184.062495,-265.999995 -5.53125,-0.39063 0,277.46875 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph1-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 24.9375,-276.6875 -6.328125,0 0,276.6875 C 70.453125,0 121.92188,0 173.76562,0 l 0,-6.328125 -148.82812,0 z"
|
||||
id="path21"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-0"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 1.21875,0 42.5,0 0,-61.796875 -42.5,0 z m 40.734375,-58.921875 0,55.84375 -18.640625,-27.96875 z m -1.21875,57.25 -36.453125,0 18.1875,-27.6875 z M 22.46875,-32.71875 4.28125,-60.125 l 36.453125,0 z m -0.84375,1.671875 -18.640625,27.96875 0,-55.84375 z"
|
||||
id="path24"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-1"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 24.796875,0.28125 0,-64.046875 22.5625,0 0,-1.484375 -46.515625,0 0,1.484375 22.546875,0 0,64.046875 z"
|
||||
id="path27"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-2"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.78125,-65.15625 -1.40625,0 0,65.15625 1.40625,0 0,-32.34375 40.921875,0 0,32.34375 1.484375,0 0,-65.15625 -1.484375,0 0,31.40625 -40.921875,0 z"
|
||||
id="path30"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-3"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.875,-31.875 33.75,0 0,-1.5 -33.75,0 0,-30.390625 34.484375,0 0,-1.390625 -35.984375,0 0,65.15625 36.171875,0 0,-1.390625 -34.671875,0 z"
|
||||
id="path33"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-4"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 67.765625,-32.625 c 0,8.859375 -3.53125,16.78125 -9.21875,22.5625 -5.78125,5.875 -13.796875,9.5 -22.5625,9.5 -8.765625,0 -16.6875,-3.625 -22.46875,-9.5 C 7.828125,-15.84375 4.1875,-23.765625 4.1875,-32.625 c 0,-8.859375 3.640625,-16.78125 9.328125,-22.5625 5.78125,-5.875 13.703125,-9.5 22.46875,-9.5 8.765625,0 16.78125,3.625 22.5625,9.5 5.6875,5.78125 9.21875,13.703125 9.21875,22.5625 z m -65.0625,0 c 0,9.234375 3.828125,17.609375 9.78125,23.671875 5.96875,6.15625 14.359375,9.890625 23.5,9.890625 9.234375,0 17.515625,-3.734375 23.578125,-9.890625 5.96875,-6.0625 9.796875,-14.4375 9.796875,-23.671875 0,-9.234375 -3.828125,-17.625 -9.796875,-23.671875 C 53.5,-62.453125 45.21875,-66.1875 35.984375,-66.1875 c -9.140625,0 -17.53125,3.734375 -23.5,9.890625 C 6.53125,-50.25 2.703125,-41.859375 2.703125,-32.625 z"
|
||||
id="path36"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-5"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.78125,-63.765625 21.15625,0 c 24.234375,0 24.234375,35.234375 0,35.234375 l -12.671875,0 0,1.40625 L 44.28125,0 46.421875,0 16.40625,-27.125 l 10.53125,0 c 26.109375,0 26.109375,-38.125 0,-38.125 l -22.5625,0 0,65.25 1.40625,0 z"
|
||||
id="path39"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-6"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.78125,-63.109375 26.5625,39.53125 1.21875,0 26.5625,-39.53125 0,63.109375 1.40625,0 0,-65.25 -1.5,0 -27.125,39.984375 L 5.875,-65.25 l -1.5,0 0,65.25 1.40625,0 z"
|
||||
id="path42"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-7"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d=""
|
||||
id="path45"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-8"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 4.375,-64.5 c 0,21.53125 0,42.96875 0,64.5 l 1.5,0 0,-24.796875 21.0625,0 c 26.109375,0 26.109375,-40.453125 0,-40.453125 l -22.5625,0 z m 1.5,38.3125 0,-37.578125 21.0625,0 c 24.234375,0 24.234375,37.578125 0,37.578125 z"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-9"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.78125,-63.765625 21.15625,0 c 24.234375,0 24.234375,35.234375 0,35.234375 l -12.671875,0 0,1.40625 L 44.28125,0 46.421875,0 16.40625,-27.125 l 10.53125,0 c 26.109375,0 26.109375,-38.125 0,-38.125 l -22.5625,0 0,65.25 1.40625,0 z"
|
||||
id="path51"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-10"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 67.03125,-32.625 c 0,8.859375 -3.546875,16.78125 -9.234375,22.5625 -5.78125,5.875 -13.796875,9.5 -22.5625,9.5 -8.765625,0 -16.6875,-3.625 -22.46875,-9.5 -5.6875,-5.78125 -9.3125,-13.703125 -9.3125,-22.5625 0,-8.859375 3.625,-16.78125 9.3125,-22.5625 5.78125,-5.875 13.703125,-9.5 22.46875,-9.5 8.765625,0 16.78125,3.625 22.5625,9.5 5.6875,5.78125 9.234375,13.703125 9.234375,22.5625 z m -65.078125,0 c 0,9.234375 3.828125,17.609375 9.796875,23.671875 5.96875,6.15625 14.34375,9.890625 23.484375,9.890625 9.234375,0 17.53125,-3.734375 23.59375,-9.890625 5.953125,-6.0625 9.78125,-14.4375 9.78125,-23.671875 0,-9.234375 -3.828125,-17.625 -9.78125,-23.671875 -6.0625,-6.15625 -14.359375,-9.890625 -23.59375,-9.890625 -9.140625,0 -17.515625,3.734375 -23.484375,9.890625 C 5.78125,-50.25 1.953125,-41.859375 1.953125,-32.625 z"
|
||||
id="path54"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-11"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 27.5,-0.84375 -25.359375,-64.3125 -1.578125,0 26.1875,66.1875 1.59375,0 26.1875,-66.1875 -1.578125,0 z"
|
||||
id="path57"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
<symbol
|
||||
overflow="visible"
|
||||
id="glyph2-12"
|
||||
style="overflow:visible">
|
||||
<path
|
||||
style="stroke:none"
|
||||
d="m 5.875,-31.875 33.75,0 0,-1.5 -33.75,0 0,-30.390625 34.484375,0 0,-1.390625 -35.984375,0 0,65.15625 36.171875,0 0,-1.390625 -34.671875,0 z"
|
||||
id="path60"
|
||||
inkscape:connector-curvature="0" />
|
||||
</symbol>
|
||||
</g>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath3094">
|
||||
<rect
|
||||
style="fill:#0000ff;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="rect3096"
|
||||
width="754.1781"
|
||||
height="300.61642"
|
||||
x="13.184932"
|
||||
y="8.90411" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g
|
||||
id="surface1"
|
||||
clip-path="url(#clipPath3094)"
|
||||
transform="matrix(0.30563256,0,0,0.25971391,2.2768141,14.142563)">
|
||||
<g
|
||||
style="fill:#000000;fill-opacity:1"
|
||||
id="g71" />
|
||||
<g
|
||||
id="g1226">
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="M 323.2793,166.51926 H 179.98243 v -6.32812 H 323.2793 V 31.14426 H 176.82618 v -5.9375 h 152.78124 v 276.6875 h -304.879816 V 25.210709 h 6.339311 v 270.787071 h 292.212385 z"
|
||||
id="path188"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccccccc" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="M 554.58618,301.89426 V 37.48801 l 182.875,264.40625 h 6.32812 V 25.303323 h -5.9375 V 290.81613 L 553.78931,25.303323 h -5.53125 V 301.89426 Z"
|
||||
id="path196"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||
d="m 493.91087,342.7146 35.08932,83.78546 35.25165,-83.75238"
|
||||
transform="matrix(3.192199,0,0,3.192199,-1250.002,-1067.559)"
|
||||
id="path75"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1"
|
||||
d="m 511.6195,385.54515 34.93019,0.0"
|
||||
transform="matrix(3.192199,0,0,3.192199,-1250.002,-1067.559)"
|
||||
id="path77"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 149 KiB |
Before Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 224 KiB |
|
@ -0,0 +1,44 @@
|
|||
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
|
||||
// to get started and then uncomment the line below.
|
||||
// import "./user_socket.js"
|
||||
|
||||
// You can include dependencies in two ways.
|
||||
//
|
||||
// The simplest option is to put them in assets/vendor and
|
||||
// import them using relative paths:
|
||||
//
|
||||
// import "../vendor/some-package.js"
|
||||
//
|
||||
// Alternatively, you can `npm install some-package --prefix assets` and import
|
||||
// them using a path starting with the package name:
|
||||
//
|
||||
// import "some-package"
|
||||
//
|
||||
|
||||
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
|
||||
import "phoenix_html"
|
||||
// Establish Phoenix Socket and LiveView configuration.
|
||||
import { Socket } from "phoenix"
|
||||
import { LiveSocket } from "phoenix_live_view"
|
||||
import topbar from "../vendor/topbar"
|
||||
|
||||
let csrfToken = document
|
||||
.querySelector("meta[name='csrf-token']")
|
||||
.getAttribute("content")
|
||||
let liveSocket = new LiveSocket("/live", Socket, {
|
||||
params: { _csrf_token: csrfToken },
|
||||
})
|
||||
|
||||
// Show progress bar on live navigation and form submits
|
||||
topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" })
|
||||
window.addEventListener("phx:page-loading-start", (_info) => topbar.show(300))
|
||||
window.addEventListener("phx:page-loading-stop", (_info) => topbar.hide())
|
||||
|
||||
// connect if there are any LiveViews on the page
|
||||
liveSocket.connect()
|
||||
|
||||
// expose liveSocket on window for web console debug logs and latency simulation:
|
||||
// >> liveSocket.enableDebug()
|
||||
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
|
||||
// >> liveSocket.disableLatencySim()
|
||||
window.liveSocket = liveSocket
|
|
@ -0,0 +1,689 @@
|
|||
# This file originates from node2nix
|
||||
|
||||
{lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile, writeShellScript}:
|
||||
|
||||
let
|
||||
# Workaround to cope with utillinux in Nixpkgs 20.09 and util-linux in Nixpkgs master
|
||||
utillinux = if pkgs ? utillinux then pkgs.utillinux else pkgs.util-linux;
|
||||
|
||||
python = if nodejs ? python then nodejs.python else python2;
|
||||
|
||||
# Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise
|
||||
tarWrapper = runCommand "tarWrapper" {} ''
|
||||
mkdir -p $out/bin
|
||||
|
||||
cat > $out/bin/tar <<EOF
|
||||
#! ${stdenv.shell} -e
|
||||
$(type -p tar) "\$@" --warning=no-unknown-keyword --delay-directory-restore
|
||||
EOF
|
||||
|
||||
chmod +x $out/bin/tar
|
||||
'';
|
||||
|
||||
# Function that generates a TGZ file from a NPM project
|
||||
buildNodeSourceDist =
|
||||
{ name, version, src, ... }:
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "node-tarball-${name}-${version}";
|
||||
inherit src;
|
||||
buildInputs = [ nodejs ];
|
||||
buildPhase = ''
|
||||
export HOME=$TMPDIR
|
||||
tgzFile=$(npm pack | tail -n 1) # Hooks to the pack command will add output (https://docs.npmjs.com/misc/scripts)
|
||||
'';
|
||||
installPhase = ''
|
||||
mkdir -p $out/tarballs
|
||||
mv $tgzFile $out/tarballs
|
||||
mkdir -p $out/nix-support
|
||||
echo "file source-dist $out/tarballs/$tgzFile" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
};
|
||||
|
||||
# Common shell logic
|
||||
installPackage = writeShellScript "install-package" ''
|
||||
installPackage() {
|
||||
local packageName=$1 src=$2
|
||||
|
||||
local strippedName
|
||||
|
||||
local DIR=$PWD
|
||||
cd $TMPDIR
|
||||
|
||||
unpackFile $src
|
||||
|
||||
# Make the base dir in which the target dependency resides first
|
||||
mkdir -p "$(dirname "$DIR/$packageName")"
|
||||
|
||||
if [ -f "$src" ]
|
||||
then
|
||||
# Figure out what directory has been unpacked
|
||||
packageDir="$(find . -maxdepth 1 -type d | tail -1)"
|
||||
|
||||
# Restore write permissions to make building work
|
||||
find "$packageDir" -type d -exec chmod u+x {} \;
|
||||
chmod -R u+w "$packageDir"
|
||||
|
||||
# Move the extracted tarball into the output folder
|
||||
mv "$packageDir" "$DIR/$packageName"
|
||||
elif [ -d "$src" ]
|
||||
then
|
||||
# Get a stripped name (without hash) of the source directory.
|
||||
# On old nixpkgs it's already set internally.
|
||||
if [ -z "$strippedName" ]
|
||||
then
|
||||
strippedName="$(stripHash $src)"
|
||||
fi
|
||||
|
||||
# Restore write permissions to make building work
|
||||
chmod -R u+w "$strippedName"
|
||||
|
||||
# Move the extracted directory into the output folder
|
||||
mv "$strippedName" "$DIR/$packageName"
|
||||
fi
|
||||
|
||||
# Change to the package directory to install dependencies
|
||||
cd "$DIR/$packageName"
|
||||
}
|
||||
'';
|
||||
|
||||
# Bundle the dependencies of the package
|
||||
#
|
||||
# Only include dependencies if they don't exist. They may also be bundled in the package.
|
||||
includeDependencies = {dependencies}:
|
||||
lib.optionalString (dependencies != []) (
|
||||
''
|
||||
mkdir -p node_modules
|
||||
cd node_modules
|
||||
''
|
||||
+ (lib.concatMapStrings (dependency:
|
||||
''
|
||||
if [ ! -e "${dependency.packageName}" ]; then
|
||||
${composePackage dependency}
|
||||
fi
|
||||
''
|
||||
) dependencies)
|
||||
+ ''
|
||||
cd ..
|
||||
''
|
||||
);
|
||||
|
||||
# Recursively composes the dependencies of a package
|
||||
composePackage = { name, packageName, src, dependencies ? [], ... }@args:
|
||||
builtins.addErrorContext "while evaluating node package '${packageName}'" ''
|
||||
installPackage "${packageName}" "${src}"
|
||||
${includeDependencies { inherit dependencies; }}
|
||||
cd ..
|
||||
${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
|
||||
'';
|
||||
|
||||
pinpointDependencies = {dependencies, production}:
|
||||
let
|
||||
pinpointDependenciesFromPackageJSON = writeTextFile {
|
||||
name = "pinpointDependencies.js";
|
||||
text = ''
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
function resolveDependencyVersion(location, name) {
|
||||
if(location == process.env['NIX_STORE']) {
|
||||
return null;
|
||||
} else {
|
||||
var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json");
|
||||
|
||||
if(fs.existsSync(dependencyPackageJSON)) {
|
||||
var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON));
|
||||
|
||||
if(dependencyPackageObj.name == name) {
|
||||
return dependencyPackageObj.version;
|
||||
}
|
||||
} else {
|
||||
return resolveDependencyVersion(path.resolve(location, ".."), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function replaceDependencies(dependencies) {
|
||||
if(typeof dependencies == "object" && dependencies !== null) {
|
||||
for(var dependency in dependencies) {
|
||||
var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency);
|
||||
|
||||
if(resolvedVersion === null) {
|
||||
process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n");
|
||||
} else {
|
||||
dependencies[dependency] = resolvedVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the package.json configuration */
|
||||
var packageObj = JSON.parse(fs.readFileSync('./package.json'));
|
||||
|
||||
/* Pinpoint all dependencies */
|
||||
replaceDependencies(packageObj.dependencies);
|
||||
if(process.argv[2] == "development") {
|
||||
replaceDependencies(packageObj.devDependencies);
|
||||
}
|
||||
else {
|
||||
packageObj.devDependencies = {};
|
||||
}
|
||||
replaceDependencies(packageObj.optionalDependencies);
|
||||
replaceDependencies(packageObj.peerDependencies);
|
||||
|
||||
/* Write the fixed package.json file */
|
||||
fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2));
|
||||
'';
|
||||
};
|
||||
in
|
||||
''
|
||||
node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"}
|
||||
|
||||
${lib.optionalString (dependencies != [])
|
||||
''
|
||||
if [ -d node_modules ]
|
||||
then
|
||||
cd node_modules
|
||||
${lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies}
|
||||
cd ..
|
||||
fi
|
||||
''}
|
||||
'';
|
||||
|
||||
# Recursively traverses all dependencies of a package and pinpoints all
|
||||
# dependencies in the package.json file to the versions that are actually
|
||||
# being used.
|
||||
|
||||
pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args:
|
||||
''
|
||||
if [ -d "${packageName}" ]
|
||||
then
|
||||
cd "${packageName}"
|
||||
${pinpointDependencies { inherit dependencies production; }}
|
||||
cd ..
|
||||
${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
|
||||
fi
|
||||
'';
|
||||
|
||||
# Extract the Node.js source code which is used to compile packages with
|
||||
# native bindings
|
||||
nodeSources = runCommand "node-sources" {} ''
|
||||
tar --no-same-owner --no-same-permissions -xf ${nodejs.src}
|
||||
mv node-* $out
|
||||
'';
|
||||
|
||||
# Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty)
|
||||
addIntegrityFieldsScript = writeTextFile {
|
||||
name = "addintegrityfields.js";
|
||||
text = ''
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
function augmentDependencies(baseDir, dependencies) {
|
||||
for(var dependencyName in dependencies) {
|
||||
var dependency = dependencies[dependencyName];
|
||||
|
||||
// Open package.json and augment metadata fields
|
||||
var packageJSONDir = path.join(baseDir, "node_modules", dependencyName);
|
||||
var packageJSONPath = path.join(packageJSONDir, "package.json");
|
||||
|
||||
if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored
|
||||
console.log("Adding metadata fields to: "+packageJSONPath);
|
||||
var packageObj = JSON.parse(fs.readFileSync(packageJSONPath));
|
||||
|
||||
if(dependency.integrity) {
|
||||
packageObj["_integrity"] = dependency.integrity;
|
||||
} else {
|
||||
packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads.
|
||||
}
|
||||
|
||||
if(dependency.resolved) {
|
||||
packageObj["_resolved"] = dependency.resolved; // Adopt the resolved property if one has been provided
|
||||
} else {
|
||||
packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories.
|
||||
}
|
||||
|
||||
if(dependency.from !== undefined) { // Adopt from property if one has been provided
|
||||
packageObj["_from"] = dependency.from;
|
||||
}
|
||||
|
||||
fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2));
|
||||
}
|
||||
|
||||
// Augment transitive dependencies
|
||||
if(dependency.dependencies !== undefined) {
|
||||
augmentDependencies(packageJSONDir, dependency.dependencies);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(fs.existsSync("./package-lock.json")) {
|
||||
var packageLock = JSON.parse(fs.readFileSync("./package-lock.json"));
|
||||
|
||||
if(![1, 2].includes(packageLock.lockfileVersion)) {
|
||||
process.stderr.write("Sorry, I only understand lock file versions 1 and 2!\n");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if(packageLock.dependencies !== undefined) {
|
||||
augmentDependencies(".", packageLock.dependencies);
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
# Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes
|
||||
reconstructPackageLock = writeTextFile {
|
||||
name = "reconstructpackagelock.js";
|
||||
text = ''
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var packageObj = JSON.parse(fs.readFileSync("package.json"));
|
||||
|
||||
var lockObj = {
|
||||
name: packageObj.name,
|
||||
version: packageObj.version,
|
||||
lockfileVersion: 2,
|
||||
requires: true,
|
||||
packages: {
|
||||
"": {
|
||||
name: packageObj.name,
|
||||
version: packageObj.version,
|
||||
license: packageObj.license,
|
||||
bin: packageObj.bin,
|
||||
dependencies: packageObj.dependencies,
|
||||
engines: packageObj.engines,
|
||||
optionalDependencies: packageObj.optionalDependencies
|
||||
}
|
||||
},
|
||||
dependencies: {}
|
||||
};
|
||||
|
||||
function augmentPackageJSON(filePath, packages, dependencies) {
|
||||
var packageJSON = path.join(filePath, "package.json");
|
||||
if(fs.existsSync(packageJSON)) {
|
||||
var packageObj = JSON.parse(fs.readFileSync(packageJSON));
|
||||
packages[filePath] = {
|
||||
version: packageObj.version,
|
||||
integrity: "sha1-000000000000000000000000000=",
|
||||
dependencies: packageObj.dependencies,
|
||||
engines: packageObj.engines,
|
||||
optionalDependencies: packageObj.optionalDependencies
|
||||
};
|
||||
dependencies[packageObj.name] = {
|
||||
version: packageObj.version,
|
||||
integrity: "sha1-000000000000000000000000000=",
|
||||
dependencies: {}
|
||||
};
|
||||
processDependencies(path.join(filePath, "node_modules"), packages, dependencies[packageObj.name].dependencies);
|
||||
}
|
||||
}
|
||||
|
||||
function processDependencies(dir, packages, dependencies) {
|
||||
if(fs.existsSync(dir)) {
|
||||
var files = fs.readdirSync(dir);
|
||||
|
||||
files.forEach(function(entry) {
|
||||
var filePath = path.join(dir, entry);
|
||||
var stats = fs.statSync(filePath);
|
||||
|
||||
if(stats.isDirectory()) {
|
||||
if(entry.substr(0, 1) == "@") {
|
||||
// When we encounter a namespace folder, augment all packages belonging to the scope
|
||||
var pkgFiles = fs.readdirSync(filePath);
|
||||
|
||||
pkgFiles.forEach(function(entry) {
|
||||
if(stats.isDirectory()) {
|
||||
var pkgFilePath = path.join(filePath, entry);
|
||||
augmentPackageJSON(pkgFilePath, packages, dependencies);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
augmentPackageJSON(filePath, packages, dependencies);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
processDependencies("node_modules", lockObj.packages, lockObj.dependencies);
|
||||
|
||||
fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2));
|
||||
'';
|
||||
};
|
||||
|
||||
# Script that links bins defined in package.json to the node_modules bin directory
|
||||
# NPM does not do this for top-level packages itself anymore as of v7
|
||||
linkBinsScript = writeTextFile {
|
||||
name = "linkbins.js";
|
||||
text = ''
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
var packageObj = JSON.parse(fs.readFileSync("package.json"));
|
||||
|
||||
var nodeModules = Array(packageObj.name.split("/").length).fill("..").join(path.sep);
|
||||
|
||||
if(packageObj.bin !== undefined) {
|
||||
fs.mkdirSync(path.join(nodeModules, ".bin"))
|
||||
|
||||
if(typeof packageObj.bin == "object") {
|
||||
Object.keys(packageObj.bin).forEach(function(exe) {
|
||||
if(fs.existsSync(packageObj.bin[exe])) {
|
||||
console.log("linking bin '" + exe + "'");
|
||||
fs.symlinkSync(
|
||||
path.join("..", packageObj.name, packageObj.bin[exe]),
|
||||
path.join(nodeModules, ".bin", exe)
|
||||
);
|
||||
}
|
||||
else {
|
||||
console.log("skipping non-existent bin '" + exe + "'");
|
||||
}
|
||||
})
|
||||
}
|
||||
else {
|
||||
if(fs.existsSync(packageObj.bin)) {
|
||||
console.log("linking bin '" + packageObj.bin + "'");
|
||||
fs.symlinkSync(
|
||||
path.join("..", packageObj.name, packageObj.bin),
|
||||
path.join(nodeModules, ".bin", packageObj.name.split("/").pop())
|
||||
);
|
||||
}
|
||||
else {
|
||||
console.log("skipping non-existent bin '" + packageObj.bin + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(packageObj.directories !== undefined && packageObj.directories.bin !== undefined) {
|
||||
fs.mkdirSync(path.join(nodeModules, ".bin"))
|
||||
|
||||
fs.readdirSync(packageObj.directories.bin).forEach(function(exe) {
|
||||
if(fs.existsSync(path.join(packageObj.directories.bin, exe))) {
|
||||
console.log("linking bin '" + exe + "'");
|
||||
fs.symlinkSync(
|
||||
path.join("..", packageObj.name, packageObj.directories.bin, exe),
|
||||
path.join(nodeModules, ".bin", exe)
|
||||
);
|
||||
}
|
||||
else {
|
||||
console.log("skipping non-existent bin '" + exe + "'");
|
||||
}
|
||||
})
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
prepareAndInvokeNPM = {packageName, bypassCache, reconstructLock, npmFlags, production}:
|
||||
let
|
||||
forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com";
|
||||
in
|
||||
''
|
||||
# Pinpoint the versions of all dependencies to the ones that are actually being used
|
||||
echo "pinpointing versions of dependencies..."
|
||||
source $pinpointDependenciesScriptPath
|
||||
|
||||
# Patch the shebangs of the bundled modules to prevent them from
|
||||
# calling executables outside the Nix store as much as possible
|
||||
patchShebangs .
|
||||
|
||||
# Deploy the Node.js package by running npm install. Since the
|
||||
# dependencies have been provided already by ourselves, it should not
|
||||
# attempt to install them again, which is good, because we want to make
|
||||
# it Nix's responsibility. If it needs to install any dependencies
|
||||
# anyway (e.g. because the dependency parameters are
|
||||
# incomplete/incorrect), it fails.
|
||||
#
|
||||
# The other responsibilities of NPM are kept -- version checks, build
|
||||
# steps, postprocessing etc.
|
||||
|
||||
export HOME=$TMPDIR
|
||||
cd "${packageName}"
|
||||
runHook preRebuild
|
||||
|
||||
${lib.optionalString bypassCache ''
|
||||
${lib.optionalString reconstructLock ''
|
||||
if [ -f package-lock.json ]
|
||||
then
|
||||
echo "WARNING: Reconstruct lock option enabled, but a lock file already exists!"
|
||||
echo "This will most likely result in version mismatches! We will remove the lock file and regenerate it!"
|
||||
rm package-lock.json
|
||||
else
|
||||
echo "No package-lock.json file found, reconstructing..."
|
||||
fi
|
||||
|
||||
node ${reconstructPackageLock}
|
||||
''}
|
||||
|
||||
node ${addIntegrityFieldsScript}
|
||||
''}
|
||||
|
||||
npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} rebuild
|
||||
|
||||
runHook postRebuild
|
||||
|
||||
if [ "''${dontNpmInstall-}" != "1" ]
|
||||
then
|
||||
# NPM tries to download packages even when they already exist if npm-shrinkwrap is used.
|
||||
rm -f npm-shrinkwrap.json
|
||||
|
||||
npm ${forceOfflineFlag} --nodedir=${nodeSources} --no-bin-links --ignore-scripts ${npmFlags} ${lib.optionalString production "--production"} install
|
||||
fi
|
||||
|
||||
# Link executables defined in package.json
|
||||
node ${linkBinsScript}
|
||||
'';
|
||||
|
||||
# Builds and composes an NPM package including all its dependencies
|
||||
buildNodePackage =
|
||||
{ name
|
||||
, packageName
|
||||
, version ? null
|
||||
, dependencies ? []
|
||||
, buildInputs ? []
|
||||
, production ? true
|
||||
, npmFlags ? ""
|
||||
, dontNpmInstall ? false
|
||||
, bypassCache ? false
|
||||
, reconstructLock ? false
|
||||
, preRebuild ? ""
|
||||
, dontStrip ? true
|
||||
, unpackPhase ? "true"
|
||||
, buildPhase ? "true"
|
||||
, meta ? {}
|
||||
, ... }@args:
|
||||
|
||||
let
|
||||
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" "meta" ];
|
||||
in
|
||||
stdenv.mkDerivation ({
|
||||
name = "${name}${if version == null then "" else "-${version}"}";
|
||||
buildInputs = [ tarWrapper python nodejs ]
|
||||
++ lib.optional (stdenv.isLinux) utillinux
|
||||
++ lib.optional (stdenv.isDarwin) libtool
|
||||
++ buildInputs;
|
||||
|
||||
inherit nodejs;
|
||||
|
||||
inherit dontStrip; # Stripping may fail a build for some package deployments
|
||||
inherit dontNpmInstall preRebuild unpackPhase buildPhase;
|
||||
|
||||
compositionScript = composePackage args;
|
||||
pinpointDependenciesScript = pinpointDependenciesOfPackage args;
|
||||
|
||||
passAsFile = [ "compositionScript" "pinpointDependenciesScript" ];
|
||||
|
||||
installPhase = ''
|
||||
source ${installPackage}
|
||||
|
||||
# Create and enter a root node_modules/ folder
|
||||
mkdir -p $out/lib/node_modules
|
||||
cd $out/lib/node_modules
|
||||
|
||||
# Compose the package and all its dependencies
|
||||
source $compositionScriptPath
|
||||
|
||||
${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }}
|
||||
|
||||
# Create symlink to the deployed executable folder, if applicable
|
||||
if [ -d "$out/lib/node_modules/.bin" ]
|
||||
then
|
||||
ln -s $out/lib/node_modules/.bin $out/bin
|
||||
|
||||
# Fixup all executables
|
||||
ls $out/bin/* | while read i
|
||||
do
|
||||
file="$(readlink -f "$i")"
|
||||
chmod u+rwx "$file"
|
||||
if isScript "$file"
|
||||
then
|
||||
sed -i 's/\r$//' "$file" # convert crlf to lf
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Create symlinks to the deployed manual page folders, if applicable
|
||||
if [ -d "$out/lib/node_modules/${packageName}/man" ]
|
||||
then
|
||||
mkdir -p $out/share
|
||||
for dir in "$out/lib/node_modules/${packageName}/man/"*
|
||||
do
|
||||
mkdir -p $out/share/man/$(basename "$dir")
|
||||
for page in "$dir"/*
|
||||
do
|
||||
ln -s $page $out/share/man/$(basename "$dir")
|
||||
done
|
||||
done
|
||||
fi
|
||||
|
||||
# Run post install hook, if provided
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
meta = {
|
||||
# default to Node.js' platforms
|
||||
platforms = nodejs.meta.platforms;
|
||||
} // meta;
|
||||
} // extraArgs);
|
||||
|
||||
# Builds a node environment (a node_modules folder and a set of binaries)
|
||||
buildNodeDependencies =
|
||||
{ name
|
||||
, packageName
|
||||
, version ? null
|
||||
, src
|
||||
, dependencies ? []
|
||||
, buildInputs ? []
|
||||
, production ? true
|
||||
, npmFlags ? ""
|
||||
, dontNpmInstall ? false
|
||||
, bypassCache ? false
|
||||
, reconstructLock ? false
|
||||
, dontStrip ? true
|
||||
, unpackPhase ? "true"
|
||||
, buildPhase ? "true"
|
||||
, ... }@args:
|
||||
|
||||
let
|
||||
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" ];
|
||||
in
|
||||
stdenv.mkDerivation ({
|
||||
name = "node-dependencies-${name}${if version == null then "" else "-${version}"}";
|
||||
|
||||
buildInputs = [ tarWrapper python nodejs ]
|
||||
++ lib.optional (stdenv.isLinux) utillinux
|
||||
++ lib.optional (stdenv.isDarwin) libtool
|
||||
++ buildInputs;
|
||||
|
||||
inherit dontStrip; # Stripping may fail a build for some package deployments
|
||||
inherit dontNpmInstall unpackPhase buildPhase;
|
||||
|
||||
includeScript = includeDependencies { inherit dependencies; };
|
||||
pinpointDependenciesScript = pinpointDependenciesOfPackage args;
|
||||
|
||||
passAsFile = [ "includeScript" "pinpointDependenciesScript" ];
|
||||
|
||||
installPhase = ''
|
||||
source ${installPackage}
|
||||
|
||||
mkdir -p $out/${packageName}
|
||||
cd $out/${packageName}
|
||||
|
||||
source $includeScriptPath
|
||||
|
||||
# Create fake package.json to make the npm commands work properly
|
||||
cp ${src}/package.json .
|
||||
chmod 644 package.json
|
||||
${lib.optionalString bypassCache ''
|
||||
if [ -f ${src}/package-lock.json ]
|
||||
then
|
||||
cp ${src}/package-lock.json .
|
||||
chmod 644 package-lock.json
|
||||
fi
|
||||
''}
|
||||
|
||||
# Go to the parent folder to make sure that all packages are pinpointed
|
||||
cd ..
|
||||
${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
|
||||
|
||||
${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }}
|
||||
|
||||
# Expose the executables that were installed
|
||||
cd ..
|
||||
${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."}
|
||||
|
||||
mv ${packageName} lib
|
||||
ln -s $out/lib/node_modules/.bin $out/bin
|
||||
'';
|
||||
} // extraArgs);
|
||||
|
||||
# Builds a development shell
|
||||
buildNodeShell =
|
||||
{ name
|
||||
, packageName
|
||||
, version ? null
|
||||
, src
|
||||
, dependencies ? []
|
||||
, buildInputs ? []
|
||||
, production ? true
|
||||
, npmFlags ? ""
|
||||
, dontNpmInstall ? false
|
||||
, bypassCache ? false
|
||||
, reconstructLock ? false
|
||||
, dontStrip ? true
|
||||
, unpackPhase ? "true"
|
||||
, buildPhase ? "true"
|
||||
, ... }@args:
|
||||
|
||||
let
|
||||
nodeDependencies = buildNodeDependencies args;
|
||||
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "unpackPhase" "buildPhase" ];
|
||||
in
|
||||
stdenv.mkDerivation ({
|
||||
name = "node-shell-${name}${if version == null then "" else "-${version}"}";
|
||||
|
||||
buildInputs = [ python nodejs ] ++ lib.optional (stdenv.isLinux) utillinux ++ buildInputs;
|
||||
buildCommand = ''
|
||||
mkdir -p $out/bin
|
||||
cat > $out/bin/shell <<EOF
|
||||
#! ${stdenv.shell} -e
|
||||
$shellHook
|
||||
exec ${stdenv.shell}
|
||||
EOF
|
||||
chmod +x $out/bin/shell
|
||||
'';
|
||||
|
||||
# Provide the dependencies in a development shell through the NODE_PATH environment variable
|
||||
inherit nodeDependencies;
|
||||
shellHook = lib.optionalString (dependencies != []) ''
|
||||
export NODE_PATH=${nodeDependencies}/lib/node_modules
|
||||
export PATH="${nodeDependencies}/bin:$PATH"
|
||||
'';
|
||||
} // extraArgs);
|
||||
in
|
||||
{
|
||||
buildNodeSourceDist = lib.makeOverridable buildNodeSourceDist;
|
||||
buildNodePackage = lib.makeOverridable buildNodePackage;
|
||||
buildNodeDependencies = lib.makeOverridable buildNodeDependencies;
|
||||
buildNodeShell = lib.makeOverridable buildNodeShell;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
# This file has been generated by node2nix 1.11.1. Do not edit!
|
||||
|
||||
{nodeEnv, fetchurl, fetchgit, nix-gitignore, stdenv, lib, globalBuildInputs ? []}:
|
||||
|
||||
let
|
||||
sources = {};
|
||||
args = {
|
||||
name = "portfolio";
|
||||
packageName = "portfolio";
|
||||
version = "0.1.0";
|
||||
src = ./.;
|
||||
buildInputs = globalBuildInputs;
|
||||
meta = {
|
||||
description = "";
|
||||
license = "ISC";
|
||||
};
|
||||
production = true;
|
||||
bypassCache = true;
|
||||
reconstructLock = false;
|
||||
};
|
||||
in
|
||||
{
|
||||
args = args;
|
||||
sources = sources;
|
||||
tarball = nodeEnv.buildNodeSourceDist args;
|
||||
package = nodeEnv.buildNodePackage args;
|
||||
shell = nodeEnv.buildNodeShell args;
|
||||
nodeDependencies = nodeEnv.buildNodeDependencies (lib.overrideExisting args {
|
||||
src = stdenv.mkDerivation {
|
||||
name = args.name + "-package-json";
|
||||
src = nix-gitignore.gitignoreSourcePure [
|
||||
"*"
|
||||
"!package.json"
|
||||
"!package-lock.json"
|
||||
] args.src;
|
||||
dontBuild = true;
|
||||
installPhase = "mkdir -p $out; cp -r ./* $out;";
|
||||
};
|
||||
});
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "portfolio",
|
||||
"version": "0.1.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "portfolio",
|
||||
"version": "0.1.0",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "portfolio",
|
||||
"version": "0.1.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\"",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
/** @type {import('prettier').Options} */
|
||||
module.exports = {
|
||||
arrowParens: "always",
|
||||
semi: false,
|
||||
tabWidth: 2,
|
||||
trailingComma: "es5",
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// See the Tailwind configuration guide for advanced usage
|
||||
// https://tailwindcss.com/docs/configuration
|
||||
|
||||
const plugin = require("tailwindcss/plugin")
|
||||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
"./js/**/*.js",
|
||||
"../lib/portfolio_web.ex",
|
||||
"../lib/portfolio_web/**/*.*ex",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
brand: "#FD4F00",
|
||||
info: "#0F3042",
|
||||
tip: "#1B7A46",
|
||||
warning: "#C68E08",
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require("@tailwindcss/forms"),
|
||||
// Allows prefixing tailwind classes with LiveView classes to add rules
|
||||
// only when LiveView classes are applied, for example:
|
||||
//
|
||||
// <div class="phx-click-loading:animate-ping">
|
||||
//
|
||||
plugin(({ addVariant }) =>
|
||||
addVariant("phx-no-feedback", [".phx-no-feedback&", ".phx-no-feedback &"])
|
||||
),
|
||||
plugin(({ addVariant }) =>
|
||||
addVariant("phx-click-loading", [
|
||||
".phx-click-loading&",
|
||||
".phx-click-loading &",
|
||||
])
|
||||
),
|
||||
plugin(({ addVariant }) =>
|
||||
addVariant("phx-submit-loading", [
|
||||
".phx-submit-loading&",
|
||||
".phx-submit-loading &",
|
||||
])
|
||||
),
|
||||
plugin(({ addVariant }) =>
|
||||
addVariant("phx-change-loading", [
|
||||
".phx-change-loading&",
|
||||
".phx-change-loading &",
|
||||
])
|
||||
),
|
||||
|
||||
// Embeds Heroicons (https://heroicons.com) into your app.css bundle
|
||||
// See your `CoreComponents.icon/1` for more information.
|
||||
//
|
||||
plugin(function ({ matchComponents, theme }) {
|
||||
let iconsDir = path.join(__dirname, "./vendor/heroicons/optimized")
|
||||
let values = {}
|
||||
let icons = [
|
||||
["", "/24/outline"],
|
||||
["-solid", "/24/solid"],
|
||||
["-mini", "/20/solid"],
|
||||
]
|
||||
icons.forEach(([suffix, dir]) => {
|
||||
fs.readdirSync(path.join(iconsDir, dir)).forEach((file) => {
|
||||
let name = path.basename(file, ".svg") + suffix
|
||||
values[name] = { name, fullPath: path.join(iconsDir, dir, file) }
|
||||
})
|
||||
})
|
||||
matchComponents(
|
||||
{
|
||||
hero: ({ name, fullPath }) => {
|
||||
let content = fs
|
||||
.readFileSync(fullPath)
|
||||
.toString()
|
||||
.replace(/\r?\n|\r/g, "")
|
||||
return {
|
||||
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
|
||||
"-webkit-mask": `var(--hero-${name})`,
|
||||
mask: `var(--hero-${name})`,
|
||||
"mask-repeat": "no-repeat",
|
||||
"background-color": "currentColor",
|
||||
"vertical-align": "middle",
|
||||
display: "inline-block",
|
||||
width: theme("spacing.5"),
|
||||
height: theme("spacing.5"),
|
||||
}
|
||||
},
|
||||
},
|
||||
{ values }
|
||||
)
|
||||
}),
|
||||
],
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
// https://esbuild.github.io/content-types/#tsconfig-json
|
||||
"compilerOptions": {
|
||||
// Keep in mind that ES6+ syntax to ES5 is not supported in esbuild yet.
|
||||
"target": "es2016",
|
||||
// Even when transpiling a single module, the TypeScript compiler actually
|
||||
// parses imported files so it can tell whether an imported name is a type
|
||||
// or a value. However, tools like esbuild compile each file in isolation so
|
||||
// they can't tell if an imported name is a type or a value.
|
||||
// https://esbuild.github.io/content-types/#isolated-modules
|
||||
"isolatedModules": true,
|
||||
// Disables legacy behavior around imports and makes TypeScript's type
|
||||
// system compatible with ESM.
|
||||
"esModuleInterop": true,
|
||||
// Enables define semantics. In this mode, TypeScript class fields behave
|
||||
// like normal JavaScript class fields. Field initializers do not trigger
|
||||
// setters on the base class.
|
||||
"useDefineForClassFields": true,
|
||||
// If either of these options are enabled, esbuild will consider all code
|
||||
// in all TypeScript files to be in strict mode and will prefix generated
|
||||
// code with "use strict" unless the output format is set to esm (since all
|
||||
// ESM files are automatically in strict mode).
|
||||
"strict": true,
|
||||
// Emit .js files with JSX changed to the equivalent React.createElement
|
||||
// calls. It seems like the "react" value mirrors esbuild's native
|
||||
// "transform" option, but it isn't obvious how these two relate from the
|
||||
// documentation: https://esbuild.github.io/api/#jsx.
|
||||
"jsx": "react"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2020 Refactoring UI Inc.
|
||||
|
||||
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.
|
|
@ -0,0 +1,6 @@
|
|||
You are running heroicons v2.0.16. To upgrade in place, you can run the following command,
|
||||
where your `HERO_VSN` export is your desired version:
|
||||
|
||||
export HERO_VSN="2.0.16" ; \
|
||||
curl -L "https://github.com/tailwindlabs/heroicons/archive/refs/tags/v${HERO_VSN}.tar.gz" | \
|
||||
tar -xvz --strip-components=1 heroicons-${HERO_VSN}/optimized
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M9.664 1.319a.75.75 0 01.672 0 41.059 41.059 0 018.198 5.424.75.75 0 01-.254 1.285 31.372 31.372 0 00-7.86 3.83.75.75 0 01-.84 0 31.508 31.508 0 00-2.08-1.287V9.394c0-.244.116-.463.302-.592a35.504 35.504 0 013.305-2.033.75.75 0 00-.714-1.319 37 37 0 00-3.446 2.12A2.216 2.216 0 006 9.393v.38a31.293 31.293 0 00-4.28-1.746.75.75 0 01-.254-1.285 41.059 41.059 0 018.198-5.424zM6 11.459a29.848 29.848 0 00-2.455-1.158 41.029 41.029 0 00-.39 3.114.75.75 0 00.419.74c.528.256 1.046.53 1.554.82-.21.324-.455.63-.739.914a.75.75 0 101.06 1.06c.37-.369.69-.77.96-1.193a26.61 26.61 0 013.095 2.348.75.75 0 00.992 0 26.547 26.547 0 015.93-3.95.75.75 0 00.42-.739 41.053 41.053 0 00-.39-3.114 29.925 29.925 0 00-5.199 2.801 2.25 2.25 0 01-2.514 0c-.41-.275-.826-.541-1.25-.797a6.985 6.985 0 01-1.084 3.45 26.503 26.503 0 00-1.281-.78A5.487 5.487 0 006 12v-.54z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1010 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M10 3.75a2 2 0 10-4 0 2 2 0 004 0zM17.25 4.5a.75.75 0 000-1.5h-5.5a.75.75 0 000 1.5h5.5zM5 3.75a.75.75 0 01-.75.75h-1.5a.75.75 0 010-1.5h1.5a.75.75 0 01.75.75zM4.25 17a.75.75 0 000-1.5h-1.5a.75.75 0 000 1.5h1.5zM17.25 17a.75.75 0 000-1.5h-5.5a.75.75 0 000 1.5h5.5zM9 10a.75.75 0 01-.75.75h-5.5a.75.75 0 010-1.5h5.5A.75.75 0 019 10zM17.25 10.75a.75.75 0 000-1.5h-1.5a.75.75 0 000 1.5h1.5zM14 10a2 2 0 10-4 0 2 2 0 004 0zM10 16.25a2 2 0 10-4 0 2 2 0 004 0z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 576 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M17 2.75a.75.75 0 00-1.5 0v5.5a.75.75 0 001.5 0v-5.5zM17 15.75a.75.75 0 00-1.5 0v1.5a.75.75 0 001.5 0v-1.5zM3.75 15a.75.75 0 01.75.75v1.5a.75.75 0 01-1.5 0v-1.5a.75.75 0 01.75-.75zM4.5 2.75a.75.75 0 00-1.5 0v5.5a.75.75 0 001.5 0v-5.5zM10 11a.75.75 0 01.75.75v5.5a.75.75 0 01-1.5 0v-5.5A.75.75 0 0110 11zM10.75 2.75a.75.75 0 00-1.5 0v1.5a.75.75 0 001.5 0v-1.5zM10 6a2 2 0 100 4 2 2 0 000-4zM3.75 10a2 2 0 100 4 2 2 0 000-4zM16.25 10a2 2 0 100 4 2 2 0 000-4z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 578 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M2 3a1 1 0 00-1 1v1a1 1 0 001 1h16a1 1 0 001-1V4a1 1 0 00-1-1H2zm0 4.5h16l-.811 7.71a2 2 0 01-1.99 1.79H4.802a2 2 0 01-1.99-1.79L2 7.5zM10 9a.75.75 0 01.75.75v2.546l.943-1.048a.75.75 0 111.114 1.004l-2.25 2.5a.75.75 0 01-1.114 0l-2.25-2.5a.75.75 0 111.114-1.004l.943 1.048V9.75A.75.75 0 0110 9z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 456 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M2 3a1 1 0 00-1 1v1a1 1 0 001 1h16a1 1 0 001-1V4a1 1 0 00-1-1H2z"/>
|
||||
<path fill-rule="evenodd" d="M2 7.5h16l-.811 7.71a2 2 0 01-1.99 1.79H4.802a2 2 0 01-1.99-1.79L2 7.5zm5.22 1.72a.75.75 0 011.06 0L10 10.94l1.72-1.72a.75.75 0 111.06 1.06L11.06 12l1.72 1.72a.75.75 0 11-1.06 1.06L10 13.06l-1.72 1.72a.75.75 0 01-1.06-1.06L8.94 12l-1.72-1.72a.75.75 0 010-1.06z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 501 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M2 3a1 1 0 00-1 1v1a1 1 0 001 1h16a1 1 0 001-1V4a1 1 0 00-1-1H2z"/>
|
||||
<path fill-rule="evenodd" d="M2 7.5h16l-.811 7.71a2 2 0 01-1.99 1.79H4.802a2 2 0 01-1.99-1.79L2 7.5zM7 11a1 1 0 011-1h4a1 1 0 110 2H8a1 1 0 01-1-1z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 359 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm.75-11.25a.75.75 0 00-1.5 0v4.59L7.3 9.24a.75.75 0 00-1.1 1.02l3.25 3.5a.75.75 0 001.1 0l3.25-3.5a.75.75 0 10-1.1-1.02l-1.95 2.1V6.75z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 330 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M14.78 5.22a.75.75 0 00-1.06 0L6.5 12.44V6.75a.75.75 0 00-1.5 0v7.5c0 .414.336.75.75.75h7.5a.75.75 0 000-1.5H7.56l7.22-7.22a.75.75 0 000-1.06z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 304 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M8 1a.75.75 0 01.75.75V6h-1.5V1.75A.75.75 0 018 1zm-.75 5v3.296l-.943-1.048a.75.75 0 10-1.114 1.004l2.25 2.5a.75.75 0 001.114 0l2.25-2.5a.75.75 0 00-1.114-1.004L8.75 9.296V6h2A2.25 2.25 0 0113 8.25v4.5A2.25 2.25 0 0110.75 15h-5.5A2.25 2.25 0 013 12.75v-4.5A2.25 2.25 0 015.25 6h2zM7 16.75v-.25h3.75a3.75 3.75 0 003.75-3.75V10h.25A2.25 2.25 0 0117 12.25v4.5A2.25 2.25 0 0114.75 19h-5.5A2.25 2.25 0 017 16.75z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 569 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M13.75 7h-3v5.296l1.943-2.048a.75.75 0 011.114 1.004l-3.25 3.5a.75.75 0 01-1.114 0l-3.25-3.5a.75.75 0 111.114-1.004l1.943 2.048V7h1.5V1.75a.75.75 0 00-1.5 0V7h-3A2.25 2.25 0 004 9.25v7.5A2.25 2.25 0 006.25 19h7.5A2.25 2.25 0 0016 16.75v-7.5A2.25 2.25 0 0013.75 7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 385 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M6.28 5.22a.75.75 0 00-1.06 1.06l7.22 7.22H6.75a.75.75 0 000 1.5h7.5a.747.747 0 00.75-.75v-7.5a.75.75 0 00-1.5 0v5.69L6.28 5.22z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 250 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path d="M10.75 2.75a.75.75 0 00-1.5 0v8.614L6.295 8.235a.75.75 0 10-1.09 1.03l4.25 4.5a.75.75 0 001.09 0l4.25-4.5a.75.75 0 00-1.09-1.03l-2.955 3.129V2.75z"/>
|
||||
<path d="M3.5 12.75a.75.75 0 00-1.5 0v2.5A2.75 2.75 0 004.75 18h10.5A2.75 2.75 0 0018 15.25v-2.5a.75.75 0 00-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 454 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 3a.75.75 0 01.75.75v10.638l3.96-4.158a.75.75 0 111.08 1.04l-5.25 5.5a.75.75 0 01-1.08 0l-5.25-5.5a.75.75 0 111.08-1.04l3.96 4.158V3.75A.75.75 0 0110 3z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 317 B |
|
@ -0,0 +1,10 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<g clip-path="url(#clip0_9_2121)">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.25-7.25a.75.75 0 000-1.5H8.66l2.1-1.95a.75.75 0 10-1.02-1.1l-3.5 3.25a.75.75 0 000 1.1l3.5 3.25a.75.75 0 001.02-1.1l-2.1-1.95h4.59z" clip-rule="evenodd"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9_2121">
|
||||
<path d="M0 0h20v20H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 475 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M3 4.25A2.25 2.25 0 015.25 2h5.5A2.25 2.25 0 0113 4.25v2a.75.75 0 01-1.5 0v-2a.75.75 0 00-.75-.75h-5.5a.75.75 0 00-.75.75v11.5c0 .414.336.75.75.75h5.5a.75.75 0 00.75-.75v-2a.75.75 0 011.5 0v2A2.25 2.25 0 0110.75 18h-5.5A2.25 2.25 0 013 15.75V4.25z" clip-rule="evenodd"/>
|
||||
<path fill-rule="evenodd" d="M19 10a.75.75 0 00-.75-.75H8.704l1.048-.943a.75.75 0 10-1.004-1.114l-2.5 2.25a.75.75 0 000 1.114l2.5 2.25a.75.75 0 101.004-1.114l-1.048-.943h9.546A.75.75 0 0019 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 628 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M17 10a.75.75 0 01-.75.75H5.612l4.158 3.96a.75.75 0 11-1.04 1.08l-5.5-5.25a.75.75 0 010-1.08l5.5-5.25a.75.75 0 111.04 1.08L5.612 9.25H16.25A.75.75 0 0117 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 319 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 2a.75.75 0 01.75.75v12.59l1.95-2.1a.75.75 0 111.1 1.02l-3.25 3.5a.75.75 0 01-1.1 0l-3.25-3.5a.75.75 0 111.1-1.02l1.95 2.1V2.75A.75.75 0 0110 2z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 309 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M18 10a.75.75 0 01-.75.75H4.66l2.1 1.95a.75.75 0 11-1.02 1.1l-3.5-3.25a.75.75 0 010-1.1l3.5-3.25a.75.75 0 111.02 1.1l-2.1 1.95h12.59A.75.75 0 0118 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 312 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M2 10a.75.75 0 01.75-.75h12.59l-2.1-1.95a.75.75 0 111.02-1.1l3.5 3.25a.75.75 0 010 1.1l-3.5 3.25a.75.75 0 11-1.02-1.1l2.1-1.95H2.75A.75.75 0 012 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 310 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 18a.75.75 0 01-.75-.75V4.66L7.3 6.76a.75.75 0 11-1.1-1.02l3.25-3.5a.75.75 0 011.1 0l3.25 3.5a.75.75 0 01-1.1 1.02l-1.95-2.1v12.59A.75.75 0 0110 18z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 313 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 4.5c1.215 0 2.417.055 3.604.162a.68.68 0 01.615.597c.124 1.038.208 2.088.25 3.15l-1.689-1.69a.75.75 0 00-1.06 1.061l2.999 3a.75.75 0 001.06 0l3.001-3a.75.75 0 10-1.06-1.06l-1.748 1.747a41.31 41.31 0 00-.264-3.386 2.18 2.18 0 00-1.97-1.913 41.512 41.512 0 00-7.477 0 2.18 2.18 0 00-1.969 1.913 41.16 41.16 0 00-.16 1.61.75.75 0 101.495.12c.041-.52.093-1.038.154-1.552a.68.68 0 01.615-.597A40.012 40.012 0 0110 4.5zM5.281 9.22a.75.75 0 00-1.06 0l-3.001 3a.75.75 0 101.06 1.06l1.748-1.747c.042 1.141.13 2.27.264 3.386a2.18 2.18 0 001.97 1.913 41.533 41.533 0 007.477 0 2.18 2.18 0 001.969-1.913c.064-.534.117-1.071.16-1.61a.75.75 0 10-1.495-.12c-.041.52-.093 1.037-.154 1.552a.68.68 0 01-.615.597 40.013 40.013 0 01-7.208 0 .68.68 0 01-.615-.597 39.785 39.785 0 01-.25-3.15l1.689 1.69a.75.75 0 001.06-1.061l-2.999-3z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 979 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M15.312 11.424a5.5 5.5 0 01-9.201 2.466l-.312-.311h2.433a.75.75 0 000-1.5H3.989a.75.75 0 00-.75.75v4.242a.75.75 0 001.5 0v-2.43l.31.31a7 7 0 0011.712-3.138.75.75 0 00-1.449-.39zm1.23-3.723a.75.75 0 00.219-.53V2.929a.75.75 0 00-1.5 0V5.36l-.31-.31A7 7 0 003.239 8.188a.75.75 0 101.448.389A5.5 5.5 0 0113.89 6.11l.311.31h-2.432a.75.75 0 000 1.5h4.243a.75.75 0 00.53-.219z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 531 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM6.75 9.25a.75.75 0 000 1.5h4.59l-2.1 1.95a.75.75 0 001.02 1.1l3.5-3.25a.75.75 0 000-1.1l-3.5-3.25a.75.75 0 10-1.02 1.1l2.1 1.95H6.75z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 329 B |
|
@ -0,0 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M3 4.25A2.25 2.25 0 015.25 2h5.5A2.25 2.25 0 0113 4.25v2a.75.75 0 01-1.5 0v-2a.75.75 0 00-.75-.75h-5.5a.75.75 0 00-.75.75v11.5c0 .414.336.75.75.75h5.5a.75.75 0 00.75-.75v-2a.75.75 0 011.5 0v2A2.25 2.25 0 0110.75 18h-5.5A2.25 2.25 0 013 15.75V4.25z" clip-rule="evenodd"/>
|
||||
<path fill-rule="evenodd" d="M6 10a.75.75 0 01.75-.75h9.546l-1.048-.943a.75.75 0 111.004-1.114l2.5 2.25a.75.75 0 010 1.114l-2.5 2.25a.75.75 0 11-1.004-1.114l1.048-.943H6.75A.75.75 0 016 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 624 B |
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
|
||||
<path fill-rule="evenodd" d="M3 10a.75.75 0 01.75-.75h10.638L10.23 5.29a.75.75 0 111.04-1.08l5.5 5.25a.75.75 0 010 1.08l-5.5 5.25a.75.75 0 11-1.04-1.08l4.158-3.96H3.75A.75.75 0 013 10z" clip-rule="evenodd"/>
|
||||
</svg>
|
After Width: | Height: | Size: 317 B |