WIP: add css from stasis
This commit is contained in:
parent
d334aaf003
commit
c87a2314c5
@ -50,3 +50,9 @@
|
|||||||
$ docker run --rm -it --init -w /opt -v $PWD:/opt -p 8080:8080 sitegen-openresty
|
$ docker run --rm -it --init -w /opt -v $PWD:/opt -p 8080:8080 sitegen-openresty
|
||||||
|
|
||||||
### visit `localhost:8080` in web browser
|
### visit `localhost:8080` in web browser
|
||||||
|
|
||||||
|
## todo
|
||||||
|
|
||||||
|
* treesitter highlighting for moonscript
|
||||||
|
* penlight library
|
||||||
|
* sitegen plugins
|
||||||
|
734
app.css
Normal file
734
app.css
Normal file
@ -0,0 +1,734 @@
|
|||||||
|
/*@import "tailwindcss/base";*/
|
||||||
|
|
||||||
|
/*@import "tailwindcss/components";*/
|
||||||
|
|
||||||
|
/*@import "tailwindcss/utilities";*/
|
||||||
|
|
||||||
|
/* This file is for your main application CSS */
|
||||||
|
|
||||||
|
/*styles.css*/
|
||||||
|
|
||||||
|
/*tones #ff2a2a*/
|
||||||
|
|
||||||
|
/*ff2a2a*/
|
||||||
|
|
||||||
|
/*ef3535*/
|
||||||
|
|
||||||
|
/*df3f3f*/
|
||||||
|
|
||||||
|
/*cf4a4a*/
|
||||||
|
|
||||||
|
/*bf5555*/
|
||||||
|
|
||||||
|
/*af5f5f*/
|
||||||
|
|
||||||
|
/*9f6a6a*/
|
||||||
|
|
||||||
|
/*8f7575*/
|
||||||
|
|
||||||
|
/*tints*/
|
||||||
|
|
||||||
|
/*.color-1 {color: #ff2a2a;}*/
|
||||||
|
|
||||||
|
/*.color-2 {color: #ff4545;}*/
|
||||||
|
|
||||||
|
/*.color-3 {color: #ff5f5f;}*/
|
||||||
|
|
||||||
|
/*.color-4 {color: #ff7a7a;}*/
|
||||||
|
|
||||||
|
/*.color-5 {color: #ff9595;}*/
|
||||||
|
|
||||||
|
/*.color-6 {color: #ffafaf;}*/
|
||||||
|
|
||||||
|
/*.color-7 {color: #ffcaca;}*/
|
||||||
|
|
||||||
|
/*.color-8 {color: #ffe4e4;}*/
|
||||||
|
|
||||||
|
a[href]:link {
|
||||||
|
color: #ff2a2a;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href]:visited {
|
||||||
|
color: dodgerblue;
|
||||||
|
color: skyblue;
|
||||||
|
color: #FF5733;
|
||||||
|
color: #900C3F;
|
||||||
|
/*tones*/
|
||||||
|
/*color: #ff2a2a;*/
|
||||||
|
/*color: #ef3535;*/
|
||||||
|
/*color: #df3f3f;*/
|
||||||
|
color: #cf4a4a;
|
||||||
|
/*color: #bf5555;*/
|
||||||
|
/*color: #af5f5f;*/
|
||||||
|
/*color: #9f6a6a;*/
|
||||||
|
/*color: #8f7575;*/
|
||||||
|
/*tints*/
|
||||||
|
/*color: #ff2a2a;*/
|
||||||
|
/*color: #ff4545;*/
|
||||||
|
/*color: #ff5f5f;*/
|
||||||
|
/*color: #ff7a7a;*/
|
||||||
|
/*color: #ff9595;*/
|
||||||
|
/*color: #ffafaf;*/
|
||||||
|
/*color: #ffcaca;*/
|
||||||
|
/*color: #ffe4e4;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href]:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
color: lightblue;
|
||||||
|
color: #FF5733;
|
||||||
|
/*tints*/
|
||||||
|
/*color: #ff2a2a;*/
|
||||||
|
/*color: #ff4545;*/
|
||||||
|
/*color: #ff5f5f;*/
|
||||||
|
color: #ff7a7a;
|
||||||
|
/*color: #ff9595;*/
|
||||||
|
/*color: #ffafaf;*/
|
||||||
|
/*color: #ffcaca;*/
|
||||||
|
/*color: #ffe4e4;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
a[href]:active {
|
||||||
|
/*tints*/
|
||||||
|
/*color: #ff2a2a;*/
|
||||||
|
/*color: #ff4545;*/
|
||||||
|
/*color: #ff5f5f;*/
|
||||||
|
/*color: #ff7a7a;*/
|
||||||
|
color: #ff9595;
|
||||||
|
/*color: #ffafaf;*/
|
||||||
|
/*color: #ffcaca;*/
|
||||||
|
/*color: #ffe4e4;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
header a[href]:visited {
|
||||||
|
color: #ff2a2a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*header a[href]:hover {*/
|
||||||
|
|
||||||
|
/* color: #FF5733;*/
|
||||||
|
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
/*header a[href]:active {*/
|
||||||
|
|
||||||
|
/* color: #FFC300;*/
|
||||||
|
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
.app-source-code-link {
|
||||||
|
font-size: smaller;
|
||||||
|
font-weight: normal;
|
||||||
|
margin-left: 0.5em;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font: 0.95em/1.692307em 'Bitter', Georgia, 'Times New Roman', Times, serif;
|
||||||
|
color: #24292e;
|
||||||
|
display: flex;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
max-width: 1160px;
|
||||||
|
flex-flow: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding: 0 1em;
|
||||||
|
text-align: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > dl > dt > a[rel="author"] {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > dl > dd {
|
||||||
|
font-family: Monaco, monospace, Courier, "Courier New";
|
||||||
|
margin: 0;
|
||||||
|
font-size: smaller;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > dl {
|
||||||
|
margin-bottom: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav > ul > li {
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
text-align: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
main * {
|
||||||
|
text-align: left;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
main > div {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
section, h2 {
|
||||||
|
max-width: 650px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section + section {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section:first-child h3 {
|
||||||
|
margin-top: 0.83em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section:last-child {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section > h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section + section > h3 {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section > time {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: smaller;
|
||||||
|
/*color: #99C300;*/
|
||||||
|
/*color: #FFC300;*/
|
||||||
|
/*color: #ffca2a;*/
|
||||||
|
/*color: #b7df3f;*/
|
||||||
|
/*color: #aecf4a;*/
|
||||||
|
/*color: #a5bf55;*/
|
||||||
|
/*color: #9baf5f;*/
|
||||||
|
/*color: #caff2a;*/
|
||||||
|
/*color: #b1df25;*/
|
||||||
|
color: #98bf1f;
|
||||||
|
/*color: #dfb125;*/
|
||||||
|
/*color: #bf981f;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
section p {
|
||||||
|
margin-top: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > * {
|
||||||
|
max-width: 600px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > time {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
margin-bottom: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
section > time, article > time {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
article > h2:first-child {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
article h2, article h3, article h4, article h5 {
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
border: 1px solid slategray;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0 1em;
|
||||||
|
background-color: #ddf0f0;
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: darkslategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info > p:first-child:before {
|
||||||
|
content: "ⓘ";
|
||||||
|
float: left;
|
||||||
|
font-size: xx-large;
|
||||||
|
color: slategray;
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
border: 1px solid orange;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 0 1em;
|
||||||
|
background-color: beige;
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: darkslategray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning > p:first-child:before {
|
||||||
|
content: "⚠";
|
||||||
|
float: left;
|
||||||
|
font-size: xx-large;
|
||||||
|
color: orange;
|
||||||
|
margin-right: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure figcaption {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: aliceblue;
|
||||||
|
padding: 1em;
|
||||||
|
border: 1px solid lightgray;
|
||||||
|
border-radius: 3px;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:not(pre) > code {
|
||||||
|
background-color: rgb(230, 232, 245);
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-filename-label, .filename-for-code-block > p {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-filename-label code, .filename-for-code-block code {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-filename-label + pre,
|
||||||
|
.code-filename-label + div.sourceCode,
|
||||||
|
.filename-for-code-block + pre,
|
||||||
|
.filename-for-code-block + div.sourceCode {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-size: 0.85em;
|
||||||
|
font-family: Monaco, monospace, Courier, "Courier New";
|
||||||
|
}
|
||||||
|
|
||||||
|
li p img {
|
||||||
|
float: left;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
li, p {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
text-align: center;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
border-left: 5px solid #ccc;
|
||||||
|
padding: 0.1em 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer {
|
||||||
|
padding: 1em;
|
||||||
|
font-size: smaller;
|
||||||
|
font-family: sans-serif;
|
||||||
|
margin-top: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
color: lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer ul, nav ul {
|
||||||
|
margin: 0;
|
||||||
|
padding-left: 1em;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-post-link {
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@media (max-width: 1100px) {*/
|
||||||
|
|
||||||
|
footer {
|
||||||
|
flex-basis: 100%;
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 3em;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer ul {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer li, footer ul {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer li::after {
|
||||||
|
content: ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
footer li:last-child::after {
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
/*@media (max-width: 950px) {*/
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style: none;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav li, nav ul {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav li + li {
|
||||||
|
margin-left: 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
header {
|
||||||
|
padding-bottom: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > a[rel="author"] {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section:first-child h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
address {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
header > dl {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
line-height: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*}*/
|
||||||
|
|
||||||
|
table > caption {
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-variant-caps: small-caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*highlighting.css*/
|
||||||
|
|
||||||
|
pre > code.sourceCode {
|
||||||
|
white-space: pre;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code.sourceCode > span {
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 1.25;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code.sourceCode > span:empty {
|
||||||
|
height: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code.sourceCode > span {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sourceCode {
|
||||||
|
margin: 1em auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.sourceCode {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen {
|
||||||
|
div.sourceCode {
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
pre > code.sourceCode {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre > code.sourceCode > span {
|
||||||
|
text-indent: -5em;
|
||||||
|
padding-left: 5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.numberSource code
|
||||||
|
{
|
||||||
|
counter-reset: source-line 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.numberSource code > span
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
left: -4em;
|
||||||
|
counter-increment: source-line;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.numberSource code > span > a:first-child::before
|
||||||
|
{
|
||||||
|
content: counter(source-line);
|
||||||
|
position: relative;
|
||||||
|
left: -1em;
|
||||||
|
text-align: right;
|
||||||
|
vertical-align: baseline;
|
||||||
|
border: none;
|
||||||
|
display: inline-block;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
padding: 0 4px;
|
||||||
|
width: 4em;
|
||||||
|
color: #aaaaaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre.numberSource {
|
||||||
|
margin-left: 3em;
|
||||||
|
border-left: 1px solid #aaaaaa;
|
||||||
|
padding-left: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sourceCode
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen {
|
||||||
|
pre > code.sourceCode > span > a:first-child::before {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
code span.al {
|
||||||
|
color: #ff0000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Alert */
|
||||||
|
|
||||||
|
code span.an {
|
||||||
|
color: #60a0b0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Annotation */
|
||||||
|
|
||||||
|
code span.at {
|
||||||
|
color: #7d9029;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attribute */
|
||||||
|
|
||||||
|
code span.bn {
|
||||||
|
color: #40a070;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BaseN */
|
||||||
|
|
||||||
|
code span.bu {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BuiltIn */
|
||||||
|
|
||||||
|
code span.cf {
|
||||||
|
color: #007020;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ControlFlow */
|
||||||
|
|
||||||
|
code span.ch {
|
||||||
|
color: #4070a0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Char */
|
||||||
|
|
||||||
|
code span.cn {
|
||||||
|
color: #880000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Constant */
|
||||||
|
|
||||||
|
code span.co {
|
||||||
|
color: #60a0b0;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Comment */
|
||||||
|
|
||||||
|
code span.cv {
|
||||||
|
color: #60a0b0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CommentVar */
|
||||||
|
|
||||||
|
code span.do {
|
||||||
|
color: #ba2121;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Documentation */
|
||||||
|
|
||||||
|
code span.dt {
|
||||||
|
color: #902000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DataType */
|
||||||
|
|
||||||
|
code span.dv {
|
||||||
|
color: #40a070;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DecVal */
|
||||||
|
|
||||||
|
code span.er {
|
||||||
|
color: #ff0000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Error */
|
||||||
|
|
||||||
|
code span.ex {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Extension */
|
||||||
|
|
||||||
|
code span.fl {
|
||||||
|
color: #40a070;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Float */
|
||||||
|
|
||||||
|
code span.fu {
|
||||||
|
color: #06287e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Function */
|
||||||
|
|
||||||
|
code span.im {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Import */
|
||||||
|
|
||||||
|
code span.in {
|
||||||
|
color: #60a0b0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Information */
|
||||||
|
|
||||||
|
code span.kw {
|
||||||
|
color: #007020;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Keyword */
|
||||||
|
|
||||||
|
code span.op {
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Operator */
|
||||||
|
|
||||||
|
code span.ot {
|
||||||
|
color: #007020;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other */
|
||||||
|
|
||||||
|
code span.pp {
|
||||||
|
color: #bc7a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Preprocessor */
|
||||||
|
|
||||||
|
code span.sc {
|
||||||
|
color: #4070a0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SpecialChar */
|
||||||
|
|
||||||
|
code span.ss {
|
||||||
|
color: #bb6688;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SpecialString */
|
||||||
|
|
||||||
|
code span.st {
|
||||||
|
color: #4070a0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* String */
|
||||||
|
|
||||||
|
code span.va {
|
||||||
|
color: #19177c;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Variable */
|
||||||
|
|
||||||
|
code span.vs {
|
||||||
|
color: #4070a0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* VerbatimString */
|
||||||
|
|
||||||
|
code span.wa {
|
||||||
|
color: #60a0b0;
|
||||||
|
font-weight: bold;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Warning */
|
89
conf/mime.types
Normal file
89
conf/mime.types
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
|
||||||
|
types {
|
||||||
|
text/html html htm shtml;
|
||||||
|
text/css css;
|
||||||
|
text/xml xml;
|
||||||
|
image/gif gif;
|
||||||
|
image/jpeg jpeg jpg;
|
||||||
|
application/javascript js;
|
||||||
|
application/atom+xml atom;
|
||||||
|
application/rss+xml rss;
|
||||||
|
|
||||||
|
text/mathml mml;
|
||||||
|
text/plain txt;
|
||||||
|
text/vnd.sun.j2me.app-descriptor jad;
|
||||||
|
text/vnd.wap.wml wml;
|
||||||
|
text/x-component htc;
|
||||||
|
|
||||||
|
image/png png;
|
||||||
|
image/tiff tif tiff;
|
||||||
|
image/vnd.wap.wbmp wbmp;
|
||||||
|
image/x-icon ico;
|
||||||
|
image/x-jng jng;
|
||||||
|
image/x-ms-bmp bmp;
|
||||||
|
image/svg+xml svg svgz;
|
||||||
|
image/webp webp;
|
||||||
|
|
||||||
|
application/font-woff woff;
|
||||||
|
application/java-archive jar war ear;
|
||||||
|
application/json json;
|
||||||
|
application/mac-binhex40 hqx;
|
||||||
|
application/msword doc;
|
||||||
|
application/pdf pdf;
|
||||||
|
application/postscript ps eps ai;
|
||||||
|
application/rtf rtf;
|
||||||
|
application/vnd.apple.mpegurl m3u8;
|
||||||
|
application/vnd.ms-excel xls;
|
||||||
|
application/vnd.ms-fontobject eot;
|
||||||
|
application/vnd.ms-powerpoint ppt;
|
||||||
|
application/vnd.wap.wmlc wmlc;
|
||||||
|
application/vnd.google-earth.kml+xml kml;
|
||||||
|
application/vnd.google-earth.kmz kmz;
|
||||||
|
application/x-7z-compressed 7z;
|
||||||
|
application/x-cocoa cco;
|
||||||
|
application/x-java-archive-diff jardiff;
|
||||||
|
application/x-java-jnlp-file jnlp;
|
||||||
|
application/x-makeself run;
|
||||||
|
application/x-perl pl pm;
|
||||||
|
application/x-pilot prc pdb;
|
||||||
|
application/x-rar-compressed rar;
|
||||||
|
application/x-redhat-package-manager rpm;
|
||||||
|
application/x-sea sea;
|
||||||
|
application/x-shockwave-flash swf;
|
||||||
|
application/x-stuffit sit;
|
||||||
|
application/x-tcl tcl tk;
|
||||||
|
application/x-x509-ca-cert der pem crt;
|
||||||
|
application/x-xpinstall xpi;
|
||||||
|
application/xhtml+xml xhtml;
|
||||||
|
application/xspf+xml xspf;
|
||||||
|
application/zip zip;
|
||||||
|
|
||||||
|
application/octet-stream bin exe dll;
|
||||||
|
application/octet-stream deb;
|
||||||
|
application/octet-stream dmg;
|
||||||
|
application/octet-stream iso img;
|
||||||
|
application/octet-stream msi msp msm;
|
||||||
|
|
||||||
|
application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
|
||||||
|
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
|
||||||
|
application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
|
||||||
|
|
||||||
|
audio/midi mid midi kar;
|
||||||
|
audio/mpeg mp3;
|
||||||
|
audio/ogg ogg;
|
||||||
|
audio/x-m4a m4a;
|
||||||
|
audio/x-realaudio ra;
|
||||||
|
|
||||||
|
video/3gpp 3gpp 3gp;
|
||||||
|
video/mp2t ts;
|
||||||
|
video/mp4 mp4;
|
||||||
|
video/mpeg mpeg mpg;
|
||||||
|
video/quicktime mov;
|
||||||
|
video/webm webm;
|
||||||
|
video/x-flv flv;
|
||||||
|
video/x-m4v m4v;
|
||||||
|
video/x-mng mng;
|
||||||
|
video/x-ms-asf asx asf;
|
||||||
|
video/x-ms-wmv wmv;
|
||||||
|
video/x-msvideo avi;
|
||||||
|
}
|
@ -5,14 +5,21 @@ events {
|
|||||||
}
|
}
|
||||||
http {
|
http {
|
||||||
server {
|
server {
|
||||||
root /opt/www;
|
|
||||||
listen 8080;
|
listen 8080;
|
||||||
|
|
||||||
|
include mime.types;
|
||||||
|
charset utf-8;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
default_type text/html;
|
default_type text/html;
|
||||||
# content_by_lua_block {
|
# content_by_lua_block {
|
||||||
# ngx.say("<p>hello, world</p>")
|
# ngx.say("<p>hello, world</p>")
|
||||||
# }
|
# }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /css {
|
||||||
|
expires 1h;
|
||||||
|
alias css;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,132 @@
|
|||||||
|
## Introduction
|
||||||
|
|
||||||
|
We wish to print a list of all the files in a directory, ignoring files beginning with certain characters, sorted alphabetically, with the directories last.
|
||||||
|
|
||||||
|
## Finding the files
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
Finds all files in the `path` directory recursively, ignoring any files or directories that start with any of the characters in the `@starts_with` module attribute.
|
||||||
|
|
||||||
|
```
|
||||||
|
defmodule Files do
|
||||||
|
@starts_with [".", "_"]
|
||||||
|
|
||||||
|
def find(path \\ "."), do: find(path, list_contents(path))
|
||||||
|
|
||||||
|
defp find(dir, files) do
|
||||||
|
Enum.reduce(files, {dir, []}, fn file, {path, contents} ->
|
||||||
|
{path, path |> Path.join(file) |> update_contents(file, contents)}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp list_contents(path), do: path |> File.ls!() |> ignore()
|
||||||
|
|
||||||
|
defp update_contents(path, file, contents) do
|
||||||
|
cond do
|
||||||
|
File.regular?(path) -> [file | contents]
|
||||||
|
File.dir?(path) -> [find(path) | contents]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp ignore(filenames) do
|
||||||
|
Enum.reject(filenames, &(String.first(&1) in @starts_with))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
The data structure holding the results of the file search.
|
||||||
|
|
||||||
|
```
|
||||||
|
iex(1)> directory_tree = Files.find("hello")
|
||||||
|
{"hello",
|
||||||
|
[
|
||||||
|
"README.md",
|
||||||
|
{"hello/test",
|
||||||
|
[
|
||||||
|
{"hello/test/support", ["conn_case.ex"]},
|
||||||
|
"test_helper.exs",
|
||||||
|
{"hello/test/hello_web",
|
||||||
|
[{"hello/test/hello_web/controllers", ["error_json_test.exs"]}]}
|
||||||
|
]},
|
||||||
|
{"hello/lib",
|
||||||
|
[
|
||||||
|
"hello.ex",
|
||||||
|
{"hello/lib/hello", ["application.ex"]},
|
||||||
|
"hello_web.ex",
|
||||||
|
{"hello/lib/hello_web",
|
||||||
|
[
|
||||||
|
{"hello/lib/hello_web/controllers", ["error_json.ex"]},
|
||||||
|
"telemetry.ex",
|
||||||
|
"router.ex",
|
||||||
|
"endpoint.ex"
|
||||||
|
]}
|
||||||
|
]},
|
||||||
|
{"hello/priv", [{"hello/priv/static", ["robots.txt", "favicon.ico"]}]},
|
||||||
|
{"hello/config",
|
||||||
|
["config.exs", "dev.exs", "test.exs", "prod.exs", "runtime.exs"]},
|
||||||
|
"mix.exs"
|
||||||
|
]}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sorting and printing
|
||||||
|
|
||||||
|
### Code
|
||||||
|
|
||||||
|
Sort alphabetically, with directories last. Downcase before comparing strings.
|
||||||
|
|
||||||
|
```
|
||||||
|
defmodule Paths do
|
||||||
|
def puts(dir_tree), do: dir_tree |> print() |> Enum.join("\n") |> IO.puts()
|
||||||
|
|
||||||
|
defp print({path, contents}), do: path |> list(contents) |> List.flatten()
|
||||||
|
|
||||||
|
defp list(path, contents) do
|
||||||
|
contents |> Enum.sort(&alpha_asc_dir_last/2) |> Enum.map(&make_path(&1, path))
|
||||||
|
end
|
||||||
|
|
||||||
|
defp alpha_asc_dir_last({a, _}, {b, _}), do: fmt(a) < fmt(b)
|
||||||
|
defp alpha_asc_dir_last({_, _}, _), do: false
|
||||||
|
defp alpha_asc_dir_last(_, {_, _}), do: true
|
||||||
|
defp alpha_asc_dir_last(a, b), do: fmt(a) < fmt(b)
|
||||||
|
|
||||||
|
defp make_path(filename, path) when is_binary(filename), do: Path.join(path, filename)
|
||||||
|
defp make_path({path, contents}, _), do: list(path, contents)
|
||||||
|
|
||||||
|
defp fmt(f), do: String.downcase(f)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output
|
||||||
|
|
||||||
|
Print all the files sorted.
|
||||||
|
|
||||||
|
```
|
||||||
|
iex(2)> Paths.puts(directory_tree)
|
||||||
|
hello/mix.exs
|
||||||
|
hello/README.md
|
||||||
|
hello/config/config.exs
|
||||||
|
hello/config/dev.exs
|
||||||
|
hello/config/prod.exs
|
||||||
|
hello/config/runtime.exs
|
||||||
|
hello/config/test.exs
|
||||||
|
hello/lib/hello.ex
|
||||||
|
hello/lib/hello_web.ex
|
||||||
|
hello/lib/hello/application.ex
|
||||||
|
hello/lib/hello_web/endpoint.ex
|
||||||
|
hello/lib/hello_web/router.ex
|
||||||
|
hello/lib/hello_web/telemetry.ex
|
||||||
|
hello/lib/hello_web/controllers/error_json.ex
|
||||||
|
hello/priv/static/favicon.ico
|
||||||
|
hello/priv/static/robots.txt
|
||||||
|
hello/test/test_helper.exs
|
||||||
|
hello/test/hello_web/controllers/error_json_test.exs
|
||||||
|
hello/test/support/conn_case.ex
|
||||||
|
:ok
|
||||||
|
```
|
||||||
|
|
||||||
|
## Conclusion
|
||||||
|
|
||||||
|
Trying to do this without recursion made it difficult to sort directories first.
|
@ -1 +0,0 @@
|
|||||||
# post 1
|
|
@ -1 +0,0 @@
|
|||||||
# post 2
|
|
4
index.md
4
index.md
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
date: "Thu May 08 2025 19:41:30.000000000"
|
date: "Thu May 08 2025 19:41:30.000000000"
|
||||||
title: "index"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Hello world!
|
## Posts
|
||||||
|
|
||||||
|
- [recursive]($root/posts/2023-08-03-recursively-list-all-files-in-a-directory-with-elixir.html)
|
||||||
|
@ -18,5 +18,10 @@ posts = (path=".") ->
|
|||||||
|
|
||||||
sitegen.create =>
|
sitegen.create =>
|
||||||
@title = "Hello World"
|
@title = "Hello World"
|
||||||
|
@app_name = "stasis"
|
||||||
|
@version = "0.2.12"
|
||||||
add "index.md"
|
add "index.md"
|
||||||
add path, target: target for path, target in pairs posts "docs"
|
add path, target: target for path, target in pairs posts "docs"
|
||||||
|
|
||||||
|
css = require("sitegen.tools").system_command "cat < %s > %s", "css"
|
||||||
|
build css, "index.css"
|
||||||
|
10
templates/app.html.heex
Normal file
10
templates/app.html.heex
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<section>
|
||||||
|
<h2>Hi, I'm Catalin Mititiuc</h2>
|
||||||
|
<p>
|
||||||
|
Experienced in full-stack web development with Elixir and JavaScript.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>Hiring? Reach me by <a href="mailto:webdevcat@proton.me">email</a>.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<%= @inner_content %>
|
9
templates/blog.html.heex
Normal file
9
templates/blog.html.heex
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<section>
|
||||||
|
<h2><a href="/posts/">Web Log</a></h2>
|
||||||
|
<p>Elixir, JavaScript, SVG, Containers, Git, Linux</p>
|
||||||
|
<p>
|
||||||
|
Questions, comments, feedback? <a href="mailto:webdevcat@proton.me">Contact the author</a>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<%= @inner_content %>
|
40
templates/home.html.heex
Normal file
40
templates/home.html.heex
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<h2>Wares</h2>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>
|
||||||
|
<a href="/apps/btroops/">BTroops</a>
|
||||||
|
<a class="app-source-code-link" href="/git/btroops/">
|
||||||
|
View Source Code
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>A virtual implementation of FASA's 1989 wargame, Battletroops, for
|
||||||
|
the browser. Suitable for single-player solo play or two-player hotseat.</p>
|
||||||
|
<p>Runs entirely on the client after the initial download from the
|
||||||
|
server. Built with HTML5, SVG and JavaScript. Uses Node.js, Esbuild and
|
||||||
|
Docker for building and running dev/test servers.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h3>
|
||||||
|
<a href="https://hex.pm/packages/pandoc">Pandoc</a>
|
||||||
|
<a class="app-source-code-link" href="/git/pandoc/">
|
||||||
|
View Source Code
|
||||||
|
</a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
A Hex package for installing and invoking <a href="https://pandoc.org/">Pandoc</a>
|
||||||
|
("a universal document converter"), fashioned after Phoenix's
|
||||||
|
<a href="https://hex.pm/packages/esbuild">Esbuild</a>
|
||||||
|
and <a href="https://hex.pm/packages/tailwind">Tailwind</a>
|
||||||
|
packages. Also included is a file system watcher, so that converted
|
||||||
|
documents are updated as soon as content changes are saved.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<%= StasisWeb.PostHTML.index(%{posts: @posts}) %>
|
||||||
|
|
||||||
|
<h4 style="text-align: center;">
|
||||||
|
<.link href={~p"/posts"} method="get">View more posts</.link>
|
||||||
|
</h4>
|
33
templates/index.html
Normal file
33
templates/index.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" style="scrollbar-gutter:stable;">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>$title</title>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
id="font-bitter-css"
|
||||||
|
href="//fonts.googleapis.com/css?family=Bitter:400,700"
|
||||||
|
type="text/css"
|
||||||
|
media="screen"
|
||||||
|
/>
|
||||||
|
<link rel="stylesheet" href="$root/app.css" />
|
||||||
|
</head>
|
||||||
|
<body class="bg-white">
|
||||||
|
<header>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<h1><a href="/">Web Dev Solutions</a></h1>
|
||||||
|
<h3 style="text-align: left">Catalin Mititiuc</h3>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
$body
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>100% Human Made, No AI Used</p>
|
||||||
|
<p>$app_name $version</p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
76
templates/root.html.heex
Normal file
76
templates/root.html.heex
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" style="scrollbar-gutter:stable;">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="csrf-token" content={get_csrf_token()} />
|
||||||
|
<.live_title suffix=" · Catalin Mititiuc">
|
||||||
|
<%= assigns[:page_title] || "WebDevCat.me" %>
|
||||||
|
</.live_title>
|
||||||
|
<link
|
||||||
|
rel="stylesheet"
|
||||||
|
id="font-bitter-css"
|
||||||
|
href="//fonts.googleapis.com/css?family=Bitter:400,700"
|
||||||
|
type="text/css"
|
||||||
|
media="screen"
|
||||||
|
/>
|
||||||
|
<link phx-track-static rel="stylesheet" href={~p"/assets/app.css"} />
|
||||||
|
<%= if assigns[:cgit] do %>
|
||||||
|
<link phx-track-static rel="stylesheet" href={~p"/assets/cgit.css"} />
|
||||||
|
<style>
|
||||||
|
article > * { max-width: unset; }
|
||||||
|
div#cgit table.list {
|
||||||
|
table-layout: auto;
|
||||||
|
width: 100%;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
div#cgit div.content {
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
div#cgit table.tabs {
|
||||||
|
table-layout: auto;
|
||||||
|
width: 100%;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
div#cgit table.blob {
|
||||||
|
table-layout: auto;
|
||||||
|
width: 100%;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
div#cgit table.tabs {
|
||||||
|
table-layout: auto;
|
||||||
|
width: 100%;
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
td.linenumbers { width: 1px; }
|
||||||
|
td.lines { max-width: 1px; overflow: hidden; }
|
||||||
|
|
||||||
|
td.linenumbers pre, td.lines pre {
|
||||||
|
line-height: 1.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre { overflow-x: scroll; overflow-y: hidden; }
|
||||||
|
code { font-size: unset; }
|
||||||
|
</style>
|
||||||
|
<% end %>
|
||||||
|
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-white">
|
||||||
|
<header>
|
||||||
|
<div style="display: inline-block;">
|
||||||
|
<h1><a href="/">Web Dev Solutions</a></h1>
|
||||||
|
<h3 style="text-align: left">Catalin Mititiuc</h3>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<%= @inner_content %>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>100% Human Made, No AI Used</p>
|
||||||
|
<p><%= app_name() %> <%= version() %></p>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
x
Reference in New Issue
Block a user