Compare commits

...

199 Commits

Author SHA1 Message Date
9d9fa13340 Clean up some 2026-02-11 10:13:22 -08:00
36953062d0 Update todo list 2026-02-11 09:59:09 -08:00
5a99a01eed Refactor timeouts 2026-02-10 19:34:54 -08:00
09bee9627c Fix recoil 2026-02-10 19:29:30 -08:00
96153b9a74 Shot ships fall with gravity 2026-02-10 19:27:50 -08:00
22ab464f5d Refactor shooting and drawing 2026-02-10 19:05:27 -08:00
b54853559f WIP: toggle gravity effect per ship 2026-02-10 16:08:18 -08:00
af8e222045 WIP: move multiple ships 2026-02-10 16:01:34 -08:00
7f07c94c82 Add another ship 2026-02-07 14:38:27 -08:00
94df5140f8 Add cannon recoil animation 2026-02-06 14:34:18 -08:00
df6cf1f75c Update ship appearance 2026-02-06 13:36:14 -08:00
0d63f87e39 Update todo list 2026-02-06 13:09:50 -08:00
3bb5536820 Add recoil velocity 2026-02-06 13:06:46 -08:00
340b30c8dc Handle multiple edge collision in a buggy way 2026-02-06 12:55:08 -08:00
4f9db0a940 Fix cannon length 2026-02-05 14:54:51 -08:00
c783394d01 Increase ship radius? 2026-02-05 14:50:45 -08:00
a13a03e031 Add todo list 2026-02-05 13:37:36 -08:00
3194245309 Move drawing the shot out of the Shoot system 2026-02-05 13:21:57 -08:00
6074b36c99 Remove unused function 2026-02-05 11:49:33 -08:00
d278da060b Move shooting into a system 2026-02-05 11:48:11 -08:00
418fd716b0 Make gun rotation a system 2026-02-05 11:17:06 -08:00
c708dadde0 Move function into Move object 2026-02-05 10:21:50 -08:00
70f958606d Clean up 2026-02-05 10:11:02 -08:00
424cb0f150 Remove unused duplicate functions 2026-02-04 13:49:12 -08:00
d89909e7bf Organize wall elements 2026-02-04 13:05:26 -08:00
93937df1fd Remove idea 2026-02-04 12:53:16 -08:00
6d7214dd46 Comment out all remaining console messages
search and replace with Vim command `:%s/console.log/\/\/ console.log/`
2026-02-04 12:44:40 -08:00
66a044cd2a Remove commented-out console messages
search and replace with Vim command `:%s/\n.*\/\/ console.log.*//`
2026-02-04 12:41:41 -08:00
52e7fd9f9b Calculate reflection using vectors instead of functions? 2026-02-04 10:19:04 -08:00
fae1fd255f Place contact point just outside wall shape 2026-02-02 14:27:48 -08:00
93157f17dd WIP: don't go through walls? 2026-02-02 10:27:19 -08:00
965ed86ed6 WIP: try to fix issue with isAcute function 2026-01-31 11:34:44 -08:00
478c90e398 Something is off in my vector calculations 2026-01-30 13:45:20 -08:00
89cf20e35a WIP: more rounding 2026-01-30 13:25:51 -08:00
d2a8758fb8 WIP: rounding position values 2026-01-30 10:55:07 -08:00
8198fc7b63 WIP: slide along edge but still fall through sometimes 2026-01-26 16:28:10 -08:00
0b6f7a55c0 Clean up 2026-01-26 16:02:23 -08:00
de0052aa0a Think I got it 2026-01-26 14:51:25 -08:00
6f580b2b77 WIP: almost got vector calc 2026-01-26 13:36:23 -08:00
5bb861c376 WIP: Bouncing working but still not perfect 2026-01-24 13:19:43 -08:00
ccc6dc1335 WIP: bounce off corners 2026-01-24 12:57:58 -08:00
853728624a Refactor 2026-01-23 18:22:05 -08:00
435eb0b128 Pull away from contacted walls 2026-01-23 16:20:04 -08:00
7408005ed2 Clean up 2026-01-23 15:29:49 -08:00
aaff3571af Clean up Move.update() 2026-01-23 15:08:37 -08:00
176fd98cb5 Remove unnecessary conditional branches 2026-01-23 14:58:38 -08:00
e1cfff39f0 Find the bounce vector 2026-01-23 14:48:28 -08:00
55f6328d3f WIP: bounce off walls 2026-01-22 13:26:34 -08:00
b509ba12ea WIP: bounce off walls 2026-01-22 12:30:23 -08:00
4b692194ae WIP: figure out normal vector but i don't th ink i need to 2026-01-21 19:18:47 -08:00
112c100057 WIP: slide along wall on collision 2026-01-21 14:16:34 -08:00
20bcd976a8 WIP: handle vertical and horizontal walls 2026-01-20 16:59:04 -08:00
2e17234daf WIP: Velocity while in contact with edge 2026-01-20 16:46:10 -08:00
ac9684f4cf WIP: Velocity while in contact with edge 2026-01-20 16:27:57 -08:00
c6ed409915 WIP: ECS 2026-01-19 14:28:09 -08:00
00f2243f03 WIP 2026-01-19 13:06:59 -08:00
616c8184d0 Add limit for angular velocity 2026-01-17 15:23:59 -08:00
d779f802a6 Rotate gun with torque and angular acceleration/velocity 2026-01-17 13:25:00 -08:00
12d9d8ae95 Add gravity 2026-01-17 12:22:13 -08:00
b68f63b379 Clean up 2026-01-17 10:20:32 -08:00
0fad07d341 Remove unused function 2026-01-17 10:01:13 -08:00
f0ddd4e13a Remove unused function 2026-01-17 09:59:43 -08:00
bbb6cd2c07 Update todo list 2026-01-17 09:33:06 -08:00
965287bcf4 WIP: bullets hit walls 2026-01-17 09:16:44 -08:00
e027291ec8 Fast bullets 2026-01-16 16:56:55 -08:00
ca9ceebd64 WIP: landing 2026-01-10 12:20:00 -08:00
50a851eb2f WIP: adjusting edge collision distance 2026-01-09 10:38:32 -08:00
c250275b1d Revert "WIP: landing"
This reverts commit c8d17b7d46.
2026-01-08 12:40:11 -08:00
c8d17b7d46 WIP: landing 2026-01-08 12:24:18 -08:00
0e4da0fc67 Set indics back to default on reset 2026-01-08 11:11:36 -08:00
da2b1d9a6f WIP: on landing; on collision, color only local wall 2026-01-08 11:05:20 -08:00
4fd9688d53 Remove unused variables 2026-01-08 10:12:52 -08:00
69a0a1dcdd Refactor map struct 2026-01-08 10:10:36 -08:00
c8b1d9c8f6 Clean up 2026-01-08 09:19:10 -08:00
ed83435218 Clean up ship update function 2026-01-07 18:37:50 -08:00
3fa1e8f722 Fix indent 2026-01-07 18:13:43 -08:00
da1bebe4f2 Rename variable 2026-01-07 18:06:54 -08:00
b81f0a8565 Refactor 2026-01-07 15:39:27 -08:00
b9884ba077 WIP 2026-01-07 15:27:51 -08:00
d17d0f0a08 Refactor function 2026-01-07 13:33:22 -08:00
625cae288c Clean up 2026-01-07 13:24:43 -08:00
5c5c76f9a1 Clean up 2026-01-07 12:58:06 -08:00
e9a86c532e Clean up 2026-01-05 10:00:15 -08:00
2c89910ee8 Clean up 2026-01-05 09:38:45 -08:00
1de687b3f1 Refactor edge collision detect function 2026-01-05 09:22:36 -08:00
d9ab0fa1fd Fix bound s between 0 and 1 2026-01-05 09:05:30 -08:00
b3f6d79c01 edgeCollisionPosition already accounts for the ship radius 2026-01-04 23:23:53 -08:00
df2eb64ed5 WIP: edge collision position 2026-01-04 23:15:59 -08:00
2f2a82c46f Fix edges facing ship calc 2026-01-04 18:50:17 -08:00
607486d308 WIP: What is s and t? swapping them seems to work 2026-01-04 17:47:14 -08:00
d6dddc25db WIP: edge segments 2026-01-04 16:52:48 -08:00
a0f580da95 WIP: Add edge collision back 2026-01-04 11:01:01 -08:00
f3db10ac68 Refactor 2026-01-04 10:21:49 -08:00
406c5d1357 Simplify 2026-01-03 16:23:43 -08:00
8db51f8870 Refactor 2026-01-03 13:53:05 -08:00
607eaa187e Fix s and t calculations 2026-01-03 13:34:12 -08:00
0868c953a3 Corner collisions 2026-01-03 12:03:59 -08:00
d45575db7c WIP: forward collision points 2026-01-02 09:31:24 -08:00
b9b744d10f WIP: perpendicular line 2026-01-01 13:46:29 -08:00
c4c0fdd86d WIP: corner collision position 2025-12-31 15:06:22 -08:00
65c4c69f21 WIP: collision corners 2025-12-31 13:12:26 -08:00
c4c8667d4f WIP: collision corners 2025-12-31 12:03:02 -08:00
08c71c05e6 Land on legs 2025-12-29 16:11:43 -08:00
6723e5f5af WIP: land with gear down 2025-12-29 14:30:41 -08:00
109d1aa6fe WIP: gear down with G key 2025-12-29 09:07:41 -08:00
2d72c7f83e WIP: land 2025-12-28 16:28:04 -08:00
e1e2c479af Clean up line intersection function 2025-12-28 14:35:39 -08:00
e8cc4e5241 Clean up 2025-12-28 14:23:22 -08:00
4903812ca1 Handle horizontal and vertical bases 2025-12-28 14:16:25 -08:00
1ab48b58c3 WIP: some cleanup 2025-12-28 13:27:21 -08:00
38c01d27bf WIP: place ship in final collision position 2025-12-28 13:18:48 -08:00
790c267957 WIP: found collision position 2025-12-28 11:38:14 -08:00
bb193630b9 WIP 2025-12-26 21:47:45 -08:00
46167340be WIP: add a circle to the end of the line 2025-12-26 16:40:44 -08:00
b836b1f92b WIP: draw normal lines 2025-12-26 15:13:44 -08:00
b8df14625c WIP: position touching on collision 2025-12-26 12:03:41 -08:00
c9b7c62365 WIP: don't overlap wall on collision 2025-12-26 11:20:29 -08:00
d75c8f1b0f WIP: position after a collision 2025-12-25 20:37:59 -08:00
d13392fef6 WIP: altitude foot point coords 2025-12-25 19:16:01 -08:00
722e8172ab Land 2025-12-25 16:57:10 -08:00
d732fe0bf1 WIP: landing 2025-12-25 10:01:48 -08:00
63e9c45490 WIP: landing 2025-12-25 08:59:53 -08:00
be61acb030 Light up bg on collision 2025-12-24 09:17:41 -08:00
803402beef Update todos 2025-12-24 09:11:02 -08:00
1fd87f8351 Add inverse walls 2025-12-23 17:34:37 -08:00
b6bc696823 Inverse? 2025-12-23 16:41:50 -08:00
d65e5c2b34 Add R key to restart 2025-12-22 15:05:14 -08:00
f7984595cc Add a 3-wall map 2025-12-21 16:55:33 -08:00
32c1d0e56d Pull collection out of function 2025-12-21 16:30:35 -08:00
d0369ca229 Rename some function params for clarity 2025-12-21 16:21:31 -08:00
19a7a26f1b Don't check corners if edge collision, and vise versa 2025-12-21 16:08:53 -08:00
962e1e4094 Refactor 2025-12-21 15:56:09 -08:00
1a7d6233d8 Fix corner collision detection 2025-12-21 15:21:02 -08:00
60ac7f137b Add additional maps 2025-12-21 14:06:07 -08:00
5b594d369b Add additional walls 2025-12-21 13:42:00 -08:00
5868ef2b24 WIP: multiple walls 2025-12-21 12:54:01 -08:00
2c2226d09f Add pointermove event to print pointer coordinates 2025-12-21 10:30:05 -08:00
1c2f35c87b Clean up 2025-12-21 09:15:24 -08:00
a6fde9e567 Fix cannon rotation 2025-12-21 08:47:38 -08:00
eb9c805786 Simplify collision triangle update function 2025-12-20 15:35:20 -08:00
8f963ab98c Remove unneeded variable 2025-12-20 15:23:44 -08:00
5089a30a3b Add missing call to update collision triangles 2025-12-20 15:19:30 -08:00
e7f098dedf Rename variable 2025-12-20 15:13:12 -08:00
273ed43a51 Refactor 2025-12-20 15:06:16 -08:00
f6974d43f4 Refactor long line 2025-12-20 14:29:13 -08:00
95c45ac7c6 Refactor to find starting edges dynamically 2025-12-20 14:20:34 -08:00
6d7669ac10 Stop reading keys after collisions until a keyup event 2025-12-20 13:12:56 -08:00
5d02620b55 Add a toggle for drawing collision lines 2025-12-20 12:58:57 -08:00
a8f9cce90e Restart after crashing with a keydown event 2025-12-20 12:54:13 -08:00
50a20982a4 Move collision detection code into its own function 2025-12-20 08:40:41 -08:00
1f782f75aa Clean up some code 2025-12-20 08:25:02 -08:00
f9a191048a Stop when all edges have been mapped 2025-12-19 19:27:59 -08:00
fc5a1155dd Remove viewed edges 2025-12-19 18:18:10 -08:00
f3a702cce0 Draw edges 2025-12-19 17:24:16 -08:00
598ecde00e Restart if ship touches wall 2025-12-19 16:48:41 -08:00
fcbae33d51 Only render acute triangles 2025-12-19 14:50:09 -08:00
7b63f0524c Stop bullets when they hit a wall 2025-12-19 13:20:49 -08:00
5a5b4e9272 Modify terrain and remove buttons 2025-12-19 13:05:58 -08:00
8705b5779d Add side collision detection 2025-12-19 12:28:48 -08:00
8b89673b6f Detect corner collisions 2025-12-18 18:08:53 -08:00
29588b36d4 Simplify code 2025-12-18 15:43:41 -08:00
7ad55c07ae Use a class instead of changing direct styles 2025-12-18 15:32:27 -08:00
c3bd622841 Find determinant 2025-12-18 14:45:45 -08:00
2b6fadab29 Remove lines, add polygons 2025-12-18 14:27:05 -08:00
4a44a21395 Rename tank to ship 2025-12-18 11:07:48 -08:00
660bfba1b9 Refactor updateBullets function to simplify 2025-12-18 11:05:51 -08:00
0282a0b721 Move bullets and lines updates to separate functions 2025-12-18 10:47:46 -08:00
a0c804823c Change terrain shape; clean up some 2025-12-18 10:31:38 -08:00
235ea57e81 Draw lines from corners 2025-12-17 18:32:19 -08:00
9e8987fcc0 WIP: collision detection 2025-12-17 17:52:47 -08:00
0b841d8873 Limit ship max speed 2025-12-17 16:59:48 -08:00
9730ff85fb Add debug info 2025-12-17 16:28:36 -08:00
bf807f9e29 Rename file 2025-12-17 15:56:57 -08:00
264cb1dc81 Add key events for arrow and angle bracket keys 2025-12-17 15:51:56 -08:00
5b3710ac4a Add key events for W, A, S, D, Q, E and Space 2025-12-17 13:50:57 -08:00
138a2122e0 Remove comments 2025-12-17 12:53:23 -08:00
b1fd38196e Make bullets originate from end of cannon 2025-12-17 12:51:01 -08:00
60836c9028 Fire bullets in direction of cannon 2025-12-17 12:37:40 -08:00
43f5fccebf WIP: fire bullets 2025-12-17 12:23:52 -08:00
c33c9ec4bc WIP: bullet 2025-12-15 11:24:13 -08:00
b358c2c0c5 Relable buttons 2025-12-14 22:13:07 -08:00
58952cfa88 Add rotating gun 2025-12-14 21:58:14 -08:00
d4e1bf5b9e Add friction 2025-12-13 22:50:42 -08:00
6418c10415 Re-lable buttons 2025-12-13 22:03:47 -08:00
d2163d060b Float around 2025-12-13 22:02:11 -08:00
1baf76d901 Fix velocity by making a vector 2025-12-13 19:42:01 -08:00
88241ad705 Add velocity 2025-12-13 19:10:56 -08:00
37f683e9a5 Output fps 2025-12-13 14:12:37 -08:00
b735a6e124 Update README.md 2025-11-25 16:10:46 -08:00
5c74ee4cbe Update base container image from "bookworm" to "trixie" (Debian 13) (#4)
These changes:

- Update base container image from Bookworm to Trixie Debian
- Update Pandoc version
- Add a `make shell` command

Caveats:

- Uses the "bookworm" version of OpenResty until "trixie" is released

Reviewed-on: #4
2025-11-25 23:56:19 +00:00
c0b54ad843 Publish post 'Test nginx Configuration Directives' (#3)
Sitegen had some problems rendering `$host$request_uri` and `$$ct` so I had to make some changes to the Markdown renderer.

Reviewed-on: #3
2025-06-30 22:49:28 +00:00
95e9be6e60 Fix spelling in blurb 2025-06-22 10:34:25 -07:00
aa33976fc8 Add deploy command to Makefile 2025-06-22 10:29:40 -07:00
2ecd7d2d9f Publish post 'Add a Pygments Lexer to Chroma' (#2)
Reviewed-on: #2
2025-06-22 16:56:45 +00:00
7839e30c28 Remove file that doesn't exist 2025-06-21 18:50:52 -07:00
9e3597e781 Use a variable to avoid repetition in Makefile 2025-06-21 18:47:47 -07:00
d5efecb3d5 Fix dev.nginx.conf 2025-06-20 15:18:57 -07:00
eebda46c39 Won't try to copy non-existent stylesheet 2025-06-20 15:12:20 -07:00
0513fd5c21 Edit README 2025-06-20 15:11:06 -07:00
16 changed files with 2967 additions and 41 deletions

View File

@@ -1,15 +1,64 @@
FROM openresty/openresty:bookworm-buildpack
FROM buildpack-deps:trixie
WORKDIR /opt/app
ARG version=3.7.0.1
ARG version=3.8.2.1
ARG pkgname=pandoc-$version-1-amd64.deb
ARG pkgurl=https://github.com/jgm/pandoc/releases/download/$version/$pkgname
ARG RESTY_DEB_FLAVOR=""
ARG RESTY_DEB_VERSION="=1.27.1.2-1~bookworm1"
ARG RESTY_LUAROCKS_VERSION="3.12.2"
RUN apt-get update && apt-get install -y \
python3-pygments lua-inotify wget && \
wget -q -O $pkgname $pkgurl && dpkg -i $pkgname && rm $pkgname
RUN wget -qO - https://openresty.org/package/pubkey.gpg | gpg --dearmor > /etc/apt/trusted.gpg.d/openresty-keyring.gpg \
&& chown root:root /etc/apt/trusted.gpg.d/openresty-keyring.gpg \
&& chmod ugo+r /etc/apt/trusted.gpg.d/openresty-keyring.gpg \
&& chmod go-w /etc/apt/trusted.gpg.d/openresty-keyring.gpg \
&& echo "\nTypes: deb\nURIs: https://openresty.org/package/debian\nSuites: bookworm\nComponents: openresty\nEnabled: yes\nSigned-By: /etc/apt/trusted.gpg.d/openresty-keyring.gpg" >> /etc/apt/sources.list.d/debian.sources \
&& DEBIAN_FRONTEND=noninteractive apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
openresty${RESTY_DEB_FLAVOR}${RESTY_DEB_VERSION} \
openresty-resty${RESTY_DEB_FLAVOR}${RESTY_DEB_VERSION} \
openresty-opm${RESTY_DEB_FLAVOR}${RESTY_DEB_VERSION} \
openresty-openssl3${RESTY_DEB_FLAVOR}-dev \
openresty-pcre2${RESTY_DEB_FLAVOR}-dev \
openresty-zlib${RESTY_DEB_FLAVOR}-dev \
&& mkdir -p /var/run/openresty \
&& ln -sf /dev/stdout /usr/local/openresty${RESTY_DEB_FLAVOR}/nginx/logs/access.log \
&& ln -sf /dev/stderr /usr/local/openresty${RESTY_DEB_FLAVOR}/nginx/logs/error.log
# Install LuaRocks
RUN curl -fSL https://luarocks.github.io/luarocks/releases/luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz -o luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
&& tar xzf luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz \
&& cd luarocks-${RESTY_LUAROCKS_VERSION} \
&& mkdir -p /usr/local/openresty/luajit \
&& ./configure \
--prefix=/usr/local/openresty/luajit \
--with-lua=/usr/local/openresty/luajit \
--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1 \
&& make build \
&& make install \
&& cd /tmp \
&& rm -rf luarocks-${RESTY_LUAROCKS_VERSION} luarocks-${RESTY_LUAROCKS_VERSION}.tar.gz
# Add additional binaries into PATH for convenience
ENV PATH="$PATH:/usr/local/openresty${RESTY_DEB_FLAVOR}/luajit/bin:/usr/local/openresty${RESTY_DEB_FLAVOR}/nginx/sbin:/usr/local/openresty${RESTY_DEB_FLAVOR}/bin"
# Add LuaRocks paths
# If OpenResty changes, these may need updating:
# /usr/local/openresty/bin/resty -e 'print(package.path)'
# /usr/local/openresty/bin/resty -e 'print(package.cpath)'
ENV LUA_PATH="/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua"
ENV LUA_CPATH="/usr/local/openresty/site/lualib/?.so;/usr/local/openresty/lualib/?.so;./?.so;/usr/local/lib/lua/5.1/?.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/loadall.so;/usr/local/openresty/luajit/lib/lua/5.1/?.so"
WORKDIR /opt/app
# Copy nginx configuration files
COPY nginx.conf /usr/local/openresty${RESTY_DEB_FLAVOR}/nginx/conf/nginx.conf
COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf
RUN luarocks install sitegen
# needed for sitegen watcher
@@ -35,3 +84,8 @@ RUN mkdir -p /var/www/certs/webdevcat.me \
-addext "subjectAltName=DNS:webdevcat.me,DNS:git.webdevcat.me,DNS:apps.webdevcat.me"
CMD ["sh", "-c", "openresty -p `pwd` -g 'daemon off;'"]
# Use SIGQUIT instead of default SIGTERM to cleanly drain requests
# See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls
STOPSIGNAL SIGQUIT

View File

@@ -1,17 +1,18 @@
image = miti.sh
docker-run = docker run --rm -w /opt/app -v $(PWD):/opt/app $(image)
run:
serve:
docker run --rm -it --init -v $(PWD):/opt/app -p 8080:80 $(image) \
sh -c "openresty -p /opt/app -g 'daemon off;' -c conf/dev.nginx.conf"
build:
docker run --rm -w /opt/app -v $(PWD):/opt/app $(image) sitegen
shell:
docker run --rm -it --init -v $(PWD):/opt/app -p 8080:80 $(image) bash
build-code:
docker run --rm -w /opt/app -v $(PWD):/opt/app $(image) sitegen build code.md
build:
$(if $(file), $(docker-run) sitegen build $(file), $(docker-run) sitegen)
build-pygments:
docker run --rm -w /opt/app -v $(PWD):/opt/app $(image) moonc pygments.moon
$(docker-run) moonc pygments.moon
image-rm:
docker image rm $(image)
@@ -20,7 +21,21 @@ image-build:
docker build -t $(image) .
lint:
docker run --rm -w /opt/app -v $(PWD):/opt/app $(image) moonc -l .
$(docker-run) moonc -l .
test: build-pygments
./test.sh
host = 'gundi@miti.sh'
path = 'www/sites/miti.sh/html/'
deploy: confirm_deploy
rsync -rvuzL html/ $(host):$(path)
confirm_deploy:
@echo -n "Deploy previously generated site over ssh using rsync\n\n\
Server hostname $(host)?\n\
Path on server to deploy to $(path)?\n\n\
Are you sure? [y/N] " && read ans && [ $${ans:-N} = y ]
.PHONY: confirm_deploy

View File

@@ -1,23 +1,26 @@
## requirements
`pandoc` utility must be installed
* Docker
- Debian Bookworm:
## up and running
$ apt-get update && apt-get install -y pandoc
## start default openresty
1. Run `docker run --rm -it --init -w /opt -v $PWD:/opt -p 80:80 openresty/openresty:1.27.1.2-0-bookworm-buildpack`
2. Visit `localhost` in web browser.
## start a custom site
### build docker image
### build container image
$ make image-build
### rebuild an existing docker image
### build site
$ make build
### start dev server
$ make serve
Visit `localhost:8080` in web browser
## getting around
### rebuild the container image
$ make image-rm image-build
@@ -27,9 +30,11 @@
### add an index page
#### create the file
$ docker run --rm -w /opt/app -v $PWD:/opt/app miti.sh sitegen page /opt/app index
### add to `site.moon`
#### add to `site.moon`
add "index.md"
@@ -52,15 +57,13 @@
}
}
### build site
### build a single file
$ make build
$ make build file=index.html
### start dev server
### start a shell
$ make
Visit `localhost:8080` in web browser
$ make shell
### start watcher
@@ -82,6 +85,17 @@ example:
$ pygmentize -S default -f html
### deploy
$ make deploy
### renew server TSL certs
SSH into server admin account and run:
$ cd www
$ dehydrated --config config -c
## gotchas
### What is error `cosmo failed: [string "..."]:62: cannot resume dead coroutine`?
@@ -102,5 +116,13 @@ Delete your `.sitegen_cache` file.
## thinking about
* use sitecache with pandoc renderer
* draft documents
* treesitter highlighting for moonscript
## todo
* destroy a target ship by shooting them with the cannon
* make corners not bouncy (leave them bouncy for now?)
* wall entities
* ship-ship collision

View File

@@ -6,6 +6,11 @@ events {
}
http {
# server {
# listen 80;
# return 301 https://$host$request_uri;
# }
server {
listen 80;
@@ -13,6 +18,13 @@ http {
charset utf-8;
default_type text/html;
# ssl_certificate /var/www/certs/miti.sh/fullchain.pem;
# ssl_certificate_key /var/www/certs/miti.sh/privkey.pem;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
try_files $uri $uri/ $uri.html =404;
# return `/posts/index.html` from `/posts`
@@ -30,4 +42,95 @@ http {
alias css;
}
}
server {
# listen 443 ssl;
server_name git.miti.sh;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
location / {
client_max_body_size 1024M;
proxy_pass http://unix:/run/gitea/gitea.socket;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
# listen 443 ssl;
server_name apps.miti.sh;
root /var/www/sites/apps.miti.sh;
include mime.types;
charset utf-8;
default_type text/html;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
}
server {
# listen 443 ssl;
server_name webdevcat.me;
include mime.types;
charset utf-8;
default_type text/html;
ssl_certificate /var/www/certs/webdevcat.me/fullchain.pem;
ssl_certificate_key /var/www/certs/webdevcat.me/privkey.pem;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
location / {
return 301 https://miti.sh$request_uri;
}
location ~ ^/git/?(.*)$ {
return 301 https://git.miti.sh/ccm/$1;
}
location ~ ^/apps/(.*)$ {
return 301 https://apps.miti.sh/$1;
}
}
server {
# listen 443 ssl;
server_name git.webdevcat.me;
ssl_certificate /var/www/certs/webdevcat.me/fullchain.pem;
ssl_certificate_key /var/www/certs/webdevcat.me/privkey.pem;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
return 301 https://git.miti.sh$request_uri;
}
server {
# listen 443 ssl;
server_name apps.webdevcat.me;
ssl_certificate /var/www/certs/webdevcat.me/fullchain.pem;
ssl_certificate_key /var/www/certs/webdevcat.me/privkey.pem;
location ^~ /.well-known/acme-challenge {
alias /var/www/dehydrated;
}
return 301 https://apps.miti.sh$request_uri;
}
}

3
html/.gitignore vendored
View File

@@ -1,8 +1,8 @@
app.css
code.html
index.html
moonscript.css
pandoc.css
posts/add-a-pygments-lexer-to-chroma.html
posts/build-a-neovim-qt-appimage-from-source.html
posts/build-static-website-generator-part-1.html
posts/deploy-elixir-generated-html-with-docker-on-digitalocean.html
@@ -15,4 +15,5 @@ posts/resize-a-qemu-disk-image.html
posts/set-up-a-gitweb-server.html
posts/start-erlangs-dialyzer-with-gui-from-a-docker-container.html
posts/test-mix-task-file-modify.html
posts/test-nginx-conf-directives.html
pygments.css

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

1627
html/images/space.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 53 KiB

117
nginx.conf Normal file
View File

@@ -0,0 +1,117 @@
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
}

58
nginx.vh.default.conf Normal file
View File

@@ -0,0 +1,58 @@
# nginx.vh.default.conf -- docker-openresty
#
# This file is installed to:
# `/etc/nginx/conf.d/default.conf`
#
# It tracks the `server` section of the upstream OpenResty's `nginx.conf`.
#
# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by
# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/local/openresty/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/local/openresty/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root /usr/local/openresty/nginx/html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}

View File

@@ -0,0 +1,287 @@
{
title: "Add a Pygments Lexer to Chroma"
blurb: "[Pygments][4] and [Chroma][5] are syntax highlighting libraries
written in [Python][6] and [Go][7], respectively. Chroma is missing a
language we like, which Pygments already supports. We add support for our
language to Chroma by converting the existing lexer from Pygments.
[4]: https://github.com/pygments/pygments
[5]: https://github.com/alecthomas/chroma
[6]: https://www.python.org/
[7]: https://go.dev/"
}
$index
## Introduction
[Gitea][8] uses [Chroma][9] for syntax highlighting. Chroma is based on the
Python syntax highlighter, [Pygments][10], and includes a [script][11] to help
convert Pygments lexers for use with Chroma. We describe how below.
[8]: https://github.com/go-gitea/gitea
[9]: https://github.com/alecthomas/chroma
[10]: https://github.com/pygments/pygments
[11]: https://github.com/alecthomas/chroma/blob/484750a96fc430f49d6b69cc2a2a8b7a67691446/_tools/pygments2chroma_xml.py
## Setup
We're going to be using the `python` and `golang` [Docker][3] images. Docker
Desktop is _not_ required.
```console
$ docker pull python
$ docker pull golang
```
Let's set up some aliases to make running the commands easier.
```console
$ alias docker-run='docker run --rm -it -w /opt -v $PWD:/opt'
$ alias docker-run-go='docker-run golang'
$ alias docker-run-py='docker-run python'
```
[3]: https://docs.docker.com/engine/
## Convert a Pygments lexer to a Chroma lexer with `pygments2chroma_xml.py`
```console
$ git clone https://github.com/alecthomas/chroma.git
$ cd chroma
```
In the Chroma root directory, we run:
```console
$ docker-run-py bash -c \
"pip install pystache pygments && \
python _tools/pygments2chroma_xml.py \
pygments.lexers.scripting.LuaLexer > lexers/embedded/lua.xml && \
pip list"
```
We should see this in the output:
```
Package Version
-------- -------
pip 25.0.1
Pygments 2.19.2
pystache 0.6.8
```
This just helps us know what version of Pygments we generated our lexer from.
The file `lexers/embedded/lua.xml` should now contain all the tokenization
rules for the [Lua](https://www.lua.org) language.
::: filename-for-code-block
`lexers/embedded/lua.xml`
:::
```xml
<lexer>
<config>
<name>Lua</name>
...
```
## Highlight some code with a Chroma lexer
Chroma provides a [simple example test file][1] we can modify to see what syntax
highlighting with our new lexer looks like. First, though, we need to create a
new Go module by running `go mod init`:
```console
$ cd ..
$ docker-run-go go mod init main
go: creating new go.mod: module main
go: to add module requirements and sums:
go mod tidy
```
We will need required modules, so let's go ahead and run `go mod tidy` as the
output suggests.
```console
$ docker-run-go go mod tidy
```
We should now have 2 additional files, `go.mod` and `go.sum`. `go.sum` has some
package hashes while `go.mod` should look like this:
::: filename-for-code-block
`go.mod`
:::
```
module main
go 1.25
require github.com/alecthomas/chroma/v2 v2.18.0
require github.com/dlclark/regexp2 v1.11.5 // indirect
```
Now we can create a `main.go` file and copy over the code from Chroma's example
test file, but we update the `code` variable with some Lua, `print("hello")`,
and the lexer we pass into the `Highlight` function is changed to `"lua"`:
::: filename-for-code-block
`main.go`
:::
```go
package main
import (
"log"
"os"
"github.com/alecthomas/chroma/v2/quick"
)
func main() {
code := `print("hello")`
err := quick.Highlight(os.Stdout, code, "lua", "html", "monokai")
if err != nil {
log.Fatal(err)
}
}
```
Now we can try running our `main.go` like this:
```console
$ docker-run-go go run main.go
go: downloading github.com/alecthomas/chroma/v2 v2.18.0
go: downloading github.com/dlclark/regexp2 v1.11.5
<html>
<style type="text/css">
...
```
And that should output markup (and styles) for highlighting that block of Lua
code to the console. But if we notice, it's importing the Chroma package from
the GitHub repo. If we want to use a local version of Chroma, we have to use a
[`replace` directive][2] to import Chroma from our local directory:
```console
$ docker-run-go go mod edit -replace \
github.com/alecthomas/chroma/v2@v2.18.0=./chroma
```
Which adds this line to our `go.mod` file:
::: filename-for-code-block
`go.mod`
:::
```
...
replace github.com/alecthomas/chroma/v2 v2.18.0 => ./chroma
```
Now, when we run `main.go`, we should no longer see Chroma being imported,
because it's using our local copy:
```console
$ docker-run-go go run main.go
go: downloading github.com/dlclark/regexp2 v1.11.5
<html>
<style type="text/css">
...
```
We should also see a list of styles followed by the HTML markup for
highlighting our Lua code (formatted for legibility):
```html
<pre class="chroma">
<code>
<span class="line">
<span class="cl">
<span class="n">print</span>
<span class="p">(</span>
<span class="s2">&#34;hello&#34;</span>
<span class="p">)</span>
</span>
</span>
</code>
</pre>
```
[1]: https://github.com/alecthomas/chroma/blob/484750a96fc430f49d6b69cc2a2a8b7a67691446/quick/example_test.go
[2]: https://go.dev/ref/mod#go-mod-file-replace
## Add test data
If we want to add our lexer to Chroma, we will need to create some test data
for it. We can create a file in `lexers/testdata` called `lua.actual` and
add the language tokens to it.
## Record test output
Once we have test data, we need to record the expected output. We create
another file called `lexers/testdata/lua.expected`. This is the file we
will record to by running the following command from the Chroma root directory:
```console
$ docker-run -e RECORD=true golang go test ./lexers
```
Once test output is recorded in `lexers/testdata/lua.expected`, we should
visually inspect and verify that the expected data is correct.
## Run tests
As a final confirmation, we can run the tests to make sure we have not broken
anything:
```console
$ docker-run-go go test ./lexers
```
## Conclusion
If we followed all these steps correctly, our lexer should be ready to be
pushed to a `git` repo and for us to open a pull request!
## Bonus!: Use local Pygments with `pygments2chroma_xml.py`
These lines in `pygments2chroma_xml.py`,
```python
import pystache
from pygments import lexer as pygments_lexer
from pygments.token import _TokenType
```
import Pygments from the [Python Package Index](https://pypi.org/). But, if we
want to convert a Pygments lexer from a local `git` repo, we can import it
by simply running the `pygments2chroma_xml.py` script from the repo root
directory.
```console
$ git clone https://github.com/pygments/pygments.git
$ cd pygments
$ docker-run \
-v ../chroma/_tools/pygments2chroma_xml.py:/opt/pygments2chroma_xml.py \
python bash -c \
"pip install pystache && \
python pygments2chroma_xml.py pygments.lexers.scripting.LuaLexer && \
pip list"
```
We should see the lexer output followed by
```console
Package Version
-------- -------
pip 25.0.1
pystache 0.6.8
```
which indicates no remote `pygments` package was installed.

View File

@@ -0,0 +1,566 @@
{
title: "Test nginx Configuration Directives"
blurb: "We use MoonScript and some Lua packages to write tests for the
directives in our `nginx` configuration files."
}
$index
## Introduction
[`nginx`](https://docs.nginx.com/nginx/admin-guide/web-server/web-server/#rewrite-uris-in-requests)
configuration can contain any number of important directives (redirects and
rewrites, for example) that need to be verified for correctness. We can write
tests for directives and run them against a test server to ensure they are
correct.
To do this, we'll use...
- [MoonScript](https://moonscript.org) and (by extension) [Lua](https://www.lua.org/) programming languages
- `nginx` we'll get from [OpenResty](https://openresty.org/en/), a web platform
created by Chinese developer, [Yichun Zhang](https://agentzh.org/)
- the [Busted testing framework](https://lunarmodules.github.io/busted/)
- the Lua package manager, [LuaRocks](https://luarocks.org/)
- a fantastic little library, [`luajit-curl`](https://bitbucket.org/senanetworksinc/luajit-curl/src/master/),
from Japanese developer [SENA Networks, Inc](https://www.sena-networks.co.jp)
- another great library, written by volunteers, [LuaSocket](https://github.com/lunarmodules/luasocket)
- our favorite container manager, [Docker Engine](https://docs.docker.com/engine/)
## Setup
Since we require LuaRocks, we'll use a Buildpack tag, which comes with it
already installed.
```console
$ docker pull openresty/openresty:bookworm-buildpack
```
Start a server on `localhost`:
```console
$ docker run --rm -it -p 80:80 openresty/openresty:bookworm-buildpack
```
We can visit `localhost` in our browser and we should see the OpenResty splash
page.
![OpenResty default nginx index page](/images/openresty-default-index-page.png)
## Get `nginx` running
First, let's [prepare the directory layout](https://openresty.org/en/getting-started.html#prepare-directory-layout).
```console
$ mkdir -p logs/ conf/conf.d/ html/
```
Next, we copy over [the default `nginx` config file](https://github.com/openresty/docker-openresty?tab=readme-ov-file#nginx-config-files).
```console
$ docker run --rm -it -w /opt -v $PWD:/opt openresty/openresty:bookworm-buildpack \
cp /etc/nginx/conf.d/default.conf /opt/conf.d/
```
Then, we update the root directive in `default.conf`:
::: filename-for-code-block
`conf/conf.d/default.conf`
:::
```diff
location / {
- root /usr/local/openresty/nginx/html;
+ root /var/www;
index index.html index.htm;
```
Now, let's add an index file.
::: filename-for-code-block
`html/index.html`
:::
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title></title>
</head>
<body>
hello world!
</body>
</html>
```
Last, we start `nginx`:
```console
$ docker run --rm -it -p 80:80 \
-v $PWD/conf/conf.d:/etc/nginx/conf.d -v $PWD/html:/var/www \
openresty/openresty:bookworm-buildpack
```
Then, in another console, this should output our index file.
```console
$ curl -v localhost
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: openresty/1.27.1.2
< ...
<
<!DOCTYPE html>
<html lang="en">
...
<body>
hello world!
</body>
</html>
```
## Test an HTTP request
If we want to write a test for that request, we need some packages from
LuaRocks. Let's add a `Dockerfile` to build an image with those packages
installed.
### Add a `Dockerfile`
```Dockerfile
FROM openresty/openresty:bookworm-buildpack
WORKDIR /opt/app
RUN luarocks install moonscript
RUN luarocks install busted
RUN luarocks install luajit-curl
RUN luarocks install luasocket
```
Now let's build our image:
```console
$ docker build -t test-nginx .
```
### Write the test
Let's first make a new directory where our tests will live.
```console
$ mkdir spec
```
Our test makes a cURL request against our test server:
::: filename-for-code-block
`spec/nginx_spec.moon`
:::
```moonscript
http = require "luajit-curl-helper.http"
req = (url) ->
request = http.init url
st = request\perform!
error request\lastError! if not st
request
describe "http://localhost", ->
it "sends /index.html", ->
request = req "http://localhost"
assert.same request\statusCode!, 200
assert.same request\statusMessage!, "OK"
assert.same request\body!\match("<body>%s+(.-)%s+</body>"), "hello world!"
```
### Run the test suite
Start the test server. We're going to use `text-nginx`, the image we just
built.
```console
$ ct=$(docker run --rm -d \
-v $PWD/conf/conf.d:/etc/nginx/conf.d \
-v $PWD/html:/var/www \
-v $PWD:/opt/app \
test-nginx)
```
Start the test run:
```console
$ docker exec -t $ct busted
1 success / 0 failures / 0 errors / 0 pending : 0.008246 seconds
```
Stop the test server.
```console
$ docker exec $ct openresty -s stop
```
## Create a `Makefile`
We now have a number of long `docker` commands, let's create a `Makefile`
to make running them easier.
::: filename-for-code-block
`Makefile`
:::
```Makefile
image = test-nginx
image-build:
docker build -t $(image) .
image-rm:
docker image rm $(image)
test:
@ct=$(shell docker run --rm -d \
-v $(PWD)/conf/conf.d:/etc/nginx/conf.d \
-v $(PWD)/html:/var/www \
-v $(PWD):/opt/app \
$(image)); \
docker exec -t $$ct busted; \
docker exec $$ct openresty -s stop
```
Now we can run the test suite with the command `make test`.
## Configure the domain name
Instead of `localhost` we'd like to use an actual domain name. We can do this
with the `--add-host` option. But before we do that, we want to make sure our
container does not have access to the internet, otherwise we might
unintentionally get a response from a domain's server on the internet rather
than from our test server.
### Ensure the test container is offline
We need to create a network that has no external access.
```console
$ docker network create --internal no-internet
```
Now we need to update our `Makefile` to add the test container to our
internal-only network:
```diff
test:
@ct=$(shell docker run --rm -d \
-v $(PWD)/conf/conf.d:/etc/nginx/conf.d \
-v $(PWD)/html:/var/www \
-v $(PWD):/opt/app \
+ --network no-internet \
$(image)); \
```
And now let's add a test in `spec/nginx_spec.moon` to make sure our test
environment is offline:
```moonscript
describe "test environment", ->
it "can't connect to the internet", ->
assert.has_error (-> req "http://example.org"),
"Couldn't resolve host name"
```
Let's run our tests:
```console
$ make test
●●
2 successes / 0 failures / 0 errors / 0 pending : 0.020207 seconds
```
### Replace `localhost` with a custom domain
To use a custom domain name instead of `localhost`, we will need to use the
`--add-host` option for the `docker run` command. Again, we edit `Makefile`:
```diff
test:
@ct=$(shell docker run --rm -d \
-v $(PWD)/conf/conf.d:/etc/nginx/conf.d \
-v $(PWD)/html:/var/www \
-v $(PWD):/opt/app \
--network no-internet \
+ --add-host=domain.abc=127.0.0.1 \
$(image)); \
```
Let's update our test to use the custom domain name:
::: filename-for-code-block
`spec/nginx_spec.moon`
:::
```diff
-describe "http://localhost", ->
+describe "http://domain.abc", ->
it "sends /index.html", ->
- request = req "http://localhost"
+ request = req "http://domain.abc"
assert.same request\statusCode!, 200
```
Verify our tests still pass.
```console
$ make test
●●
2 successes / 0 failures / 0 errors / 0 pending : 0.0224 seconds
```
## Test an HTTP redirect
We want our server to redirect all `http` requests to `https`.
### Write the test
Let's practice a bit of test-driven development and write our test first.
```moonscript
describe "http://domain.abc", ->
it "redirects to https", ->
request = req "http://domain.abc"
assert.same request\statusCode!, 301
assert.same request\statusMessage!, "Moved Permanently"
assert.same request\header!.Location, "https://domain.abc/"
```
We should now have one failing test.
```console
$ make test
●●◼
2 successes / 1 failure / 0 errors / 0 pending : 0.010449 seconds
Failure → .../luajit/lib/luarocks/rocks-5.1/busted/2.2.0-1/bin/busted @ 3
http://domain.abc redirects to https
spec/nginx_spec.moon:24: Expected objects to be the same.
Passed in:
(number) 301
Expected:
(number) 200
```
### Configure `nginx`
We're going to add the redirect directives, as well as a server name for our
domain and the directives for the SSL certificates we will generate.
```diff
+server {
+ listen 80;
+ return 301 https://$host$request_uri;
+}
server {
- listen 80;
+ listen 443 ssl;
+ server_name domain.abc;
+ ssl_certificate /etc/ssl/certs/domain.abc.pem;
+ ssl_certificate_key /etc/ssl/private/domain.abc.pem;
location / {
root /var/www;
index index.html index.htm;
}
```
### Generate self-signed SSL/TLS certs for testing
Add a command to our `Dockerfile` to generate self-signed certificates:
```Dockerfile
RUN openssl req -x509 -newkey rsa:4096 -nodes \
-keyout /etc/ssl/private/domain.abc.pem \
-out /etc/ssl/certs/domain.abc.pem \
-sha256 -days 365 -subj '/CN=domain.abc' \
-addext "subjectAltName=DNS:domain.abc"
```
Rebuild the image:
```console
$ make image-rm image-build
```
We need to update our previous test to use HTTPS instead of HTTP.
::: filename-for-code-block
`spec/nginx_spec.moon`
:::
```diff
-describe "http://domain.abc", ->
+describe "https://domain.abc", ->
it "sends /index.html", ->
- request = req "http://domain.abc"
+ request = req "https://domain.abc"
```
Run tests:
```console
$ make test
●●●
3 successes / 0 failures / 0 errors / 0 pending : 0.017065 seconds
```
## Test reverse proxy a subdomain request to a Unix socket
Let's say we have a running service that connects to a Unix socket. We want to
proxy the requests through `nginx` so that our service can respond to `https`
requests but can leave handling SSL/TLS to `nginx`.
### Configure `nginx`
We'll add another server block to `conf/conf.d/default.conf` for our subdomain,
`git.domain.abc`, with the proxy directives:
```nginx
server {
listen 443 ssl;
server_name git.domain.abc;
location / {
client_max_body_size 1024M;
proxy_pass http://unix:/run/gitea/gitea.socket;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
### Add subdomain to SSL/TLS certs
Next, we need to add our subdomain to the generated SSL certs in the
`Dockerfile`:
```diff
RUN openssl req -x509 -newkey rsa:4096 -nodes \
-keyout /etc/ssl/private/domain.abc.pem \
-out /etc/ssl/certs/domain.abc.pem \
-sha256 -days 365 -subj '/CN=domain.abc' \
- -addext "subjectAltName=DNS:domain.abc"
+ -addext "subjectAltName=DNS:domain.abc,DNS:git.domain.abc"
```
### Add subdomain as a host
Let's assign the loopback address to a variable and then add our subdomain as a
host in our `Makefile`:
```diff
+loopback = 127.0.0.1
test:
@ct=$(shell docker run --rm -d \
-v $(PWD)/conf/conf.d:/etc/nginx/conf.d \
-v $(PWD)/html:/var/www \
-v $(PWD):/opt/app \
--network no-internet \
- --add-host=domain.abc=127.0.0.1 \
+ --add-host=domain.abc=$(loopback) \
+ --add-host=git.domain.abc=$(loopback) \
$(image)); \
```
### Add a test socket server
We need to start up a mock socket server for our test to ensure our request is
being proxied correctly. This is why we needed the LuaSocket library.
Copied and modified from [here](https://github.com/lunarmodules/luasocket/blob/4844a48fbf76b0400fd7b7e4d15d244484019df1/test/unixstreamsrvr.lua),
this should suit our purposes:
::: filename-for-code-block
`spec/unixstreamsrvr.moon`
:::
```moonscript
socket = require "socket"
socket.unix = require "socket.unix"
u = assert socket.unix.stream!
assert u\bind "/run/gitea/gitea.socket"
assert u\listen!
assert u\settimeout 1
c = assert u\accept!
while true
m = assert c\receive!
break if m == ""
print m
```
### Write the test
And now we can add our test:
::: filename-for-code-block
`spec/nginx_spec.moon`
:::
```moonscript
describe "https://git.domain.abc", ->
it "reverse-proxy's a subdomain request to a unix socket", ->
socket = fname: "unixstreamsrvr.moon", dir: "/run/gitea", owner: "nobody"
basepath = debug.getinfo(1).short_src\match"^(.*)/[^/]*$" or "."
seconds = 0.1
os.execute "install -o #{socket.owner} -d #{socket.dir}"
cmd = "su -s /bin/bash -c 'moon %s' %s"
server = io.popen cmd\format "#{basepath}/#{socket.fname}", socket.owner
os.execute "sleep #{seconds}" -- wait for server to start
f = io.popen "find #{socket.dir} -type s -ls", "r"
result = with f\read "*a"
f\close!
assert.truthy result\match "nobody%s+nogroup.+#{socket.dir}/gitea.socket"
req "https://git.domain.abc"
reqheader = with server\read "*a"
server\close!
assert.truthy reqheader\match "Host: git.domain.abc"
```
Because we modified the `Dockerfile`, we need to rebuild our image:
```console
$ make image-rm image-build
```
And if all went well, our test should pass.
```console
$ make test
●●●●
4 successes / 0 failures / 0 errors / 0 pending : 0.131619 seconds
```
## Conclusion
These are just a few examples of how to test `nginx` directives. Using these
tools, we can verify that changes to our server configuration are working the
way we intended.

View File

@@ -23,11 +23,11 @@ span.linenos.special { color: #50fa7b; background-color: #6272a4; padding-left:
.highlight .py-cpf { color: #6272a4 } /* Comment.PreprocFile */
.highlight .py-c1 { color: #6272a4 } /* Comment.Single */
.highlight .py-cs { color: #6272a4 } /* Comment.Special */
.highlight .py-gd { color: #8b080b } /* Generic.Deleted */
.highlight .py-gd { color: #ff5555 } /* Generic.Deleted */
.highlight .py-ge { color: #f8f8f2; text-decoration: underline } /* Generic.Emph */
.highlight .py-gr { color: #f8f8f2 } /* Generic.Error */
.highlight .py-gh { color: #f8f8f2; font-weight: bold } /* Generic.Heading */
.highlight .py-gi { color: #f8f8f2; font-weight: bold } /* Generic.Inserted */
.highlight .py-gi { color: #50fa7b } /* Generic.Inserted */
.highlight .py-go { color: #f8f8f2 } /* Generic.Output */
.highlight .py-gp { color: #50fa7b } /* Generic.Prompt */
.highlight .py-gs { color: #f8f8f2 } /* Generic.Strong */

View File

@@ -1,5 +1,70 @@
Path = require "sitegen.path"
dollar_temp = "z000sitegen_markdown00dollar0000"
-- a constructor for quote delimited strings
simple_string = (delim) ->
import P from require "lpeg"
inner = P("\\#{delim}") + "\\\\" + (1 - P delim)
inner = inner^0
P(delim) * inner * P(delim)
lua_string = ->
import P, C, Cmt, Cb, Cg from require "lpeg"
check_lua_string = (str, pos, right, left) ->
#left == #right
string_open = P"[" * P"="^0 * "["
string_close = P"]" * P"="^0 * "]"
valid_close = Cmt C(string_close) * Cb"string_open", check_lua_string
Cg(string_open, "string_open") *
(1 - valid_close)^0 * string_close
-- returns a pattern that parses a cosmo template. Can be used to have
-- pre-processors ignore text that would be handled by cosmo
parse_cosmo = ->
import P, R, Cmt, Cs, V from require "lpeg"
curly = P {
P"{" * (
simple_string("'") +
simple_string('"') +
lua_string! +
V(1) +
(P(1) - "}")
)^0 * P"}"
}
alphanum = R "az", "AZ", "09", "__"
P"$" * alphanum^1 * (curly)^-1
escape_cosmo = (str) ->
escapes = {}
import P, R, Cmt, Cs, V from require "lpeg"
counter = 0
cosmo = parse_cosmo! / (tpl) ->
counter += 1
key = "#{dollar_temp}_#{counter}"
escapes[key] = tpl
key
patt = Cs (cosmo + P(1))^0 * P(-1)
str = patt\match(str) or str, escapes
str, escapes
unescape_cosmo = (str, escapes) ->
import P, R, Cmt, Cs from require "lpeg"
escape_patt = P(dollar_temp) * P("_") * R("09")^1 / (key) ->
escapes[key] or error "bad key for unescape_cosmo"
patt = Cs (escape_patt + P(1))^0 * P(-1)
assert patt\match(str)
needs_shell_escape = (str) -> not not str\match "[^%w_-]"
shell_escape = (str) -> str\gsub "'", "''"
@@ -19,12 +84,13 @@ write_exec = (cmd, content) ->
fname
-- config command like this in site.moon:
-- require("renderers.markdown").cmd = "pandoc --mathjax >"
class PandocRenderer extends require "sitegen.renderers.markdown"
unescape_cosmo = @unescape_cosmo
escape_cosmo = @escape_cosmo
class PandocRenderer extends require "sitegen.renderers.html"
@escape_cosmo: escape_cosmo
@unescape_cosmo: unescape_cosmo
@parse_cosmo: parse_cosmo
source_ext: "md"
ext: "html"
cmd: "pandoc --mathjax --lua-filter pygments.lua >"
pandoc: (content) => Path.read_file write_exec @@cmd, content

View File

@@ -29,7 +29,6 @@ get_files = (path, prefix=path) ->
files = for file in *files
file\gsub "^#{escape_patt prefix}/?", ""
table.sort files
files
-- strip file extension from filename
@@ -126,7 +125,6 @@ sitegen.create =>
copy "app.css"
copy "pygments.css"
copy "moonscript.css"
copy "pandoc.css"
-- replace post markdown yaml headers with moonscript headers

View File

@@ -104,6 +104,10 @@ describe "https://miti.sh/posts/", ->
describe "https://miti.sh/posts", ->
it "sends /posts/index.html", ->
with require "sitegen.path"
assert .exists("html/posts/index.html"),
"missing html/posts/index.html (try `make build file=blog.html`)"
request = req "https://miti.sh/posts"
assert.same request\statusCode!, 200
assert.same request\statusMessage!, "OK"

View File

@@ -86,3 +86,11 @@ this code block has no label
assert.same [[<div class="sourceCode" id="cb1"><pre
class="sourceCode heex"><code class="sourceCode elixir"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="op">&lt;.</span>greet name<span class="op">=</span><span class="st">&quot;Jane&quot;</span><span class="op">/&gt;</span></span></code></pre></div>]], out
it "escapes and unescapes double dollar signs", ->
out = flatten_html render [[
```Makefile
$$name
```]]
assert.same [[<div class="highlight"><pre><span></span><code><span class="py-w"></span><span class="py-nv">$$name</span></code></pre></div>]], out