1
0
Fork 0
forked from fun/fun

Moved the website code to ./web/ to make it easier to maintain for me. No code changes. (0.40.5)

This commit is contained in:
Johannes Findeisen 2026-04-10 22:36:29 +02:00
commit 71576be449
71 changed files with 3354 additions and 1 deletions

8
.gitignore vendored
View file

@ -3,8 +3,11 @@ CMakeCache.txt
!.editorconfig
!.gitignore
!.github
!.gitkeep
.venv
build*
build/*
build_debug/*
build_release/*
cmake_install.cmake
database.sqlite
demo_*
@ -18,3 +21,6 @@ src/rust/Cargo.lock
src/rust/target
*.swp
tmp*
web/_cache/*
web/_site/*
web/Gemfile.lock

132
web/CODE_OF_CONDUCT.md Normal file
View file

@ -0,0 +1,132 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
community@xw3.org. All complaints will be reviewed and investigated promptly and
fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations

33
web/Gemfile Normal file
View file

@ -0,0 +1,33 @@
# frozen_string_literal: true
source "https://rubygems.org"
gem 'addressable'
gem 'colorator'
gem 'concurrent-ruby'
gem 'csv'
gem 'em-websocket'
gem 'i18n'
gem 'jekyll'
gem 'jekyll-admin'
gem 'jekyll-paginate'
gem 'jekyll-sass-converter'
gem 'jekyll-seo-tag'
gem 'jekyll-sitemap'
gem 'jekyll-toc'
gem 'jekyll-watch'
gem 'json'
gem 'kramdown'
gem 'kramdown-parser-gfm'
gem 'liquid'
gem 'listen'
gem 'mercenary'
gem 'nokogiri'
gem 'pathutil'
gem 'rack'
gem 'rackup'
gem 'rouge'
gem 'safe_yaml'
gem 'terminal-table'
gem 'webrick'

13
web/LICENSE Normal file
View file

@ -0,0 +1,13 @@
Copyright 2024 Johannes Findeisen <you@hanez.org>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

73
web/Makefile Normal file
View file

@ -0,0 +1,73 @@
all:
make release
build:
#wget -O ./handbook/handbook.md https://git.xw3.org/fun/fun/raw/branch/main/docs/handbook.md
bundle exec jekyll b --incremental
clean:
rm -rf _site/*
freshrelease:
make clean
make release
freshreleaseraw:
make clean
make build
make sync
freshrun:
make clean
make build
make minify
make run
local:
make clean
make build
make minify
localraw:
make clean
make build
localrelease:
make local
make minify
minify:
find ./_site -type f -name "*.html" -exec minify --html-keep-document-tags --html-keep-end-tags -o {} {} \;
find ./_site -type f -name "*.html" -exec sed -i 's/ \/>/>/g' {} +
#find ./_site -type f -name "*.html" -exec perl -0777 -pi -e 's/\n/ /g' {} +
find ./_site -type f -name "*.css" -exec minify --css-precision 0 -o {} {} \;
find ./_site -type f -name "*.xml" -exec minify -o {} {} \;
release:
make build
make minify
make sync
releaseraw:
make build
make sync
run:
bundle exec jekyll s --incremental --drafts
runclean:
make clean
bundle exec jekyll s --incremental --drafts
runcleanreload:
make clean
bundle exec jekyll s --incremental --drafts --livereload
runreload:
bundle exec jekyll s --incremental --drafts --livereload
sync:
rsync -avr --delete --delete-excluded ./_site/ fun-lang.xyz:/var/www/fun-lang.xyz/www/htdocs/
#ssh a.xw3.org 'cd /var/www/fun-lang.xyz/www/lib/ && git pull'
#ssh a.xw3.org 'cd /var/www/fun-lang.xyz/www/htdocs/cgi/bin/ && gcc index.c -o index'

10
web/README.md Normal file
View file

@ -0,0 +1,10 @@
# [fun-lang.xyz](https://fun-lang.xyz)
The [Fun Programming Language Website](https://fun-lang.xyz).
## Rules
- No target="_blank"
- No line numbers in "pre" tags
- More to come... ;)

0
web/_cache/.gitkeep Normal file
View file

115
web/_config.yml Normal file
View file

@ -0,0 +1,115 @@
document_root: /var/www/fun-lang.xyz/www/htdocs/
data_dir: /var/www/fun-lang.xyz/www/htdocs/
title: fun>
subtitle: The programming language that makes you have fun!
description: The programming language that makes you have fun!
keywords:
- fun
- static
- dynamic
- programming
- language
- c
- python
- scrpts
- repl
- type
- safety
author: Johannes Findeisen <you@hanez.org>
email: hanez@fun-lang.xyz
baseurl:
url: https://fun-lang.xyz
url_short: fun-lang.xyz
lang: en
os: GNU/Linux
charset: utf-8
libdir: /var/www/fun-lang.xyz/www/lib
license: CC BY-NC-SA
license_name: Attribution-NonCommercial-ShareAlike 4.0 International
license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/
mastodon: https://fosstodon.org/@fun
truncatewords_length: 100000
# Set to your git root and branch to show a link to the file source in the footer. Unset to disable.
git: https://git.xw3.org/fun/fun/
git_short: https://git.xw3.org
branch: src/branch/main/
lifetime: 3600
challenge_error: Invalid challenge result! Please try again... :(
mail_thank_you: Thank you for contacting me... :)
username: xw3
cookiebanner_text: This website uses cookies to provide you with a better online experience. Leave this site if you don't accept the usage of cookies. No tracking cookies are being used! To find out more, please visit this website's
cookiebanner_dismiss_text: Got it!
cookiebanner_link_text: Privacy Policy
cookiebanner_link: /privacy/
paginate: 2
paginate_path: /page/:num/
permalink: /:year/:month/:day/:title/
markdown: kramdown
highlighter: rouge
kramdown:
input: GFM
# syntax_highlighter_opts:
# Rouge Options https://github.com/jneen/rouge#full-options
# css_class: 'highlight'
#line_numbers: true # bad idea, spans don't need linenos and would inherit this option
# span:
# line_numbers: false
# block:
# line_numbers: true
# start_line: 1
tocTopTag: h2
anchorPrefix: ""
showToggleButton: false
contentsLabel: Table of contents
exclude:
- .idea/
- lib/
- venv/
- .project
- build.log
- Makefile
- README.md
- requirements.txt
- package.json
- package-lock.json
- xw3.code-workspace
category_archive:
path: /category/
plugins:
- jekyll-paginate
# - jekyll-seo-tag
- jekyll-sitemap
- jekyll-toc
# - jekyll-admin
# https://stackoverflow.com/questions/10218779/custom-variables-in-jekyll-front-matter
# https://github.com/gjtorikian/jekyll-conrefifier
# https://stackoverflow.com/questions/65989040/bundle-exec-jekyll-serve-cannot-load-such-file
# - jekyll-conrefifier
defaults:
-
scope:
path: "cgi/*"
values:
sitemap: false
-
scope:
path: "files/*"
values:
sitemap: false

0
web/_data/.gitkeep Normal file
View file

0
web/_drafts/.gitkeep Normal file
View file

26
web/_includes/footer.html Normal file
View file

@ -0,0 +1,26 @@
<footer class="site-footer">
<div class="wrapper">
<div class="footer-col-wrapper">
<!--<p style="text-align:center;">{% if site.git %}Source: <a href="{{ site.git }}{{ site.branch }}{{ page.path }}" class="git" target="_blank">{{ site.git }}{{ site.branch }}{{ page.path }}</a>{% endif %}</p>-->
<h2 style="display:none;">Navigation</h2>
<ul style="list-style:none;margin-left:0px;text-align:center;">
<li style="display:inline;"><a href="/" style="text-decoration:none;" title="Homepage" class="home">Homepage</a>&nbsp;-</li>
<!--<li style="display:inline;">&nbsp;<a href="/about/" style="text-decoration:none;" title="About" class="about">About</a>&nbsp;-</li>-->
<li style="display:inline;">&nbsp;<a href="/contact/" style="text-decoration:none;" title="Contact" class="mail">Contact</a>&nbsp;-</li>
<li style="display:inline;">&nbsp;<a href="/community/code-of-conduct/" style="text-decoration:none;" title="Code of Conduct" class="love">Code of Conduct</a>&nbsp;-</li>
<li style="display:inline;">&nbsp;<a href="/privacy/" style="text-decoration:none;" title="Privacy" class="privacy">Privacy</a>&nbsp;-</li>
<!--<li style="display:inline;">&nbsp;<a href="/search/" style="text-decoration:none;" title="Search" class="search">Search</a>&nbsp;-</li>-->
<li style="display:inline;">&nbsp;<a href="/feed/" style="text-decoration:none;" title="Blog Feed" class="rss">Blog Feed</a></li>
</ul>
<ul style="list-style:none;margin-left:0px;text-align:center;">
<li style="display:inline;">&nbsp;<a href="{{ site.git }}" style="text-decoration:none;" title="Git" class="git">Git</a>&nbsp;-</li>
<li style="display:inline;">&nbsp;<a href="{{ site.git }}issues" style="text-decoration:none;" title="Issues" class="bug">Issues</a>&nbsp;-</li>
<li style="display:inline;">&nbsp;<a href="{{ site.mastodon }}" style="text-decoration:none;" title="Mastodon" class="mastodon" rel="me">Mastodon</a>&nbsp;-</li>
<li style="display:inline;">&nbsp;<a href="{{ site.git }}wiki" style="text-decoration:none;" title="Wiki" class="wiki">Wiki</a></li>
</ul>
<p style="text-align:center;"><a href="/copyright/" style="text-decoration:none;" title="Copyright">Copyright</a> &copy; {{ site.time | date: "%Y" }} - Johannes Findeisen (<a href="https://git.xw3.org/hanez" class="user">hanez</a>)</p>
</div>
</div>
</footer>

18
web/_includes/head.html Normal file
View file

@ -0,0 +1,18 @@
<head>
<meta charset="{{ site.charset }}">
<meta name="author" content="{{ site.author }}">
<title>{{ site.title }} {{ page.title }} - {{ site.subtitle }}</title>
<meta name="description" content="{{ site.title }} - {{ site.description | strip_html | strip_newlines | truncate: 160 }}{% if page.description %} - {{ page.description | strip_html | strip_newlines | truncate: 160 }}{% endif %}">
{% if page.tags %}<meta name="keywords" content="{{ site.keywords | join: ',' }},{{ page.tags | join: ',' }}">{% endif %}
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="revisit-after" content="7 days">
<meta name="robots" content="index,follow">
<link rel="alternate" type="application/rss+xml" title="Blog Feed - {{ site.title }}" href="{{ site.url }}/feed/">
<link rel="canonical" href="{{ site.url }}{{ page.url | replace:'index.html','' }}">
<link rel="shortcut icon" type="image/png" href="/favicon.png">
<link rel="stylesheet" type="text/css" href="/css/cookieconsent.min.css">
<link rel="stylesheet" type="text/css" href="/css/main.css">
<script src="/js/jquery-3.6.4.min.js" charset="{{ site.charset }}"></script>
<script src="/js/js-cookie-3.0.5.min.js" charset="{{ site.charset }}"></script>
<script src="/js/matomo.min.js" charset="{{ site.charset }}"></script>
</head>

48
web/_includes/header.html Normal file
View file

@ -0,0 +1,48 @@
<header class="site-header">
<div class="wrapper">
<a class="site-title" href="/"><img src="/images/fun.png" alt="{{ site.title }}" style="border-radius: 12px; margin: 9px 0 18px 0" title="Fun"></a>
<nav class="site-nav" style="border-radius:8px;">
<a href="#" class="menu-icon"><span>&#8801;</span></a>
<div class="trigger">
<h2 style="display:none;">Navigation</h2>
<ul style="list-style: none;">
<li><a class="page-link" href="/" style="text-decoration:none;" title="/">/</a></li>
<li><a class="page-link" href="/about/" style="text-decoration:none;" title="/about/">/about/</a></li>
<li><a class="page-link" href="/community/" style="text-decoration:none;" title="/community/">/community/</a></li>
<li><a class="page-link" href="/contact/" style="text-decoration:none;" title="/contact/">/contact/</a></li>
<!--<li><a class="page-link" href="/development/" style="text-decoration:none;" title="/development/">/development/</a></li>-->
<li><a class="page-link" href="/documentation/" style="text-decoration:none;" title="/documentation/">/documentation/</a></li>
<!--<li><a class="page-link" href="/examples/" style="text-decoration:none;" title="/examples/">/examples/</a></li>-->
<!--<li><a class="page-link" href="/faq/" style="text-decoration:none;" title="/faq/">/faq/</a></li>-->
<!--
<li>----------------</li>
<li><a class="page-link" href="/account/" style="text-decoration:none;" title="/account/">/account/</a></li>
-->
<!--
https://www.w3schools.com/howto/howto_js_toggle_dark_mode.asp
https://dev.to/warish/how-to-create-a-dark-mode-toggle-with-html-css-and-javascript-378m
-->
<!--
<li><div class="toggle-container" id="themeToggle">
<svg class="sun-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
<svg class="moon-icon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
</div></li>
-->
</ul>
</div>
</nav>
</div>
</header>

31
web/_layouts/default.html Normal file
View file

@ -0,0 +1,31 @@
---
layout:
---
<!DOCTYPE html>
<html lang="{% if page.lang %}{{ page.lang }}{% else %}{{ site.lang }}{% endif %}" id="top">
{% include head.html %}
<body>
<div class="site">
<div id="loader" class="lds-dual-ring hidden overlay"></div>
{% include header.html %}
<div class="page-content">
<div class="wrapper">
{{ content }}
</div>
</div>
{% include footer.html %}
</div>
<p style="text-align: center; color: #e8e8e8; font-size: 12px;">
Page generated at: {{ site.time | date: "%b %-d, %Y" }} ({{ site.time | date: "%Z" }}) using <a href="https://jekyllrb.com/">Jekyll</a> and <a href="https://git.xw3.org/xw3/xw3">xw3</a> on {{ site.os }}<br>
<a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" style="text-decoration:none;" title="License"><img src="/images/by-nc-sa-88x31.png"></a></p>
<script src="/js/sorttable-2.min.js" charset="utf-8"></script>
<script src="/js/cookieconsent.min.js" data-cfasync="false"></script>
<!-- Source for documentation and download: https://www.osano.com/cookieconsent/download/ - https://www.osano.com/cookieconsent/documentation/compliance/ -->
<script>window.cookieconsent.initialise({"palette":{"popup":{"background":"#000","text":"#e8e8e8"},"button":{"background":"#bc6c21"}},"theme":"classic","position":"bottom","static":false,"content":{"message":"{{ site.cookiebanner_text }} ","dismiss":"{{ site.cookiebanner_dismiss_text }}","link":"{{ site.cookiebanner_link_text }}.","href":"{{ site.cookiebanner_link }}"}});</script>
</body>
</html>

21
web/_layouts/page.html Normal file
View file

@ -0,0 +1,21 @@
---
layout: default
---
<div class="post">
<header class="post-header">
<h1 class="post-title" id="terminal">{{ site.title }} {{ page.title }}</h1>
{% if page.noDate != true %}<p class="post-meta" style="padding: 0px 0px 0px 0px;">{% if page.date %}{{ page.date | date: "%b %-d, %Y %H:%M:%S" }} ({{ page.date | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}) - {% endif %}
Edited: {{ page.path | file_date | date: "%b %-d, %Y %H:%M:%S" }} ({{ page.path | file_date | date: "%Z" }}){% endif %}{% if page.author %}, <a href="{{ site.git_short }}/{{ page.author }}" target="_blank" class="user">{{ page.author }}</a>{% endif %}</p>
{% if page.subtitle %}<p style="padding: 0px 0px 0px 0px;">{{ page.subtitle }}</p>{% endif %}
</header>
<article class="post-content">
{{ content | toc_generate }}
{% if page.noComments != true %}
<h2>Comments</h2>
<section id="isso-thread"><noscript>Javascript needs to be activated to view comments.</noscript></section>
<script data-isso="/comments" src="/comments/js/embed.min.js"></script>
{% endif %}
</article>
</div>

23
web/_layouts/post.html Normal file
View file

@ -0,0 +1,23 @@
---
layout: default
---
<div class="post">
<header class="post-header">
<h1 class="post-title" id="terminal">{{ site.title }} {{ page.title }}</h1>
<p class="post-meta" style="padding: 0px 0px 0px 0px;">{% if page.date %}{{ page.date | date: "%b %-d, %Y %H:%M:%S" }}{% endif %}
{% if page.date and page.date_updated %} - {% endif %}
{% if page.date_updated %}Edited: {{ page.date_updated | date: "%b %-d, %Y %H:%M:%S" }}{% endif %}
{% if page.date or page.date_updated %} ({{ page.date | date: "%Z" }}){% endif %}{% if page.author %}, <a href="{{ site.git_short }}/{{ page.author }}" target="_blank" class="user">{{ page.author }}</a>{% endif %}</p>
</header>
<article class="post-content">
{{ content }}
{% if page.noComments != true %}
<h2>Comments</h2>
<section id="isso-thread"><noscript>Javascript needs to be activated to view comments.</noscript></section>
<script data-isso="/comments" src="/comments/js/embed.min.js"></script>
{% endif %}
<!--<p>Permalink: <a href="{{ page.url }}" title="{{ site.url }}{{ page.url }}">{{ site.url }}{{ page.url }}</a></p>-->
</article>
</div>

0
web/_plugins/.gitkeep Normal file
View file

12
web/_plugins/myFilters.rb Normal file
View file

@ -0,0 +1,12 @@
# https://stackoverflow.com/questions/14978474/how-to-show-the-modification-date-of-a-file-in-jekyll
module Jekyll
module MyFilters
def file_date(input)
File.mtime(input)
end
end
end
Liquid::Template.register_filter(Jekyll::MyFilters)

View file

@ -0,0 +1,144 @@
# This code was originally written by Davide Ficano:
# https://github.com/dafi/jekyll-toc-generator
# Thank you for that!
require 'nokogiri'
require 'digest/md5'
module Jekyll
module TOCGenerator
TOGGLE_HTML = '<div id="toctitle"><h2>%1</h2>%2</div>'
TOC_CONTAINER_HTML = '<div id="toc-container">%1<ul>%2</ul></div>'
def toc_generate(html)
# No Toc can be specified on every single page
# For example the index page has no table of contents
no_toc = @context.environments.first["page"]["noToc"] || false;
if no_toc
return html
end
config = @context.registers[:site].config
# Minimum number of items needed to show TOC, default 0 (0 means no minimum)
min_items_to_show_toc = config["minItemsToShowToc"] || 0
anchor_prefix = config["anchorPrefix"] || 'tocAnchor-'
# better for traditional page seo, commonlly use h1 as title
toc_top_tag = config["tocTopTag"] || 'h1'
toc_top_tag = toc_top_tag.gsub(/h/, '').to_i
if toc_top_tag > 5
toc_top_tag = 5
end
toc_sec_tag = toc_top_tag + 1
toc_top_tag = "h#{toc_top_tag}"
toc_sec_tag = "h#{toc_sec_tag}"
# Text labels
contents_label = config["contentsLabel"] || 'Contents'
hide_label = config["hideLabel"] || 'hide'
show_label = config["showLabel"] || 'show'
show_toggle_button = config["showToggleButton"]
toc_html = ''
toc_level = 1
toc_section = 1
item_number = 1
level_html = ''
doc = Nokogiri::HTML(html)
# Find H1 tag and all its H2 siblings until next H1
doc.css(toc_top_tag).each do |tag|
# TODO This XPATH expression can greatly improved
ct = tag.xpath("count(following-sibling::#{toc_top_tag})")
sects = tag.xpath("following-sibling::#{toc_sec_tag}[count(following-sibling::#{toc_top_tag})=#{ct}]")
level_html = '';
inner_section = 0;
sects.map.each do |sect|
inner_section += 1;
#anchor_id = anchor_prefix + toc_level.to_s + '-' + toc_section.to_s + '-' + inner_section.to_s
anchor_id = anchor_prefix + Digest::SHA256.hexdigest(tag.text + sect.text);
anchor_id = anchor_id[0..7];
sect['id'] = "#{anchor_id}"
level_html += create_level_html(anchor_id,
toc_level + 1,
toc_section + inner_section,
item_number.to_s + '.' + inner_section.to_s,
sect.text,
'')
end
if level_html.length > 0
level_html = '<ul>' + level_html + '</ul>';
end
#anchor_id = anchor_prefix + toc_level.to_s + '-' + toc_section.to_s;
anchor_id = anchor_prefix + Digest::SHA256.hexdigest(tag.text);
anchor_id = anchor_id[0..7];
tag['id'] = "#{anchor_id}"
toc_html += create_level_html(anchor_id,
toc_level,
toc_section,
item_number,
tag.text,
level_html);
toc_section += 1 + inner_section;
item_number += 1;
end
#toc_html += create_level_html("ccba53",
# 1,
# toc_section,
# item_number,
# "Comments",
# "");
# for convenience item_number starts from 1
# so we decrement it to obtain the index count
toc_index_count = item_number - 1
if toc_html.length > 0
hide_html = '';
if (show_toggle_button)
hide_html = HIDE_HTML.gsub('%1', hide_label)
end
if min_items_to_show_toc <= toc_index_count
replaced_toggle_html = TOGGLE_HTML
.gsub('%1', contents_label)
.gsub('%2', hide_html);
toc_table = TOC_CONTAINER_HTML
.gsub('%1', replaced_toggle_html)
.gsub('%2', toc_html);
doc.css('body').children.before(toc_table)
end
doc.css('body').children.to_xhtml(indent:3, indent_text:" ")
else
return html
end
end
private
def create_level_html(anchor_id, toc_level, toc_section, tocNumber, tocText, tocInner)
link = '<a href="#%1"><span class="tocnumber">%2</span> <span class="toctext">%3</span></a>%4'
.gsub('%1', anchor_id.to_s)
.gsub('%2', tocNumber.to_s)
.gsub('%3', tocText)
.gsub('%4', tocInner ? tocInner : '');
'<li class="toc_level-%1 toc_section-%2">%3</li>'
.gsub('%1', toc_level.to_s)
.gsub('%2', toc_section.to_s)
.gsub('%3', link)
end
end
end
Liquid::Template.register_filter(Jekyll::TOCGenerator)

0
web/_posts/.gitkeep Normal file
View file

View file

@ -0,0 +1,21 @@
---
layout: post
published: true
author: hanez
title: Init Fun!
description: Blog - Init Fun!
date: 2025-10-05
_date_updated: 2024-02-07
categories:
- news
- project
tags:
- fun
- programming
- static
- dynamic
- language
---
Initial homepage... no content actually!

View file

@ -0,0 +1,177 @@
---
layout: post
published: true
author: hanez
noToc: false
title: Announcing Fun 0.37.62
description: Homepage and Blog
date: 2026-01-25
date_updated: 2026-01-31 21:45:03
categories:
- news
- project
tags:
- fun
- programming
- static
- dynamic
- language
---
### First at all! Special thanks go to my wonderful girlfriend Sabine, my friends [Armin](https://m2m.pm/){:class="ext"} and [Ole](https://schizzoteam.org/){:class="ext"}, who motivated me over the past month to implement this. Cheers! Markus, I miss YOU, R.I.P!
We're excited to announce the release of Fun version 0.37.62, the latest iteration of our experimental programming language that prioritizes simplicity, consistency, and most importantly — joy in coding.
[Link to Hackernews post](https://news.ycombinator.com/item?id=46787331){:class="ext"}.
### What's Fun All About?
Fun is a highly strict yet highly simple programming language that draws inspiration from Bash, C, Lua, PHP, Python, and Rust. If you love Python's clean syntax but want something with stricter rules and built-in type safety, Fun might be worth exploring. It's dynamically typed with optional static typing, written in C (C99) and Fun itself, and designed to be small, embeddable, and hackable. More on the [about](https://fun-lang.xyz/about/) page.
### Important: This is an Experiment
Please note: Fun is an experimental language and should be treated as such. While Fun works, it has many known and unknown bugs. We will not declare Fun as stable until we reach the 1.0 release. This is a project born out of curiosity and passion for elegant code, not production readiness — at least not yet.
### What Makes Fun... Fun?
#### Philosophy
Fun is built on the idea that coding should be enjoyable, elegant, and consistent. Our manifesto includes core principles like:
- Fun is Fun Programming should spark creativity, not frustration
- Fun Uses Nothing Minimalism is power; no unnecessary features or syntax variations
- Indentation is Truth Two spaces, always (no tabs, no debates, no four-space wars)
- One Way to Do It No clutter, no 15 ways of writing the same thing. Simplicity means clarity
- Hackable by Nature Small and embeddable, like Lua. Easy to understand, extend, and tinker with
- Beautiful Defaults A language that doesn't need linters, formatters, or style guides. Beauty is built in
### What's New in Specification v0.3 (and Fun 0.37.62)
This release brings Fun closer to its vision with significant language enhancements:
- Object-Oriented Programming Classes and objects with methods, constructors, and inheritance using extends
- Explicit this in method definitions for clarity
- Private members by convention (leading underscore)
- Dot-call syntax sugar for clean method invocations: obj.method(a, b)
<pre>
class Counter
value = 0
fun inc(this)
this.value = this.value + 1
return this.value
c = Counter()
print(c.inc()) // 1
</pre>
### Module System
- Namespaced includes with #include <path> as alias for clean imports
- Organize code into reusable modules without naming conflicts
<pre>
#include <utils/math.fun> as m
print(m.add(2, 3)) // 5
</pre>
### Enhanced Type System
- Fixed-width integers: int8, uint8, int16, uint16, int32, uint32, int64, uint64
- Maps/dictionaries: map<K, V> with literal syntax { "key": value }
- Typed arrays: array<T> for type-safe collections
- Byte type for low-level operations
### Concurrency Support
- Thread primitives: thread_spawn, thread_join, and sleep
- Write concurrent programs with ease
<pre>
fun square(n)
sleep(100)
return n * n
tid = thread_spawn(square, 5)
print(thread_join(tid)) // 25
</pre>
### Control Flow Improvements
- Loop control: break and continue statements
- Exception handling: try/catch/finally syntax (runtime implementation evolving)
### System and Network Integration
- Process execution: Blocking (exec, system) and non-blocking (nexec, nspawn) with process management
- TCP and Unix domain sockets: Build networked applications
- Serial port support: Communicate with hardware devices
- Environment variables: Access with env(NAME)
- CLI argument handling: Parse command-line arguments
### Additional Features
- Bitwise operations: band, bor, bxor, bnot, shl
- Rich standard library with modules for cryptography (MD5, SHA1/256/384/512, CRC32), encoding (Base64, hex), JSON, XML, INI, regular expressions (PCRE2), datetime utilities, and more
- Optional extensions for cURL, SQLite/libSQL, PC/SC smart cards, and Tk GUI toolkit
### Core Language Features
Fun provides a clean, readable syntax with:
- Strict indentation-based structure (2 spaces, no semicolons)
- Type safety with no implicit numeric coercions
- Bounds-checked operations to prevent common errors
- Higher-order functions: map, filter, reduce for functional programming
- Multiple return values from functions
- Comprehensive built-ins for common tasks
### The Community: Fun Unites Nerds
Fun isn't about being the fastest or most feature-rich language — it's about sharing the joy of coding. We welcome contributors who are:
- Respectful
- Curious
- Creative
A language that feels like home for developers who love minimal, elegant tools, believe consistency is freedom, and want to write code that looks good and feels good.
### Want to Participate?
Everybody is welcome to participate! However, before you can get started, you need to contact me at [hanez@fun-lang.org](mailto:hanez@fun-lang.org){:class="mail"} to request an account on our Git server.
Important: Fun is not developed on third-party Git servers like GitHub or GitLab. All Fun infrastructure is self-hosted at git.xw3.org. This keeps us independent and aligned with the hacker spirit of the project — we control our tools, our code, and our community.
### Getting Started
If you're curious about Fun, check out:
- [Website](https://fun-lang.xyz)
- [Git Repository](https://git.xw3.org/fun/fun){:class="git"}
- [Fun Handbook](https://git.xw3.org/fun/fun/src/branch/main/docs/handbook.md){:class="git"}
- [Fun REPL Guide](https://git.xw3.org/fun/fun/src/branch/main/docs/repl.md){:class="git"}
- [Specification v0.3](https://git.xw3.org/fun/fun/src/branch/main/spec/v0.3.md){:class="git"}
- [Examples](https://git.xw3.org/fun/fun/src/branch/main/examples){:class="git"}
- [Standard Library](https://git.xw3.org/fun/fun/src/branch/main/lib){:class="git"}
- [Community](https://fun-lang.xyz/community/)
The examples directory contains demonstrations of most Fun features, from basic "Hello, World!" to threading, networking, classes, and more. The lib directory includes modules written in Fun itself — and in the future, most enhancements will be written in Fun rather than C.
### For Developers
- [Fun Internals](https://git.xw3.org/fun/fun/src/branch/main/docs/internals.md){:class="git"}
- [Fun Opcodes](https://git.xw3.org/fun/fun/src/branch/main/docs/opcodes.md){:class="git"}
- [Basic Rust Opcodes Support](https://git.xw3.org/fun/fun/src/branch/main/docs/rust.md){:class="git"}
### The Road Ahead
Documentation is a work in progress as we continue debugging, fixing bugs, and evolving the language. Complete API documentation will follow in future releases. Version 0.37.62 represents substantial progress, but remember: this is an experiment, and stability won't be declared until we reach 1.0.
Fun may not change the world, but it aims to make programming a little more fun. We're on a journey, and we'd love to have you along for the ride — bugs and all.
Fun is and will always be 100% free under the terms of the [Apache-2.0 License](https://opensource.org/license/apache-2-0){:class="ext"}.
Happy hacking, and remember: Fun is Fun!
Johannes Findeisen (hanez) - [hanez@fun-lang.org](mailto:hanez@fun-lang.org){:class="mail"}

0
web/_sass/.gitkeep Normal file
View file

188
web/_sass/_base.scss Normal file
View file

@ -0,0 +1,188 @@
html {
margin: 0;
padding: 0;
}
body, h1, h2, h3, h4, h5, h6, p, code, blockquote,
pre, hr, dl, dd, ol, ul, figure, span {
margin: 0;
padding: 0;
}
body {
background: $background-color;
//background-color: $background-color;
//background-image: url("/images/fractalized.jpg");
//background-repeat: no-repeat;
//background-attachment: fixed;
//background-size: 100%;
color: $text-color;
font-family: $base-font-family;
font-size: $base-font-size;
font-weight: 300;
line-height: $base-line-height;
}
h1, h2, h3, h4, h5, h6 {
color: $headline-color;
padding-top: 18px;
}
h1 {
color: $headline-color;
padding-top: 0px;
}
h2 {
> a,
a:link,
a:visited {
text-decoration: none;
}
}
img {
max-width: 100%;
vertical-align: middle;
}
img.l {
border: 0;
float: left;
margin: 6px 16px 0 0;
padding: 0;
}
img.r {
border: 0;
float: right;
margin: 6px 0 0 16px;
padding: 0;
}
img.x {
max-width: 99.8%;
border: 1px solid #000;
}
ul, ol {
margin: 0 0 0 25px;
padding: 0 0 12px 0;
}
li {
> ul,
> ol {
margin-bottom: 0;
}
}
p {
padding: 0px 0px 14px 0px;
}
blockquote {
color: $grey-color;
border-left: 4px solid $grey-color-light;
font-size: 18px;
font-style: italic;
letter-spacing: -1px;
padding-left: calc($spacing-unit / 2);
> :last-child {
margin-bottom: 0;
}
}
pre {
background: $grey-color-dark;
/*background-image: -webkit-linear-gradient($grey-color-dark 50%, $grey-color-light 50%);
background-image: -moz-linear-gradient($grey-color-dark 50%, $grey-color-light 50%);
background-image: -ms-linear-gradient($grey-color-dark 50%, $grey-color-light 50%);
background-image: -o-linear-gradient($grey-color-dark 50%, $grey-color-light 50%);
background-image: linear-gradient($grey-color-dark 50%, $grey-color-light 50%);*/
background-position: 0 0;
background-repeat: repeat;
background-size: 2.8em 2.8em;
border: 0px $grey-color solid;
border-radius: 8px;
counter-reset: line-numbering;
font-family: $base-font-family;
font-size: $base-font-size;
// https://stackoverflow.com/questions/5840328/styling-each-line-inside-pre-with-css
line-height: 1.4em;
margin: 0 0 0 0;
overflow: auto;
overflow-x: auto;
padding: 8px;
tab-size: 2;
-moz-tab-size: 2;
}
/*pre::before {
content: counter(linex);
counter-increment: linex;
padding-right: 1em;
width: 1.5em;
text-align: right;
opacity: 0.5;
}*/
/*pre > code {
font-family: $base-font-family;
font-size: $base-font-size;
counter-increment: line;
margin: 0 0 0 0;
padding: 0 0 0 0;
}*/
/**pre > code:before{
content: counter(line);
display: inline-block;
width: 2.0em;
border-right: 1px solid $grey-color;
padding-right: .7em;
margin-right: .7em;
color: #bc6c21;
-webkit-user-select: none;
text-align: right;
}**/
audio {
height: 24px;
width: 100%;
}
table {
border: 0px solid black;
//border-collapse: collapse;
}
table > thead > tr {
}
table > thead > tr > th {
background: $tablehead-color;
border: 0px solid black;
color: white;
padding: 4px;
}
table > tbody > tr:nth-child(even) {
background: $grey-color-light;
}
table > tbody > tr:nth-child(odd) {
background: $grey-color-dark;
}
table > tbody > tr > td {
border: 0px solid black;
padding: 4px;
}
table.sortable th:not(.sorttable_sorted):not(.sorttable_sorted_reverse):not(.sorttable_nosort):after {
content: " \25B4 \25BE"
}

9
web/_sass/_fonts.scss Normal file
View file

@ -0,0 +1,9 @@
@font-face {
font-family: "CPS";
src: url("../fonts/Courier-Prime-Sans.ttf");
}
@font-face {
font-family: "MDI";
src: url("../fonts/materialdesignicons-webfont.woff2") format("woff2");
}

126
web/_sass/_forms.scss Normal file
View file

@ -0,0 +1,126 @@
// Contact form
#contactform {
//padding: 20px;
//border: 1px solid $grey-color;
//background: $grey-color-light;
//display: inline;
}
#contactform label, #contactform input, #contactform textarea {
display: block;
width: 98%;
resize: none;
}
#contactform textarea {
height: 120px;
}
#contactform label { margin: 10px 0; }
#contactform label:first-child { margin-top: 0; }
#contactform input, #contactform textarea {
font-family: $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
font-weight: 300;
padding: 10px;
margin-bottom: 10px;
border: 1px solid $grey-color;
}
#contactform input[type=submit] {
border: 0;
color: #fff;
background: $brand-color;
cursor: pointer;
width: 100%;
}
#contactform input[type=submit]:hover {
background: $headline-color;
}
// Login form
#loginform {
//background: $grey-color-light;
//border: 1px solid $grey-color;
display: inline;
//padding: 20px;
//width: 380px;
}
#loginform label, #loginform input{
//display: block;
resize: none;
}
#loginform label { margin: 10px 0; }
#loginform label:first-child { margin-top: 0; }
#loginform input {
border: 1px solid $grey-color;
font-family: $base-font-family;
line-height: $base-line-height;
font-size: $base-font-size;
//font-weight: 300;
margin: 10px;
padding: 10px;
}
#loginform input[type=submit] {
border: 0;
background: $brand-color;
color: #fff;
cursor: pointer;
}
#loginform input[type=submit]:hover {
background: $headline-color;
}
// Search form
#searchform {
//padding: 20px;
//border: 1px solid $grey-color;
//background: $grey-color-light;
}
#searchform label, #searchform input, #searchform textarea {
display: block;
width: 98%;
resize: none;
}
#searchform textarea {
height: 120px;
}
#searchform label { margin: 10px 0; }
#searchform label:first-child { margin-top: 0; }
#searchform input, #searchform textarea {
font-family: $base-font-family;
font-size: $base-font-size;
line-height: $base-line-height;
font-weight: 300;
padding: 10px;
margin-bottom: 10px;
border: 1px solid $grey-color;
}
#searchform input[type=submit] {
border: 0;
color: #fff;
background: $brand-color;
cursor: pointer;
width: 100%;
}
#searchform input[type=submit]:hover {
background: $headline-color;
}

61
web/_sass/_highlight.scss Normal file
View file

@ -0,0 +1,61 @@
/*.highlight { background: #ffffff; }*/
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { font-weight: bold } /* Keyword */
.highlight .o { font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { font-weight: bold } /* Keyword.Constant */
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d14 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
.highlight .sc { color: #d14 } /* Literal.String.Char */
.highlight .sd { color: #d14 } /* Literal.String.Doc */
.highlight .s2 { color: #d14 } /* Literal.String.Double */
.highlight .se { color: #d14 } /* Literal.String.Escape */
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
.highlight .si { color: #d14 } /* Literal.String.Interpol */
.highlight .sx { color: #d14 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d14 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */

44
web/_sass/_isso.scss Normal file
View file

@ -0,0 +1,44 @@
.isso-input-wrapper {
margin: 0px;
padding: 0px;
width: 238px;
}
.isso-input-wrapper input {
box-shadow: 0 0 0 0;
margin-top: 3px;
}
.isso-input-wrapper input[type="email"] {
box-shadow: 0 0 0 0;
}
.isso-input-wrapper input[type="text"] {
box-shadow: 0 0 0 0;
}
.isso-textarea-wrapper textarea {
border-radius: 0;
box-shadow: 0 0 0 0;
}
#isso-postbox-author, #isso-postbox-email, #isso-postbox-website, .isso-post-action input, .isso-textarea {
border-radius: 0;
font-family: $base-font-family;
font-size: $base-font-size;
}
.isso-post-action input[type=button], .isso-post-action input[type=submit] {
border: 0;
color: #fff;
background: $brand-color;
cursor: pointer;
margin-top: 3px;
padding: 6px 18px 6px 18px;
width: 100%;
}
.isso-post-action input[type=button]:hover, .isso-post-action input[type=submit]:hover {
background: $headline-color;
}

401
web/_sass/_layout.scss Normal file
View file

@ -0,0 +1,401 @@
.site {
//border-radius: 12px 12px;
border: 1px solid #000;
border-radius: 8px;
background-color: #fcfbf9;
max-width: -webkit-calc(#{$content-width} - (#{$spacing-unit} * 2));
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
margin-right: auto;
margin-left: auto;
margin-top: 4px;
margin-bottom: 4px;
//box-shadow: 0px 0px 3px #000;
}
.pagination {
margin-top: $spacing-unit;
margin-bottom: $spacing-unit;
text-align: center;
}
.site-header {
min-height: 56px;
position: relative;
}
.site-title {
line-height: 56px;
margin-bottom: 0;
float: left;
}
.site-nav {
float: right;
z-index: 998;
position: absolute;
top: 18px;
right: 18px;
background-color: white;
border: 1px solid $brand-color;
//border-radius: 6px;
text-align: right;
text-decoration: none;
.menu-icon {
display: block;
float: right;
width: 36px;
height: 26px;
line-height: 0;
padding-top: 10px;
text-align: center;
text-decoration: none;
//> svg {
// width: 18px;
// height: 15px;
// path {
// fill: $grey-color-dark;
// }
//}
> span {
align-items: center;
justify-content: center;
display: flex;
flex-direction: column;
font-size: 24px;
padding-top: 10px;
}
}
.trigger {
clear: both;
display: none;
}
&:hover .trigger {
display: block;
//padding-bottom: 5px;
//text-decoration: none;
//color: $brand-color;
}
.page-link {
display: block;
padding: 5px 10px;
}
}
/*.ham-menu {
display: inline-block;
position: relative;
margin: 2px 0;
}
.ham-menu, .ham-menu::before, .ham-menu::after {
width: 100px;
height: 20px;
border-radius: 7px;
background-color: black;
}
.ham-menu::before, .ham-menu::after {
content: "";
display: block;
position: absolute;
}
.ham-menu::before {
bottom: 130%;
}
.ham-menu::after {
top: 130%;
}*/
.site-footer {
margin: calc($spacing-unit / 4);
//border-radius: 12px 12px;
//background-color: $grey-color-light;
//border: 1px solid $grey-color;
}
.footer-col-wrapper {
margin-left: calc($spacing-unit / 2);
@extend %clearfix;
}
.footer-col {
float: left;
margin-bottom: calc($spacing-unit / 2);
padding-left: calc($spacing-unit / 2);
}
@include media-query($on-palm) {
.footer-col {
float: none;
width: -webkit-calc(100% - (#{$spacing-unit} / 2));
width: calc(100% - (#{$spacing-unit} / 2));
}
}
.page-content {
}
.page-heading {
}
.post-list {
margin-left: 0;
list-style: none;
> li {
margin-bottom: $spacing-unit;
}
}
.post-meta {
font-size: $small-font-size;
color: $grey-color;
}
.post-link {
display: block;
font-size: 24px;
}
.post-header {
margin-bottom: $spacing-unit;
}
.post-title {
letter-spacing: -1px;
line-height: 1;
@include media-query($on-laptop) {
}
}
.post-content {
margin-bottom: $spacing-unit;
}
.post-content img {
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
min-width: 100%;
height: 100%;
min-height: 100%;
background: rgba(0,0,0,.8);
z-index: 999;
opacity: 1;
transition: all 0.5s;
}
.wrapper {
max-width: calc(#{$content-width} - (#{$spacing-unit} * 2));
margin-right: auto;
margin-left: auto;
padding-right: $spacing-unit;
padding-left: $spacing-unit;
padding-top: calc($spacing-unit / 2);
padding-bottom: 0;
@extend %clearfix;
@include media-query($on-laptop) {
max-width: calc(#{$content-width} - (#{$spacing-unit}));
padding-right: calc($spacing-unit / 2);
padding-left: calc($spacing-unit / 2);
}
}
%clearfix {
&:after {
content: "";
display: table;
clear: both;
}
}
.icon {
> svg {
display: inline-block;
width: 16px;
height: 16px;
vertical-align: middle;
path {
fill: $grey-color;
}
}
}
.pagination a, span {
margin-left: 4px;
margin-right: 4px;
}
span.feed {
border: 1px solid;
border-color: #FC9 #630 #330 #F96;
padding: 0 3px;
font: bold 0.4em sans-serif;
color: #fff;
background: #f60;
text-decoration: none;
margin: 0;
}
#topbutton {
text-align: center;
padding: 0;
width: 46px;
height: 46px;
background: $topbutton-color url(/images/up-arrow.png) no-repeat center center;
border: 1px solid $grey-color-dark;
position: fixed;
bottom: 10px;
right: 10px;
cursor: pointer;
}
span.cursor {
color: #FF9500;
display: inline-block;
background: transparent;
margin-left: 1px;
animation: 1s blink step-end infinite;
}
@keyframes "blink" bold {
from, to {
color: transparent;
}
50% {
color: black;
}
}
@-webkit-keyframes "blink" bold {
from, to {
color: transparent;
}
50% {
color: black;
}
}
@-ms-keyframes "blink" bold {
from, to {
color: transparent;
}
50% {
color: black;
}
}
@-o-keyframes "blink" {
from, to {
color: transparent;
}
50% {
color: black;
}
}
#pages {
text-align: center;
}
#pages a:link,
#pages a:visited,
#pages strong {
float: left;
width: 1.8em;
border: 1px solid #000;
font-weight: bold;
text-decoration: none;
text-align: center;
margin: 0px 4px 4px 0;
padding: 2px;
background: $brand-color;
color: #fff;
}
#pages > a.active {
color: $grey-color-light;
background: #fff;
border-color: $grey-color;
}
#pages a:focus,
#pages a:hover,
#pages a:active {
color: $hover-color;
background: #fff;
}
#pages p {
float: left;
width: 100%;
}
#notify {
padding: 10px;
margin-bottom: 20px;
border: 1px solid $grey-color;
background: $headline-color;
}
.lds-dual-ring.hidden {
display: none;
}
.lds-dual-ring {
display: inline-block;
width: 80px;
height: 80px;
}
.lds-dual-ring:after {
content: " ";
display: block;
width: 64px;
height: 64px;
margin: 5% auto;
border-radius: 50%;
border: 6px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
@keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
#terminal::before {
content: "";
}
@media (prefers-reduced-motion: no-preference) {
@keyframes flash {
50% { opacity: 0; }
}
@keyframes reveal {
from { width: 2em; }
to { width: 100%; }
}
#terminal {
animation: reveal 6s linear;
overflow: hidden;
text-overflow: "";
white-space: nowrap;
}
#terminal::after {
animation: flash 1.5s step-end infinite;
content: "";
}
}

269
web/_sass/_links.scss Normal file
View file

@ -0,0 +1,269 @@
a {
color: $brand-color;
//display: inline-block;
//position: relative;
}
a:link {
text-decoration: underline;
}
a:visited {
color: $brand-color;
text-decoration: underline;
}
a:focus,
a:hover {
color: $hover-color;
text-decoration: none;
text-shadow: $hover-color 0px 0px 6px;
}
a:active {
color: $hover-color;
text-decoration: none;
}
// https://stackoverflow.com/questions/2011142/how-to-change-the-style-of-the-title-attribute-inside-an-anchor-tag
// https://css-tricks.com/css-content/
/*a[title]:hover::after {
background: rgba(0,0,0,1.0);
//content: attr(title);
//position: absolute;
//top: -100%;
//left: 0;
border-radius: 0px;
//border: 1px solid red;
//color: #fff;
//background: $brand-color;
}*/
a.bug::after {
content: "\F0A30";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.bug:hover::after {
color: $hover-color;
}
a.chat::after {
content: "\F0EDE";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.chat:hover::after {
color: $hover-color;
}
a.code::after {
content: "\F102B";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.code:hover::after {
color: $hover-color;
}
a.commit::after {
content: "\F05D6";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.commit:hover::after {
color: $hover-color;
}
a.community::after {
content: "\F112D";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.community:hover::after {
color: $hover-color;
}
a.cube::after {
content: "\F01A7";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.cube:hover::after {
color: $hover-color;
}
a.document::after {
content: "\F09EE";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.document:hover::after {
color: $hover-color;
}
a.ext::after {
content: "\F03CC";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.ext:hover::after {
color: $hover-color;
}
a.file::after {
content: "\F0224";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.file:hover::after {
color: $hover-color;
}
a.git::after {
content: "\F02A2";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.git:hover::after {
color: $hover-color;
}
a.home::after {
content: "\F06A1";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.home:hover::after {
color: $hover-color;
}
a.love::after {
content: "\F02D5";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.love:hover::after {
color: $hover-color;
}
a.mail::after {
content: "\F01F0";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.mail:hover::after {
color: $hover-color;
}
a.mastodon::after {
content: "\F0AD1";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.mastodon:hover::after {
color: $hover-color;
}
a.privacy::after {
content: "\F0CC8";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.privacy:hover::after {
color: $hover-color;
}
a.rss::after {
content: "\F046B";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.rss:hover::after {
color: $hover-color;
}
a.search::after {
content: "\F0349";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.search:hover::after {
color: $hover-color;
}
a.user::after {
content: "\F0013";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.user:hover::after {
color: $hover-color;
}
a.wiki::after {
content: "\F1CCC";
color: $base-icon-color;
font-family: $base-icon-font-family;
font-size: $base-icon-size;
padding-left: 5px;
}
a.wiki:hover::after {
color: $hover-color;
}

17
web/_sass/_toc.scss Normal file
View file

@ -0,0 +1,17 @@
//#toc-container h2 {
// font-size: 1.4em;
//}
#toc-container ul {
list-style-image: none;
list-style-type: none;
margin-left: $spacing-unit;
//margin:0;
//padding: 0;
//text-align: left;
}
#toc-container ul li {
list-style-type: none;
padding-left: 0;
}

0
web/_site/.gitkeep Normal file
View file

0
web/_tmp/.gitkeep Normal file
View file

124
web/about/about.md Normal file
View file

@ -0,0 +1,124 @@
---
layout: page
title: About
subtitle: More information about having fun... :)
description: About
metasub: news
noToc: true
noDate: false
tags:
- fun
- programming
- language
- about
_description: The programming language that just makes fun!
noComments: true
permalink: /about/
---
## What is Fun?
Fun is an experiment, just for fun, but Fun works!
Fun is a highly strict programming language, but also highly simple. It looks like Python (My favorite language), but there are differences.
Influenced by **[Bash](https://www.gnu.org/software/bash/){:class="ext"}**, **[C](https://en.wikipedia.org/wiki/The_C_Programming_Language){:class="ext"}**, **[Lua](https://www.lua.org/){:class="ext"}**, PHP, **[Python](https://www.python.org/){:class="ext"}**, and a little Rust (Most influences came from linked languages).
Fun is and will ever be 100% free under the terms of the [Apache-2.0 License](https://opensource.org/license/apache-2-0){:class="ext"}.
## Idea
- Simplicity
- Consistency
- Simple to extend
- Hackable
- Joy in coding
- Fun!
## Characteristics
- Dynamic and optionally statically typed
- Type safety
- Written in C (C99) and Fun
- Internal libs are written with no_camel_case even when written in Fun, except class names
- Only a minimal function set is written in C, and most other core functions and libraries are implemented in Fun
## The Fun Manifesto
Fun is a programming language built on a simple idea:
Coding should be enjoyable, elegant, and consistent.
### Philosophy
- **Fun is Fun**<br>
Programming should spark creativity, not frustration. Code in Fun feels light, playful, and rewarding.
- **Fun Uses Nothing**<br>
Minimalism is power. No unnecessary features, no endless syntax variations, no formatting debates. Just clean, uniform code.
- **Indentation is Truth**<br>
Two spaces, always. No tabs, no four-space wars. Code should look the same everywhere, from your laptop to /usr/bin/fun.
- **One Way to Do It**<br>
No clutter, no 15 ways of writing the same thing. Simplicity means clarity.
- **Hackable by Nature**<br>
Fun should be small and embeddable, like Lua. Easy to understand, extend, and tinker with — true to the hacker spirit.
- **Beautiful Defaults**<br>
A language that doesnt need linters, formatters, or style guides. Beauty is built in.
## The Community
Fun is not about being the fastest or the most feature-rich. Its about sharing joy in coding. The community should be:
- Respectful
- Curious
- Creative
Like the name says: Fun Unites Nerds.
Please visit the [Fun Community Page](https://fun-lang.xyz/community/){:class="git"} to get in touch.
## The Goal
A language that feels like home for developers who:
- Love minimal, elegant tools
- Believe consistency is freedom
- Want to write code that looks good and feels good
Fun may not change the world — but it will make programming a little more fun.
## Features
### Core
- functions/classes/objects
- if/else if/else
- try/catch/finally
and much more...
Look at the examples here: [https://git.xw3.org/fun/fun/src/branch/main/examples](https://git.xw3.org/fun/fun/src/branch/main/examples){:class="ext"}
### Lib
See [https://git.xw3.org/fun/fun/src/branch/main/lib](https://git.xw3.org/fun/fun/src/branch/main/lib) for what the standard library provides.
### Extensions (only Linux actually)
- [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface){:class="ext"} support builtin using [kcgi](https://kristaps.bsd.lv/kcgi/){:class="ext"} (optional) <span style="color:red;font-weight:bold;">&#9744;</span>
- [cURL](https://curl.se/){:class="ext"} support builtin using [libcurl](https://curl.se/libcurl/){:class="ext"} (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [INI](https://en.wikipedia.org/wiki/INI_file){:class="ext"} support builtin using [iniparser](https://gitlab.com/iniparser/iniparser/){:class="ext"} (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [JSON](https://www.json.org/){:class="ext"} support builtin using [json-c](https://github.com/json-c/json-c){:class="ext"} (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [PCRE2](https://pcre2project.github.io/pcre2/){:class="ext"} support builtin for Perl-Compatible Regular Expressions (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [PCSC](https://pcscworkgroup.com/){:class="ext"} smart card support builtin using [PCSC lite](https://pcsclite.apdu.fr/){:class="ext"} (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [SQLite](https://sqlite.org/){:class="ext"} support builtin (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
- [XML](https://www.w3.org/XML/){:class="ext"} support builtin using [libxml2](https://gitlab.gnome.org/GNOME/libxml2/-/wikis/home){:class="ext"} (optional) <span style="color:green;font-weight:bold;">&#9745;</span>
<span style="color:green;font-weight:bold;">&#9745;</span> = Done / <span style="color:red;font-weight:bold;">&#9744;</span> = Planned or in progress.
Note: Not all of the above features will be implemented. Those who are marked "Done" will probably remain in Fun, but I don't know actually... ;)
There are some libs written in Fun available in the [./lib/](https://git.xw3.org/fun/fun/src/branch/main/lib){:class="ext"} diretory. In the future most Fun enhancements should be written in Fun itself.
## Code
- [https://git.xw3.org/fun/fun/](https://git.xw3.org/fun/fun/){:class="git"}

View file

@ -0,0 +1,27 @@
---
permalink: /cgi/challenge/
---
<?php
session_start();
session_set_cookie_params(3600);
date_default_timezone_set("{{ site.timezone }}");
if(isset($_SESSION["one"])) {
unset($_SESSION["one"]);
}
if(isset($_SESSION["two"])) {
unset($_SESSION["two"]);
}
$_SESSION["one"] = rand(0, 9);
$_SESSION["two"] = rand(0, 9);
#$_SESSION["sum"] = $_SESSION["one"] + $_SESSION["two"];
$challenge = $_SESSION["one"] . " + " . $_SESSION["two"];
header('Content-Type: text/plain; charset=utf-8');
echo($challenge);
?>

47
web/cgi/mail/mail.php Normal file
View file

@ -0,0 +1,47 @@
---
permalink: /cgi/mail/
---
<?php
session_start();
session_set_cookie_params(3600);
date_default_timezone_set("{{ site.timezone }}");
$error = "";
$sum = $_SESSION["one"] + $_SESSION["two"];
if ($_POST["sum"] != $sum) { $error = "{{ site.challenge_error }}"; }
if ($_POST["sum"] == $sum) {
$mailTo = "{{ site.email }}";
$mailAddress = "noreply@{{ site.url_short }}";
if($_POST["email"]) {
$mailAddress = $_POST["email"];
}
$mailHeaders = "From: " . $_POST["name"] . " <" . $mailAddress . ">" . "\r\n" .
"Date: " . date(DATE_RFC822);
$mailSubject = "[{{ site.url_short }}]: No subject!";
if($_POST["subject"]) {
$mailSubject = "[{{ site.url_short }}]: " . $_POST["subject"];
}
$mailBody = $_POST["message"] . "\n\n" . "Website: " . $_POST["website"] . "\nUser Agent: " . $_SERVER['HTTP_USER_AGENT'];
if (!@mail($mailTo, $mailSubject, $mailBody, $mailHeaders)) { $error = "Failed to send mail!"; }
unset($_SESSION["one"]);
unset($_SESSION["two"]);
}
header('Content-Type: text/plain; charset=utf-8');
if ($error=="") {
echo("{{ site.mail_thank_you }}");
} else {
//echo($error . " (". $_POST["sum"] . "/" . $sum . ")");
echo($error);
}
?>

View file

@ -0,0 +1,89 @@
---
layout: page
published: true
noToc: false
noDate: false
title: Code of Conduct
subtitle: Contributor Covenant Code of Conduct
description: Code of Conduct
permalink: /community/code-of-conduct/
---
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, caste, color, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
<br>
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at [community@fun-lang.xyz](mailto:community@fun-lang.xyz){:class="mail"}. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
### Correction
Community Impact: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
Consequence: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
### Warning
Community Impact: A violation through a single incident or series of actions.
Consequence: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
### Temporary Ban
Community Impact: A serious violation of community standards, including sustained inappropriate behavior.
Consequence: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
### Permanent Ban
Community Impact: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
Consequence: A permanent ban from any sort of public interaction within the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org){:class="ext"}, version 2.1, available at [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html](https://www.contributor-covenant.org/version/2/1/code_of_conduct.html){:class="ext"}.
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity){:class="ext"}.
For answers to common questions about this code of conduct, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq){:class="ext"}. Translations are available at [https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations){:class="ext"}.

View file

@ -0,0 +1,92 @@
---
layout: page
published: true
noToc: false
noDate: false
title: Community
subtitle: The place to contact the Fun community.
permalink: /community/
description: Community
---
<h2>Important</h2>
<p>Please read the <a href="/community/code-of-conduct/">Code of Conduct</a> before participating in xw3 community discussions.</p>
<h2>IRC</h2>
<p>We use the <a href="https://libera.chat/" class="ext">Libera.Chat</a> IRC network for realtime collaboration.</p>
<p>Just click the channel name to open a web based client in your browser for instant chat.</p>
<table width="100%" border="1" style="table-layout: fixed;" class="sortable">
<thead>
<tr>
<th style="text-align: left; width: 120px;">Channel</th>
<th style="text-align: left;">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://web.libera.chat/#fun-lang" class="chat">#fun-lang</a></td>
<td>All discussion about the Fun programming language</td>
</tr>
</tbody>
</table>
<h2>Mailinglists</h2>
<p>Mailinglists are provided by the <a href="https://lists.xw3.org" class="ext">lists.xw3.org</a> mailinglist server.</p>
<p>Simply click "Subscribe" to join a list by sending a blank email.</a>
<table width="100%" border="1" class="sortable">
<thead>
<tr>
<th style="text-align: left;">List</th>
<th style="text-align: left;">Description</th>
<th colspan="2">Action</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="https://lists.xw3.org/mailman3/lists/fun-announcements@fun-lang.xyz/" class="ext">fun-announcements@fun-lang.xyz</a></td>
<td>For Fun announcements</td>
<td><a href="mailto:fun-announcements-subscribe@fun-lang.xyz" class="mail">[Subscribe]</a></td>
<td><a href="mailto:fun-announcements-unsubscribe@fun-lang.xyz" class="mail">[Unsubscribe]</a></td>
</tr>
<tr>
<td><a href="https://lists.xw3.org/mailman3/lists/fun-developers@fun-lang.xyz/" class="ext">xw3-developers@fun-lang.xyz</a></td>
<td>Developer discussion about Fun</td>
<td><a href="mailto:fun-developers-subscribe@fun-lang.xyz" class="mail">[Subscribe]</a></td>
<td><a href="mailto:fun-developers-unsubscribe@fun-lang.xyz" class="mail">[Unsubscribe]</a></td>
</tr>
<tr>
<td><a href="https://lists.xw3.org/mailman3/lists/fun-users@fun-lang.xyz/" class="ext">xw3-users@fun-lang.xyz</a></td>
<td>User discussion about Fun</td>
<td><a href="mailto:fun-users-subscribe@fun-lang.xyz" class="mail">[Subscribe]</a></td>
<td><a href="mailto:fun-users-unsubscribe@fun-lang.xyz" class="mail">[Unsubscribe]</a></td>
</tr>
</tbody>
</table>
<br>
<p>You can also post to a list without a subscription, but your messages will be moderated and experience indefinite delays in delivery, and you won't receive replies if other users simply reply to the list without CCing you.</p>
<h2>Mastodon</h2>
<p>We will use Mastodon for announcements in the future: <a href="https://fosstodon.org/@fun" class="mastodon">https://fosstodon.org/@fun</a>.</p>
<h2>Others</h2>
<p>We believe that the communication channels mentioned above are sufficient for Fun development. IRC, mailing lists and Mastodon provide you with the perfect entry points for discussions about Fun development. Nothing more is needed.</p>
<h3>Matrix</h3>
<p>We do not and will never provide chat over the Matrix protocol in any way. Matrix sucks!</p>
<p>We also will in no way provide an IRC <-> Matrix bridge. Again, Matrix sucks!</p>
<p>For details read <a href="https://hanez.org/document/why-matrix-sucks/" class="ext">why Matrix sucks</a>!</p>

69
web/contact/contact.html Normal file
View file

@ -0,0 +1,69 @@
---
layout: page
published: true
noToc: true
noDate: false
noPermalink: true
noComments: true
title: Contact
subtitle: Please use the following form to contact us directly, anonymously if you prefer.
description: Contact
permalink: /contact/
tags:
- contact
---
<script>
function doSubmit() {
$("#loader").removeClass("hidden");
event.preventDefault();
var form = $('#contactform')[0];
var data = new FormData(form);
$.ajax({
type: "POST",
enctype: 'multipart/form-data',
data: data,
url: "/cgi/mail/",
processData: false,
contentType: false,
cache: false,
success: function(data){
window.alert(data);
$("#challenge").load("/cgi/challenge/");
$("#loader").addClass("hidden");
}
});
return false;
}
$(document).ready(function(){
$("#challenge").load("/cgi/challenge/");
});
</script>
<div style="margin:0;padding0;text-align:left;">
<form id="contactform" method="post" onsubmit="return doSubmit();">
<div><label>Name:<span style="color:red;">*</span></label>
<input type="text" name="name" id="name" required></div>
<div><label>Email:</label>
<input type="email" name="email" id="email"></div>
<div><label>Website:</label>
<input type="text" name="website" id="website"></div>
<div><label>Subject:</label>
<input type="text" name="subject" id="subject"></div>
<div><label>Message:<span style="color:red;">*</span></label>
<textarea name="message" id="message" required style="font-size:1em;font-family:OpenSans-Regular;"></textarea></div>
<div style="text-align:left;width:50%;float:left;"><label>Challenge: <span id="challenge" name="challenge">NULL</span>?
<span style="color:red;">*</span></label>
<input style="width:10%;text-align:center;" type="text" name="sum" id="sum" required></div>
<div style="text-align:right;width:50%;float:right;"><span style="color:red;">*</span> = Required fields</div>
<div><input type="submit" value="Send!" id="button"></div>
</form>
</div>

View file

@ -0,0 +1,19 @@
---
layout: page
published: true
noToc: true
title: Copyright
description: The copyright for the content at fun-lang.xyz.
permalink: /copyright/
tags:
- license
- copyright
metasub: projects
---
The contents of this website (unless otherwise noted) are licensed under a non-commercial share-alike license. This means (among other things) that you may not put my content on a web page that contains a paywall, Google AdWords or any other similar advertising, and you may not use any automated system to take an RSS feed from my blog (either directly, via Feedburner, or via a Planet installation or other syndication service that includes my posts) and post it to another blog for commercial purposes (which includes attempts to increase page-rank or other SEO).
So, all content is licensed under an [{{ site.license_name }} ({{ site.license }})]({{ site.license_url }}){:class="ext"} license if not otherwise mentioned. You must [contact](/contact/){:class="ext"} me and ask for permission if you want to use some of my content for commercial purposes.
Original source: [https://doc.coker.com.au/legal/blog-license/](https://doc.coker.com.au/legal/blog-license/){:class="ext"} - I modified the content to what you read above.

0
web/css/.gitkeep Normal file
View file

6
web/css/cookieconsent.min.css vendored Normal file
View file

@ -0,0 +1,6 @@
.cc-window{opacity:1;-webkit-transition:opacity 1s ease;transition:opacity 1s ease}.cc-window.cc-invisible{opacity:0}.cc-animate.cc-revoke{-webkit-transition:transform 1s ease;-webkit-transition:-webkit-transform 1s ease;transition:-webkit-transform 1s ease;transition:transform 1s ease;transition:transform 1s ease,-webkit-transform 1s ease}.cc-animate.cc-revoke.cc-top{-webkit-transform:translateY(-2em);transform:translateY(-2em)}.cc-animate.cc-revoke.cc-bottom{-webkit-transform:translateY(2em);transform:translateY(2em)}.cc-animate.cc-revoke.cc-active.cc-top{-webkit-transform:translateY(0);transform:translateY(0)}.cc-animate.cc-revoke.cc-active.cc-bottom{-webkit-transform:translateY(0);transform:translateY(0)}.cc-revoke:hover{-webkit-transform:translateY(0);transform:translateY(0)}.cc-grower{max-height:0;overflow:hidden;-webkit-transition:max-height 1s;transition:max-height 1s}
.cc-revoke,.cc-window{position:fixed;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;font-family:Helvetica,Calibri,Arial,sans-serif;font-size:16px;line-height:1.5em;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;z-index:9999}.cc-window.cc-static{position:static}.cc-window.cc-floating{padding:2em;max-width:24em;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner{padding:1em 1.8em;width:100%;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.cc-revoke{padding:.5em}.cc-revoke:hover{text-decoration:underline}.cc-header{font-size:18px;font-weight:700}.cc-btn,.cc-close,.cc-link,.cc-revoke{cursor:pointer}.cc-link{opacity:.8;display:inline-block;padding:.2em;text-decoration:underline}.cc-link:hover{opacity:1}.cc-link:active,.cc-link:visited{color:initial}.cc-btn{display:block;padding:.4em .8em;font-size:.9em;font-weight:700;border-width:2px;border-style:solid;text-align:center;white-space:nowrap}.cc-highlight .cc-btn:first-child{background-color:transparent;border-color:transparent}.cc-highlight .cc-btn:first-child:focus,.cc-highlight .cc-btn:first-child:hover{background-color:transparent;text-decoration:underline}.cc-close{display:block;position:absolute;top:.5em;right:.5em;font-size:1.6em;opacity:.9;line-height:.75}.cc-close:focus,.cc-close:hover{opacity:1}
.cc-revoke.cc-top{top:0;left:3em;border-bottom-left-radius:.5em;border-bottom-right-radius:.5em}.cc-revoke.cc-bottom{bottom:0;left:3em;border-top-left-radius:.5em;border-top-right-radius:.5em}.cc-revoke.cc-left{left:3em;right:unset}.cc-revoke.cc-right{right:3em;left:unset}.cc-top{top:1em}.cc-left{left:1em}.cc-right{right:1em}.cc-bottom{bottom:1em}.cc-floating>.cc-link{margin-bottom:1em}.cc-floating .cc-message{display:block;margin-bottom:1em}.cc-window.cc-floating .cc-compliance{-webkit-box-flex:1;-ms-flex:1 0 auto;flex:1 0 auto}.cc-window.cc-banner{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.cc-banner.cc-top{left:0;right:0;top:0}.cc-banner.cc-bottom{left:0;right:0;bottom:0}.cc-banner .cc-message{display:block;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;max-width:100%;margin-right:1em}.cc-compliance{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:justify;align-content:space-between}.cc-floating .cc-compliance>.cc-btn{-webkit-box-flex:1;-ms-flex:1;flex:1}.cc-btn+.cc-btn{margin-left:.5em}
@media print{.cc-revoke,.cc-window{display:none}}@media screen and (max-width:900px){.cc-btn{white-space:normal}}@media screen and (max-width:414px) and (orientation:portrait),screen and (max-width:736px) and (orientation:landscape){.cc-window.cc-top{top:0}.cc-window.cc-bottom{bottom:0}.cc-window.cc-banner,.cc-window.cc-floating,.cc-window.cc-left,.cc-window.cc-right{left:0;right:0}.cc-window.cc-banner{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.cc-window.cc-banner .cc-compliance{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.cc-window.cc-floating{max-width:none}.cc-window .cc-message{margin-bottom:1em}.cc-window.cc-banner{-webkit-box-align:unset;-ms-flex-align:unset;align-items:unset}.cc-window.cc-banner .cc-message{margin-right:0}}
.cc-floating.cc-theme-classic{padding:1.2em;border-radius:5px}.cc-floating.cc-type-info.cc-theme-classic .cc-compliance{text-align:center;display:inline;-webkit-box-flex:0;-ms-flex:none;flex:none}.cc-theme-classic .cc-btn{border-radius:5px}.cc-theme-classic .cc-btn:last-child{min-width:140px}.cc-floating.cc-type-info.cc-theme-classic .cc-btn{display:inline-block}
.cc-theme-edgeless.cc-window{padding:0}.cc-floating.cc-theme-edgeless .cc-message{margin:2em;margin-bottom:1.5em}.cc-banner.cc-theme-edgeless .cc-btn{margin:0;padding:.8em 1.8em;height:100%}.cc-banner.cc-theme-edgeless .cc-message{margin-left:1em}.cc-floating.cc-theme-edgeless .cc-btn+.cc-btn{margin-left:0}

33
web/css/main.scss Normal file
View file

@ -0,0 +1,33 @@
---
# Only the main Sass file needs front matter (the dashes are enough)
---
@charset "utf-8";
$base-font-family: "CPS";
$base-font-size: 16px;
$small-font-size: $base-font-size * 0.875;
$base-icon-font-family: "MDI";
$base-icon-size: 12px;
$base-icon-color: #565656;
$base-line-height: 1.6;
$spacing-unit: 18px;
$text-color: #000;
$background-color: #565656;
$headline-color: #bc6c21; //#b40000;
$hover-color: #bc6c21;
$topbutton-color: $headline-color;
$brand-color: #1fa2af;
$brand-color-light: lighten($brand-color, 40%);
$grey-color: #828282;
$grey-color-light: #e8e8e8;
$grey-color-dark: #dbdbdb;
$green-color: #3ab215;
$tablehead-color: #bc6c21;
$content-width: 1024px;
$on-palm: 761px;
$on-laptop: 1024px;
@mixin media-query($device) {
@media screen and (max-width: $device) {
@content;
}
}
@import "base", "fonts", "forms", "highlight", "isso", "layout", "links", "toc";

View file

@ -0,0 +1,49 @@
---
layout: page
published: true
noToc: true
noComments: false
noDate: false
title: Documentation
subtitle: Some documentation about the Fun programming language.
description: The Fun Documentation
permalink: /documentation/
lang: en
tags:
- documentation
- handbook
- installation
- usage
- introduction
- help
- guide
- howto
- docs
- specifications
- specs
- repl
---
## Basics
[The Fun Handbook is found here](https://git.xw3.org/fun/fun/src/branch/main/docs/handbook.md){:class="git"}!
Look at [https://git.xw3.org/fun/fun/src/branch/main/docs](https://git.xw3.org/fun/fun/src/branch/main/docs){:class="git"} for more detailed documentation!
## More information
- [Specification v0.3](https://git.xw3.org/fun/fun/src/branch/main/spec/v0.3.md){:class="git"}
- [Specification v0.2](https://git.xw3.org/fun/fun/src/branch/main/spec/v0.2.md){:class="git"}
- [Specification v0.1](https://git.xw3.org/fun/fun/src/branch/main/spec/v0.1.md){:class="git"}
- [Examples](https://git.xw3.org/fun/fun/src/branch/main/examples){:class="git"}
- [Standard Library](https://git.xw3.org/fun/fun/src/branch/main/lib){:class="git"}
- [Fun REPL Guide](https://git.xw3.org/fun/fun/src/branch/main/docs/repl.md){:class="git"}
The examples directory contains demonstrations of most Fun features, from basic "Hello, World!" to threading, networking, classes, and more. The lib directory includes modules written in Fun itself.
## For Developers
- [Fun Internals](https://git.xw3.org/fun/fun/src/branch/main/docs/internals.md){:class="git"}
- [Fun Opcodes](https://git.xw3.org/fun/fun/src/branch/main/docs/opcodes.md){:class="git"}
- [Basic Rust Opcodes Support](https://git.xw3.org/fun/fun/src/branch/main/docs/rust.md){:class="git"}

17
web/faq/faq.md Normal file
View file

@ -0,0 +1,17 @@
---
layout: page
published: true
noToc: true
title: FAQ
subtitle: Frequently Asked Questions
description: Frequently Asked Questions (FAQ)
permalink: /faq/
tags:
- faq
- about
---
## Why Fun?
Because of fun... ;)

BIN
web/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

30
web/feed/feed.xml Normal file
View file

@ -0,0 +1,30 @@
---
layout:
permalink: /feed/
---
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ site.title | xml_escape }}</title>
<description>{{ site.description | xml_escape }}</description>
<link>{{ site.url }}</link>
<atom:link href="{{ site.url }}/blog/feed/" rel="self" type="application/rss+xml"/>
<pubDate>{{ site.time | date_to_rfc822 }}</pubDate>
<lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>
{% for post in site.posts limit:10 %}
<item>
<title>{{ post.title | xml_escape }}</title>
<description>{{ post.content | xml_escape }}</description>
<pubDate>{{ post.date | date_to_rfc822 }}</pubDate>
<link>{{ site.url }}{{ post.url }}</link>
<guid isPermaLink="true">{{ site.url }}{{ post.url }}</guid>
{% for tag in post.tags %}
<category>{{ tag | xml_escape }}</category>
{% endfor %}
{% for cat in post.categories %}
<category>{{ cat | xml_escape }}</category>
{% endfor %}
</item>
{% endfor %}
</channel>
</rss>

0
web/files/.gitkeep Normal file
View file

0
web/fonts/.gitkeep Normal file
View file

Binary file not shown.

Binary file not shown.

0
web/images/.gitkeep Normal file
View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
web/images/fun-square.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
web/images/fun.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
web/images/spinner.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
web/images/up-arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 649 B

66
web/index.md Normal file
View file

@ -0,0 +1,66 @@
---
layout: page
title: :load /index.fun
subtitle: The programming language that makes you have fun!
description: Blog and Homepage
metasub: news
noToc: true
noDate: false
tags:
- fun
- project
- dynamic
- static
- programming
- blog
- language
permalink: /
---
<h2>What is Fun?</h2>
<p>Fun is an experiment, just for fun, but Fun works!</p>
<p>Fun is a highly strict programming language, but also highly simple. It looks like Python (My favorite language), but there are differences.</p>
<p>Influenced by <a href="https://www.gnu.org/software/bash/" class="ext">Bash</a>, <a href="https://en.wikipedia.org/wiki/The_C_Programming_Language" class="ext">C</a>, <a href="https://www.lua.org/" class="ext">Lua</a>, PHP, <a href="https://www.python.org/" class="ext">Python</a>, and a little Rust (Most influences came from linked languages).</p>
<p>Fun is and will ever be 100% free under the terms of the <a href="https://opensource.org/license/apache-2-0" class="ext">Apache-2.0 License</a>.</p>
<p style="text-align:right;"><a href="/about/" title="About">[Read more]</a></p>
<!--<p><a href="/about/">More about Fun</a><p>-->
<h2>Blog (<a href="/feed/" title="Blog Feed" class="rss">Feed</a>)</h2>
{% for post in site.tags.pinned %}
<article class="post-content">
<h2><a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a> <span style="cursor:help; float: right;" title="Pinned Post!">📌</span></h2>
<p class="post-meta">{{ post.date | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }})
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ site.git_short }}/{{ post.author }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{{ post.content | truncatewords: site.truncatewords_length }}
<p style="text-align:right;"><a href="{{ post.url }}" title="{{ post.url }}">[Read post]</a></p>
</article>
{% endfor %}
{% for post in site.posts %}
{% unless post.tags contains 'pinned' %}
<article class="post-content">
<h2><a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a></h2>
<p class="post-meta">{{ post.date | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }})
{% if post.date_updated %} - Edited: {{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" }} ({{ post.date_updated | date: "%b %-d, %Y %H:%M:%S" | date: "%Z" }}){% endif %}{% if post.author %}, <a href="{{ site.git_short }}/{{ post.author }}" target="_blank" class="user">{{ post.author }}</a>{% endif %}</p>
{{ post.content | truncatewords: site.truncatewords_length }}
<p style="text-align:right;"><a href="{{ post.url }}" title="{{ post.url }}">[Read post]</a></p>
</article>
{% endunless %}
{% endfor %}
<h2>Pages</h2>
<div id="pages">
{% if paginator.page == 1 %}<a href="/blog/" class="active" title="Page 1">1</a>{% else %}<a href="/blog/" title="Page 1">1</a>{% endif %}
{% for count in (2..paginator.total_pages) %}
{% if count == paginator.page %}<a href="/{{ count }}/" class="active" title="Page {{ count }}">{{ count }}</a>{% else %}<a href="/{{ count }}/" title="Page {{ count }}">{{ count }}</a>{% endif %}
{% endfor %}
</div><br>

0
web/js/.gitkeep Normal file
View file

1
web/js/cookieconsent.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
web/js/jquery-3.6.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
web/js/jquery-3.7.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
web/js/js-cookie-3.0.5.min.js vendored Normal file
View file

@ -0,0 +1,2 @@
/*! js-cookie v3.0.5 | MIT */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self,function(){var n=e.Cookies,o=e.Cookies=t();o.noConflict=function(){return e.Cookies=n,o}}())}(this,(function(){"use strict";function e(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)e[o]=n[o]}return e}var t=function t(n,o){function r(t,r,i){if("undefined"!=typeof document){"number"==typeof(i=e({},o,i)).expires&&(i.expires=new Date(Date.now()+864e5*i.expires)),i.expires&&(i.expires=i.expires.toUTCString()),t=encodeURIComponent(t).replace(/%(2[346B]|5E|60|7C)/g,decodeURIComponent).replace(/[()]/g,escape);var c="";for(var u in i)i[u]&&(c+="; "+u,!0!==i[u]&&(c+="="+i[u].split(";")[0]));return document.cookie=t+"="+n.write(r,t)+c}}return Object.create({set:r,get:function(e){if("undefined"!=typeof document&&(!arguments.length||e)){for(var t=document.cookie?document.cookie.split("; "):[],o={},r=0;r<t.length;r++){var i=t[r].split("="),c=i.slice(1).join("=");try{var u=decodeURIComponent(i[0]);if(o[u]=n.read(c,u),e===u)break}catch(e){}}return e?o[e]:o}},remove:function(t,n){r(t,"",e({},n,{expires:-1}))},withAttributes:function(n){return t(this.converter,e({},this.attributes,n))},withConverter:function(n){return t(e({},this.converter,n),this.attributes)}},{attributes:{value:Object.freeze(o)},converter:{value:Object.freeze(n)}})}({read:function(e){return'"'===e[0]&&(e=e.slice(1,-1)),e.replace(/(%[\dA-F]{2})+/gi,decodeURIComponent)},write:function(e){return encodeURIComponent(e).replace(/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,decodeURIComponent)}},{path:"/"});return t}));

10
web/js/matomo.js Normal file
View file

@ -0,0 +1,10 @@
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="https://mtm.xw3.org/";
_paq.push(['setTrackerUrl', u+'matomo.php']);
_paq.push(['setSiteId', '9']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
})();

1
web/js/matomo.min.js vendored Normal file
View file

@ -0,0 +1 @@
var _paq=window._paq=window._paq||[];_paq.push(["trackPageView"]),_paq.push(["enableLinkTracking"]),function(){var e="https://mtm.xw3.org/";_paq.push(["setTrackerUrl",e+"matomo.php"]),_paq.push(["setSiteId","9"]);var a=document,t=a.createElement("script"),p=a.getElementsByTagName("script")[0];t.async=!0,t.src=e+"matomo.js",p.parentNode.insertBefore(t,p)}();

495
web/js/sorttable-2.js Normal file
View file

@ -0,0 +1,495 @@
/*
SortTable
version 2
7th April 2007
Stuart Langridge, http://www.kryogenix.org/code/browser/sorttable/
Instructions:
Download this file
Add <script src="sorttable.js"></script> to your HTML
Add class="sortable" to any table you'd like to make sortable
Click on the headers to sort
Thanks to many, many people for contributions and suggestions.
Licenced as X11: http://www.kryogenix.org/code/browser/licence.html
This basically means: do what you want with it.
*/
var stIsIE = /*@cc_on!@*/false;
sorttable = {
init: function() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// kill the timer
if (_timer) clearInterval(_timer);
if (!document.createElement || !document.getElementsByTagName) return;
sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/;
forEach(document.getElementsByTagName('table'), function(table) {
if (table.className.search(/\bsortable\b/) != -1) {
sorttable.makeSortable(table);
}
});
},
makeSortable: function(table) {
if (table.getElementsByTagName('thead').length == 0) {
// table doesn't have a tHead. Since it should have, create one and
// put the first table row in it.
the = document.createElement('thead');
the.appendChild(table.rows[0]);
table.insertBefore(the,table.firstChild);
}
// Safari doesn't support table.tHead, sigh
if (table.tHead == null) table.tHead = table.getElementsByTagName('thead')[0];
if (table.tHead.rows.length != 1) return; // can't cope with two header rows
// Sorttable v1 put rows with a class of "sortbottom" at the bottom (as
// "total" rows, for example). This is B&R, since what you're supposed
// to do is put them in a tfoot. So, if there are sortbottom rows,
// for backwards compatibility, move them to tfoot (creating it if needed).
sortbottomrows = [];
for (var i=0; i<table.rows.length; i++) {
if (table.rows[i].className.search(/\bsortbottom\b/) != -1) {
sortbottomrows[sortbottomrows.length] = table.rows[i];
}
}
if (sortbottomrows) {
if (table.tFoot == null) {
// table doesn't have a tfoot. Create one.
tfo = document.createElement('tfoot');
table.appendChild(tfo);
}
for (var i=0; i<sortbottomrows.length; i++) {
tfo.appendChild(sortbottomrows[i]);
}
delete sortbottomrows;
}
// work through each column and calculate its type
headrow = table.tHead.rows[0].cells;
for (var i=0; i<headrow.length; i++) {
// manually override the type with a sorttable_type attribute
if (!headrow[i].className.match(/\bsorttable_nosort\b/)) { // skip this col
mtch = headrow[i].className.match(/\bsorttable_([a-z0-9]+)\b/);
if (mtch) { override = mtch[1]; }
if (mtch && typeof sorttable["sort_"+override] == 'function') {
headrow[i].sorttable_sortfunction = sorttable["sort_"+override];
} else {
headrow[i].sorttable_sortfunction = sorttable.guessType(table,i);
}
// make it clickable to sort
headrow[i].sorttable_columnindex = i;
headrow[i].sorttable_tbody = table.tBodies[0];
dean_addEvent(headrow[i],"click", sorttable.innerSortFunction = function(e) {
if (this.className.search(/\bsorttable_sorted\b/) != -1) {
// if we're already sorted by this column, just
// reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted',
'sorttable_sorted_reverse');
this.removeChild(document.getElementById('sorttable_sortfwdind'));
sortrevind = document.createElement('span');
sortrevind.id = "sorttable_sortrevind";
sortrevind.innerHTML = stIsIE ? '&nbsp<font face="webdings">5</font>' : '&nbsp;&#x25B4;';
this.appendChild(sortrevind);
return;
}
if (this.className.search(/\bsorttable_sorted_reverse\b/) != -1) {
// if we're already sorted by this column in reverse, just
// re-reverse the table, which is quicker
sorttable.reverse(this.sorttable_tbody);
this.className = this.className.replace('sorttable_sorted_reverse',
'sorttable_sorted');
this.removeChild(document.getElementById('sorttable_sortrevind'));
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
this.appendChild(sortfwdind);
return;
}
// remove sorttable_sorted classes
theadrow = this.parentNode;
forEach(theadrow.childNodes, function(cell) {
if (cell.nodeType == 1) { // an element
cell.className = cell.className.replace('sorttable_sorted_reverse','');
cell.className = cell.className.replace('sorttable_sorted','');
}
});
sortfwdind = document.getElementById('sorttable_sortfwdind');
if (sortfwdind) { sortfwdind.parentNode.removeChild(sortfwdind); }
sortrevind = document.getElementById('sorttable_sortrevind');
if (sortrevind) { sortrevind.parentNode.removeChild(sortrevind); }
this.className += ' sorttable_sorted';
sortfwdind = document.createElement('span');
sortfwdind.id = "sorttable_sortfwdind";
sortfwdind.innerHTML = stIsIE ? '&nbsp<font face="webdings">6</font>' : '&nbsp;&#x25BE;';
this.appendChild(sortfwdind);
// build an array to sort. This is a Schwartzian transform thing,
// i.e., we "decorate" each row with the actual sort key,
// sort based on the sort keys, and then put the rows back in order
// which is a lot faster because you only do getInnerText once per row
row_array = [];
col = this.sorttable_columnindex;
rows = this.sorttable_tbody.rows;
for (var j=0; j<rows.length; j++) {
row_array[row_array.length] = [sorttable.getInnerText(rows[j].cells[col]), rows[j]];
}
/* If you want a stable sort, uncomment the following line */
//sorttable.shaker_sort(row_array, this.sorttable_sortfunction);
/* and comment out this one */
row_array.sort(this.sorttable_sortfunction);
tb = this.sorttable_tbody;
for (var j=0; j<row_array.length; j++) {
tb.appendChild(row_array[j][1]);
}
delete row_array;
});
}
}
},
guessType: function(table, column) {
// guess the type of a column based on its first non-blank row
sortfn = sorttable.sort_alpha;
for (var i=0; i<table.tBodies[0].rows.length; i++) {
text = sorttable.getInnerText(table.tBodies[0].rows[i].cells[column]);
if (text != '') {
if (text.match(/^-?[£$€]?[\d,.]+%?$/)) {
return sorttable.sort_numeric;
}
// check for a date: dd/mm/yyyy or dd/mm/yy
// can have / or . or - as separator
// can be mm/dd as well
possdate = text.match(sorttable.DATE_RE)
if (possdate) {
// looks like a date
first = parseInt(possdate[1]);
second = parseInt(possdate[2]);
if (first > 12) {
// definitely dd/mm
return sorttable.sort_ddmm;
} else if (second > 12) {
return sorttable.sort_mmdd;
} else {
// looks like a date, but we can't tell which, so assume
// that it's dd/mm (English imperialism!) and keep looking
sortfn = sorttable.sort_ddmm;
}
}
}
}
return sortfn;
},
getInnerText: function(node) {
// gets the text we want to use for sorting for a cell.
// strips leading and trailing whitespace.
// this is *not* a generic getInnerText function; it's special to sorttable.
// for example, you can override the cell text with a customkey attribute.
// it also gets .value for <input> fields.
if (!node) return "";
hasInputs = (typeof node.getElementsByTagName == 'function') &&
node.getElementsByTagName('input').length;
if (node.getAttribute("sorttable_customkey") != null) {
return node.getAttribute("sorttable_customkey");
}
else if (typeof node.textContent != 'undefined' && !hasInputs) {
return node.textContent.replace(/^\s+|\s+$/g, '');
}
else if (typeof node.innerText != 'undefined' && !hasInputs) {
return node.innerText.replace(/^\s+|\s+$/g, '');
}
else if (typeof node.text != 'undefined' && !hasInputs) {
return node.text.replace(/^\s+|\s+$/g, '');
}
else {
switch (node.nodeType) {
case 3:
if (node.nodeName.toLowerCase() == 'input') {
return node.value.replace(/^\s+|\s+$/g, '');
}
case 4:
return node.nodeValue.replace(/^\s+|\s+$/g, '');
break;
case 1:
case 11:
var innerText = '';
for (var i = 0; i < node.childNodes.length; i++) {
innerText += sorttable.getInnerText(node.childNodes[i]);
}
return innerText.replace(/^\s+|\s+$/g, '');
break;
default:
return '';
}
}
},
reverse: function(tbody) {
// reverse the rows in a tbody
newrows = [];
for (var i=0; i<tbody.rows.length; i++) {
newrows[newrows.length] = tbody.rows[i];
}
for (var i=newrows.length-1; i>=0; i--) {
tbody.appendChild(newrows[i]);
}
delete newrows;
},
/* sort functions
each sort function takes two parameters, a and b
you are comparing a[0] and b[0] */
sort_numeric: function(a,b) {
aa = parseFloat(a[0].replace(/[^0-9.-]/g,''));
if (isNaN(aa)) aa = 0;
bb = parseFloat(b[0].replace(/[^0-9.-]/g,''));
if (isNaN(bb)) bb = 0;
return aa-bb;
},
sort_alpha: function(a,b) {
if (a[0]==b[0]) return 0;
if (a[0]<b[0]) return -1;
return 1;
},
sort_ddmm: function(a,b) {
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3]; m = mtch[2]; d = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt1 = y+m+d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3]; m = mtch[2]; d = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt2 = y+m+d;
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
},
sort_mmdd: function(a,b) {
mtch = a[0].match(sorttable.DATE_RE);
y = mtch[3]; d = mtch[2]; m = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt1 = y+m+d;
mtch = b[0].match(sorttable.DATE_RE);
y = mtch[3]; d = mtch[2]; m = mtch[1];
if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d;
dt2 = y+m+d;
if (dt1==dt2) return 0;
if (dt1<dt2) return -1;
return 1;
},
shaker_sort: function(list, comp_func) {
// A stable sort function to allow multi-level sorting of data
// see: http://en.wikipedia.org/wiki/Cocktail_sort
// thanks to Joseph Nahmias
var b = 0;
var t = list.length - 1;
var swap = true;
while(swap) {
swap = false;
for(var i = b; i < t; ++i) {
if ( comp_func(list[i], list[i+1]) > 0 ) {
var q = list[i]; list[i] = list[i+1]; list[i+1] = q;
swap = true;
}
} // for
t--;
if (!swap) break;
for(var i = t; i > b; --i) {
if ( comp_func(list[i], list[i-1]) < 0 ) {
var q = list[i]; list[i] = list[i-1]; list[i-1] = q;
swap = true;
}
} // for
b++;
} // while(swap)
}
}
/* ******************************************************************
Supporting functions: bundled here to avoid depending on a library
****************************************************************** */
// Dean Edwards/Matthias Miller/John Resig
/* for Mozilla/Opera9 */
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", sorttable.init, false);
}
/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var script = document.getElementById("__ie_onload");
script.onreadystatechange = function() {
if (this.readyState == "complete") {
sorttable.init(); // call the onload handler
}
};
/*@end @*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
sorttable.init(); // call the onload handler
}
}, 10);
}
/* for other browsers */
window.onload = sorttable.init;
// written by Dean Edwards, 2005
// with input from Tino Zijdel, Matthias Miller, Diego Perini
// http://dean.edwards.name/weblog/2005/10/add-event/
function dean_addEvent(element, type, handler) {
if (element.addEventListener) {
element.addEventListener(type, handler, false);
} else {
// assign each event handler a unique ID
if (!handler.$$guid) handler.$$guid = dean_addEvent.guid++;
// create a hash table of event types for the element
if (!element.events) element.events = {};
// create a hash table of event handlers for each element/event pair
var handlers = element.events[type];
if (!handlers) {
handlers = element.events[type] = {};
// store the existing event handler (if there is one)
if (element["on" + type]) {
handlers[0] = element["on" + type];
}
}
// store the event handler in the hash table
handlers[handler.$$guid] = handler;
// assign a global event handler to do all the work
element["on" + type] = handleEvent;
}
};
// a counter used to create unique IDs
dean_addEvent.guid = 1;
function removeEvent(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else {
// delete the event handler from the hash table
if (element.events && element.events[type]) {
delete element.events[type][handler.$$guid];
}
}
};
function handleEvent(event) {
var returnValue = true;
// grab the event object (IE uses a global event object)
event = event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);
// get a reference to the hash table of event handlers
var handlers = this.events[event.type];
// execute each event handler
for (var i in handlers) {
this.$$handleEvent = handlers[i];
if (this.$$handleEvent(event) === false) {
returnValue = false;
}
}
return returnValue;
};
function fixEvent(event) {
// add W3C standard event methods
event.preventDefault = fixEvent.preventDefault;
event.stopPropagation = fixEvent.stopPropagation;
return event;
};
fixEvent.preventDefault = function() {
this.returnValue = false;
};
fixEvent.stopPropagation = function() {
this.cancelBubble = true;
}
// Dean's forEach: http://dean.edwards.name/base/forEach.js
/*
forEach, version 1.0
Copyright 2006, Dean Edwards
License: http://www.opensource.org/licenses/mit-license.php
*/
// array-like enumeration
if (!Array.forEach) { // mozilla already supports this
Array.forEach = function(array, block, context) {
for (var i = 0; i < array.length; i++) {
block.call(context, array[i], i, array);
}
};
}
// generic enumeration
Function.prototype.forEach = function(object, block, context) {
for (var key in object) {
if (typeof this.prototype[key] == "undefined") {
block.call(context, object[key], key, object);
}
}
};
// character enumeration
String.forEach = function(string, block, context) {
Array.forEach(string.split(""), function(chr, index) {
block.call(context, chr, index, string);
});
};
// globally resolve forEach enumeration
var forEach = function(object, block, context) {
if (object) {
var resolve = Object; // default
if (object instanceof Function) {
// functions have a "length" property
resolve = Function;
} else if (object.forEach instanceof Function) {
// the object implements a custom forEach method so use that
object.forEach(block, context);
return;
} else if (typeof object == "string") {
// the object is a string
resolve = String;
} else if (typeof object.length == "number") {
// the object is array-like
resolve = Array;
}
resolve.forEach(object, block, context);
}
};

2
web/js/sorttable-2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

119
web/privacy/privacy.md Normal file
View file

@ -0,0 +1,119 @@
---
layout: page
published: true
noToc: false
noComments: true
title: Privacy
subtitle:
description: Privacy
permalink: /privacy/
lang: en
tags:
- privacy
- tracking
- cookies
- analytics
- policy
---
## Overview
At fun-lang.xyz, accessible from <a href="https://fun-lang.xyz/">https://fun-lang.xyz/</a>, one of our main priorities is the privacy of our visitors. This Privacy Policy document contains types of information that is collected and recorded by fun-lang.xyz and how we use it.
If you have additional questions or require more information about our Privacy Policy, do not hesitate to <a href="/contact/">contact</a> us.
This Privacy Policy applies only to our online activities and is valid for visitors to our website with regards to the information that they shared and/or collect in fun-lang.xyz. This policy is not applicable to any information collected offline or via channels other than this website.
## Consent
By using our website, you hereby consent to our Privacy Policy and agree to its terms.
## Information we collect
The personal information that you are asked to provide, and the reasons why you are asked to provide it, will be made clear to you at the point we ask you to provide your personal information.
If you contact us directly, we may receive additional information about you such as your name, email address, phone number, the contents of the message and/or attachments you may send us, and any other information you may choose to provide.
When you register for an Account, we may ask for your contact information, including items such as name, company name, address, email address, and telephone number.
## How we use your information
We use the information we collect in various ways, including to:
- Provide, operate, and maintain our website
- Improve, personalize, and expand our website
- Understand and analyze how you use our website
- Develop new products, services, features, and functionality
- Communicate with you, either directly or through one of our partners, including for customer service, to provide you with updates and other information relating to the website, and for marketing and promotional purposes
- Send you emails
- Find and prevent fraud
## Log Files
fun-lang.xyz follows a standard procedure of using log files. These files log visitors when they visit websites. All hosting companies do this and a part of hosting services' analytics. The information collected by log files include internet protocol (IP) addresses, browser type, Internet Service Provider (ISP), date and time stamp, referring/exit pages, and possibly the number of clicks. These are not linked to any information that is personally identifiable. The purpose of the information is for analyzing trends, administering the site, tracking users' movement on the website, and gathering demographic information.
## Cookies and Web Beacons
Like any other website, fun-lang.xyz uses "cookies". These cookies are used to store information including visitors' preferences, and the pages on the website that the visitor accessed or visited. The information is used to optimize the users' experience by customizing our web page content based on visitors' browser type and/or other information.
## Advertising Partners Privacy Policies
You may consult this list to find the Privacy Policy for each of the advertising partners of fun-lang.xyz.
Third-party ad servers or ad networks uses technologies like cookies, JavaScript, or Web Beacons that are used in their respective advertisements and links that appear on fun-lang.xyz, which are sent directly to users' browser. They automatically receive your IP address when this occurs. These technologies are used to measure the effectiveness of their advertising campaigns and/or to personalize the advertising content that you see on websites that you visit.
Note that fun-lang.xyz has no access to or control over these cookies that are used by third-party advertisers.
## Third Party Privacy Policies
fun-lang.xyz's Privacy Policy does not apply to other advertisers or websites. Thus, we are advising you to consult the respective Privacy Policies of these third-party ad servers for more detailed information. It may include their practices and instructions about how to opt-out of certain options.
You can choose to disable cookies through your individual browser options. To know more detailed information about cookie management with specific web browsers, it can be found at the browsers' respective websites.
## CCPA Privacy Rights (Do Not Sell My Personal Information)
Under the CCPA, among other rights, California consumers have the right to:
Request that a business that collects a consumer's personal data disclose the categories and specific pieces of personal data that a business has collected about consumers.
Request that a business delete any personal data about the consumer that a business has collected.
Request that a business that sells a consumer's personal data, not sell the consumer's personal data.
If you make a request, we have one month to respond to you. If you would like to exercise any of these rights, please <a href="/contact/">contact</a> us.
## GDPR Data Protection Rights
We would like to make sure you are fully aware of all of your data protection rights. Every user is entitled to the following:
The right to access You have the right to request copies of your personal data. We may charge you a small fee for this service.
The right to rectification You have the right to request that we correct any information you believe is inaccurate. You also have the right to request that we complete the information you believe is incomplete.
The right to erasure You have the right to request that we erase your personal data, under certain conditions.
The right to restrict processing You have the right to request that we restrict the processing of your personal data, under certain conditions.
The right to object to processing You have the right to object to our processing of your personal data, under certain conditions.
The right to data portability You have the right to request that we transfer the data that we have collected to another organization, or directly to you, under certain conditions.
If you make a request, we have one month to respond to you. If you would like to exercise any of these rights, please <a href="/contact/">contact</a> us.
## Children's Information
Another part of our priority is adding protection for children while using the internet. We encourage parents and guardians to observe, participate in, and/or monitor and guide their online activity.
fun-lang.xyz does not knowingly collect any Personal Identifiable Information from children under the age of 13. If you think that your child provided this kind of information on our website, we strongly encourage you to contact us immediately and we will do our best efforts to promptly remove such information from our records.
## Changes to this Privacy Policy
We may update our Privacy Policy from time to time. Thus, we advise you to review this page periodically for any changes. We will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately, after they are posted on this page.
Our Privacy Policy was created with the help of the <a href="https://www.privacypolicygenerator.info" class="ext">Privacy Policy Generator</a>.
## Contact Us
If you have any questions or suggestions about our Privacy Policy, do not hesitate to <a href="/contact/">contact</a> us.

4
web/robots.txt Normal file
View file

@ -0,0 +1,4 @@
User-agent: *
Disallow:
Sitemap: https://fun-lang.xyz/sitemap.xml

29
web/search/search.html Normal file
View file

@ -0,0 +1,29 @@
---
layout: default
published: false
noToc: true
noDate: true
noPermalink: true
noComments: true
title: /search/index.fun
description: Search
subtitle: Search this site using <a href="https://duckduckgo.com/" class="ext" target="_blank">DuckDuckGo</a>
permalink: /search/
tags:
- search
- duckduckgo
---
<div class="post">
<header class="post-header">
<h1 class="post-title" id="terminal">{{ site.title }} {{ page.title }}</h1>
<p>{{ page.subtitle }}</p>
</header>
</div>
<form method="get" id="searchform" action="https://duckduckgo.com/" target="_blank">
<input type="hidden" name="sites" value="{{ site.url_short }}"/>
<input type="input" name="q" placeholder="Keywords&hellip;" required/>
<input type="submit" value="Search!" />
</form>