M .gitignore => .gitignore +4 -4
@@ 1,4 1,4 @@
-www
-funlist.html
-navbar.html
-postlist.html
+/www/
+/funlist.html
+/navbar.html
+/postlist.html
A assets/posts/apple_firefox_meme.webp => assets/posts/apple_firefox_meme.webp +0 -0
A => +18 -0
@@ 0,0 1,18 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256">
<defs>
<linearGradient x1="0.085" y1="0.085" x2="0.915" y2="0.915" id="RSSg">
<stop offset="0.0" stop-color="#E3702D"/><stop offset="0.1071" stop-color="#EA7D31"/>
<stop offset="0.3503" stop-color="#F69537"/><stop offset="0.5" stop-color="#FB9E3A"/>
<stop offset="0.7016" stop-color="#EA7C31"/><stop offset="0.8866" stop-color="#DE642B"/>
<stop offset="1.0" stop-color="#D95B29"/>
</linearGradient>
</defs>
<rect width="256" height="256" rx="55" ry="55" x="0" y="0" fill="#CC5D15"/>
<rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/>
<rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#RSSg)"/>
<circle cx="68" cy="189" r="24" fill="#FFF"/>
<path d="M160 213h-34a82 82 0 0 0 -82 -82v-34a116 116 0 0 1 116 116z" fill="#FFF"/>
<path d="M184 213A140 140 0 0 0 44 73 V 38a175 175 0 0 1 175 175z" fill="#FFF"/>
</svg>
A assets/srht.svg => assets/srht.svg +5 -0
@@ 0,0 1,5 @@
+<?xml version="1.0"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
+<path d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200z"/>
+</svg>
M assets/styles.css => assets/styles.css +4 -0
@@ 97,6 97,10 @@ footer {
font-size: 0.5em;
}
+footer a img {
+ height: 1em;
+}
+
blockquote {
background: #f9f9f9;
border-left: 7px solid #ccc;
M build => build +26 -17
@@ 1,5 1,7 @@
#!/bin/sh
+set -e
+
OUT_DIR=www
rm -rf $OUT_DIR
@@ 7,10 9,10 @@ mkdir $OUT_DIR
cp -r assets $OUT_DIR/
-TITLE=rdck.dev
-LINK_PREFIX=https://rdck.dev
+export TITLE=rdck.dev
+export LINK_PREFIX=https://rdck.dev
-RSSFEED=$OUT_DIR/rss.xml
+export RSSFEED=$OUT_DIR/rss.xml
function get_title() {
cat $1 | grep "^# " | head -1 | sed 's/^# //'
@@ 33,7 35,7 @@ function generate_rss() {
echo "<rss version=\"2.0\">
<channel>
-<title>$TITLE</title>
+<title>rdck.dev</title>
<link>$LINK_PREFIX</link>
<language>en-us</language>
<pubDate>`date -R`</pubDate>
@@ 45,6 47,7 @@ function generate_rss() {
<title>`get_title $f`</title>
<link>$LINK_PREFIX/`get_url $f`</link>
<pubDate>`get_date2 $f`</pubDate>
+<description>`mmtt < $f | lowdown`</description>
</item>" >> $RSSFEED
done
@@ 64,26 67,32 @@ function generate_list() {
echo "</ul>" >> $2
}
-generate_list ./fun ./funlist.html
-generate_list ./posts ./postlist.html
+function generate_navbar() {
+ echo "<nav>" > $NAVBAR_HTML
+ for f in `find content -type f -name '*.md' ! -name '404.md' ! -name 'index.md'`
+ do
+ NAME=`basename -s .md $f | awk '{ print toupper(substr($0,1,1)) substr($0,2) }'`
+ URL=/`get_url $f`
+ echo "<a href=\"$URL\">$NAME</a>" >> $NAVBAR_HTML
+ done
+ echo "</nav>" >> $NAVBAR_HTML
+}
+
+export POSTS_HTML=./postlist.html
+export FUN_HTML=./funlist.html
+export NAVBAR_HTML=./navbar.html
+generate_list ./fun $FUN_HTML
+generate_list ./posts $POSTS_HTML
generate_rss `find posts fun -name \*.md -type f`
-# build navbar html
-echo "<nav>" > ./navbar.html
-for f in `find content -type f -name '*.md' ! -name '404.md' ! -name 'index.md'`
-do
- NAME=`basename -s .md $f | awk '{ print toupper(substr($0,1,1)) substr($0,2) }'`
- URL=/`get_url $f`
- echo "<a href=\"$URL\">$NAME</a>" >> navbar.html
-done
-echo "</nav>" >> navbar.html
+generate_navbar
# build html from md
for f in `find content posts fun -name \*.md`; do
PART=$OUT_DIR/`basename -s .md $f`.part.html
HTML=$OUT_DIR/`basename -s .md $f`.html
- POSTS_HTML=./postlist.html FUN_HTML=./funlist.html mmtt < $f | lowdown --html-no-skiphtml --html-no-escapehtml > $PART
- TITLE=rdck.dev CONTENT_HTML=$PART NAVBAR_HTML=./navbar.html mmtt < template.html > $HTML
+ mmtt < $f | lowdown --html-no-skiphtml --html-no-escapehtml > $PART
+ TITLE=`get_title $f` CONTENT_HTML=$PART mmtt < template.html > $HTML
done
M content/index.md => content/index.md +4 -2
@@ 6,14 6,16 @@ My name is Prokop Randáček. I write code, like cats and play Factorio.
### Cool websites in alphabetical order
+- [0D9E](https://0d9e.tech/)
- [Bear blog](https://bearblog.dev/)
-- [Command Line Interface Guidelines](https://clig.dev)
- [Drew DeVault](https://drewdevault.com/)
- [Kubíkovo](https://chamik.eu/)
- [Lua](https://www.lua.org/)
- [LuaJIT](http://luajit.org/)
- [Marek Maškarinec](https://mrms.cz/)
+- [Marian Šámal](https://mariansam.eu/)
+- [Matěj Volf](https://matej.0d9e.tech/)
- [rxi](https://rxi.github.io/)
-- [SourceHut](https://sourcehut.org)
+- [SourceHut](https://sourcehut.org/)
- [Zig](https://ziglang.org/)
M fun/2022-03-06-wang.md => fun/2022-03-06-wang.md +0 -3
@@ 1,7 1,4 @@
<style>
-html, body {
- margin: 0;
-}
#grid {
border-collapse: collapse;
}
A fun/2023-04-07-web-graph.md => fun/2023-04-07-web-graph.md +96 -0
@@ 0,0 1,96 @@
+# web map
+
+requires disabling cross-origin resource sharing.
+
+<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
+
+<style>
+#mynetwork {
+ width: 100vh;
+ height: 100vh;
+ border: 1px solid lightgray;
+}
+</style>
+
+<div id="mynetwork"></div>
+
+<script type="text/javascript">
+
+const nodes = new vis.DataSet([{ id: "rdck.dev", label: "rdck.dev", expanded: false, depth: 0 }]);
+const edges = new vis.DataSet([]);
+
+var container = document.getElementById('mynetwork');
+
+var data = { nodes: nodes, edges: edges };
+
+var options = { };
+
+var network = new vis.Network(container, data, options);
+
+async function fetchLinks(url) {
+ try {
+ const response = await fetch("https://" + url)
+ const text = await response.text()
+ const doc = new DOMParser().parseFromString(text, "text/html")
+ return new Set(Array.from(doc.querySelectorAll("a"))
+ .map(a => a.getAttribute("href"))
+ .map(href => new URL(href, "https://" + url).hostname)
+ .filter(a => a != "")
+ .map(hostname => {
+ const parts = hostname.split(".");
+ return parts[parts.length - 2] + "." + parts[parts.length - 1];
+ }));
+ } catch (error) {
+ console.error(error)
+ }
+ return new Set()
+}
+
+async function expandNode(nodeId) {
+ const node = nodes.get(nodeId);
+
+ if (node.expanded) return;
+
+ const newLinks = await fetchLinks(node.id);
+ node.expanded = true;
+ nodes.update(node);
+
+ newLinks.forEach(link => {
+ if (!nodes.get(link)) {
+ nodes.update({
+ id: link,
+ label: link,
+ expanded: false,
+ depth: node.depth + 1
+ });
+ }
+ edges.update({ from: node.id, to: link });
+ }
+ );
+}
+
+network.on('click', (params) => {
+ if (params.nodes.length) {
+ expandNode(params.nodes[0]);
+ }
+});
+
+async function expandAll() {
+ const unexpandedNodes = nodes.get({
+ filter: node => !node.expanded,
+ fields: ['id']
+ });
+
+ for (const node of unexpandedNodes) {
+ await expandNode(node.id);
+ }
+}
+
+(async function() {
+await expandAll();
+await expandAll();
+await expandAll();
+})();
+
+</script>
+
A post.txt => post.txt +9 -0
@@ 0,0 1,9 @@
+# Posts
+
+Sometimes I like to write something that is not code :D
+
+Note that I disown anything I wrote more than 2 years ago.
+
+------------------------------------------------------------------------
+
+{:: cat \$POSTS_HTML ::}
A posts/2023-05-10-lebka-propaganda-1.md => posts/2023-05-10-lebka-propaganda-1.md +76 -0
@@ 0,0 1,76 @@
+# Common web L
+
+## Present
+
+The overwhelming complexity of current web standards has narrowed down web
+browsers to just 3 implementations: Chromium, Safari, and Frefox. Even
+Microsoft, valued at 2 *trillion* dollars[1] with 100k developers[2], abandoned
+maintaining its own web browser and switched to Blink.
+
+Interestingly, Apple's uncompetitive browser restrictions are the last thing
+keeping web browser diversity alive. Today's web development usually involves
+maintaining compatibility with Chrome, Safari, and Firefox.
+
+- Chrome, because it has the biggest usage share (65 %[3])
+- Safari, because it is mandatory on Apple devices (19 %[3])
+- Firefox, because you might as well while you are at it (2 %[3])
+
+Supporting 2 platforms instead of 3 isn't a significant reduction in workload.
+As seen by Firefox still being deemed worth the developer's time and effort to
+support.
+
+## Speculation
+
+Imagine if Apple decided to abandon WebKit, joining forces with Chromium just
+like Microsoft. Firefox would be in an even worse position than it is now. With
+Chromium-based browsers dominating 94 %[3] of the web, few would care about the
+remaining 6 %. The reduced need to distinguish between browser-specific behavior
+and standard specified behavior would kill any browser that did not walk or
+quack like Chrome.
+
+This would enable Chrome to push non-standard behavior and custom features, such
+as [Web
+Bluetooth](https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API),
+[Shape Detection](https://developer.chrome.com/en/articles/shape-detection),
+[WebUSB](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API), and more.
+It doesn't matter if they're experimental; if it works on Chrome, why not rely
+on it? This trend would make it increasingly difficult for new browsers to
+emerge. Competing with Chrome would mean not only implementing the entire
+HTML/CSS/JS stack but also additional features like a face recognition API.
+
+Of course, Apple isn't keeping WebKit alive to save Firefox; they talk about
+"security" reasons[4]...
+
+Ironically, *efforts to stop Apple from enforcing WebKit on iOS might be the
+final nail in the Firefox coffin*.
+
+![](assets/posts/apple_firefox_meme.webp)
+
+## Present
+
+Even Chromium and WebKit-based browsers aren't immune to these challenges. I
+currently use the WebKit-based [qutebrowser](https://qutebrowser.org), but that
+doesn't mean that things just work. To bypass the new generation of captchas on
+sites like Hetzner or ChatGPT, I have to abandon qutebrowser and launch
+Chromium. I didn't bother reaching out to OpenAI and Hetzner doesn't care:
+
+> [...] we cannot support your current browser. The reason is that the use of
+> this browser is very rare, and it is not viable for us to customize our
+> website specifically for it. [...]
+
+It is not enough that qutebrowser supports everything that Safari does, it has
+to trick websites into thinking that it actually is Safari.
+
+## Conclusion
+
+The web is in a terrible state, and we need to do better. If only there was a
+way to achieve 70% of web functionality with just 10% of the code. Removing the
+technical debt, reducing complexity, improving modularity, embracing simplicity,
+making it possible again for meere mortals to create homebrew
+browsers[...](https://git.sr.ht/~prokop/lebka)
+
+[1]: https://www.macrotrends.net/stocks/charts/MSFT/microsoft/net-worth
+[2]: https://devblogs.microsoft.com/engineering-at-microsoft/welcome-to-the-engineering-at-microsoft-blog
+[3]: https://en.wikipedia.org/wiki/Usage_share_of_web_browsers
+[4]: https://www.macrumors.com/2022/02/25/should-apple-ban-rival-browser-engines
+