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
|
||||
|
||||
### 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 {
|
||||
server {
|
||||
root /opt/www;
|
||||
listen 8080;
|
||||
|
||||
include mime.types;
|
||||
charset utf-8;
|
||||
|
||||
location / {
|
||||
default_type text/html;
|
||||
# content_by_lua_block {
|
||||
# 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"
|
||||
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 =>
|
||||
@title = "Hello World"
|
||||
@app_name = "stasis"
|
||||
@version = "0.2.12"
|
||||
add "index.md"
|
||||
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