Feat: 1p intro w/ markdownit+hljs+lucide

This commit is contained in:
2025-09-15 00:19:19 -07:00
parent a3ce37555b
commit b58406cb63

View File

@@ -1,119 +1,327 @@
<!doctype html><html lang=en> <!doctype html><html lang=en>
<head> <head>
<meta charset=utf-8> <meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<meta name=viewport content="width=device-width,initial-scale=1,viewport-fit=cover"> <title>Hi — a tiny, symbolic, AIfirst language</title>
<title>Hi — a tiny, symbolic, AI-first programming language</title>
<link rel=preconnect href=https://fonts.googleapis.com> <link rel=preconnect href=https://fonts.googleapis.com>
<link rel=preconnect href=https://fonts.gstatic.com crossorigin> <link rel=preconnect href=https://fonts.gstatic.com crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=Fira+Code:wght@400;600&display=swap" rel=stylesheet> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;800&family=JetBrains+Mono:wght@300;400;600&display=swap" rel=stylesheet>
<script src="https://cdn.tailwindcss.com"></script> <link rel=stylesheet href=https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.5.1/github-markdown.min.css integrity=sha512-ig3uzadlU/hJ2SXiczY2h5D7J26fI6z6mDbcf0sApsWsOqgSmnNoZiH+4rUrka+tp68Q2mEwMpsv/u+8mewaJQ== crossorigin=anonymous referrerpolicy=no-referrer>
<link rel=stylesheet href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-light.min.css"> <link rel=stylesheet href=https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css integrity=sha512-3mb8zCey3p+3w0lI04lH8mKeb4d0x1c6PXo2g0Q9yQkQhy/c6v2dGEZ7V6o0H6YugyS0r5uEIAJ0u8oHNoq6tA== crossorigin=anonymous referrerpolicy=no-referrer>
<link rel=stylesheet href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles/github.min.css">
<style> <style>
:root{color-scheme:light} :root{--bg:radial-gradient(1200px 600px at 70% -20%,#d9e6ff22,transparent),radial-gradient(1000px 500px at 10% -10%,#ffd9f022,transparent),linear-gradient(#fafbff,#f7f9ff);--bgD:radial-gradient(1200px 600px at 70% -20%,#2a335522,transparent),radial-gradient(1000px 500px at 10% -10%,#4a234422,transparent),linear-gradient(#0c0f13,#0a0d10)}
*{box-sizing:border-box} *{box-sizing:border-box}
html,body{height:100%} html,body{height:100%}
body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Apple Color Emoji,Noto Color Emoji,Arial,Helvetica,sans-serif} html{color-scheme:light dark}
code,pre,.font-mono{font-family:"Fira Code",ui-monospace,Menlo,Consolas,monospace} body{margin:0;font:400 13.25px/1.55 Inter,ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,Noto Sans,Apple Color Emoji,Segoe UI Emoji,sans-serif;background:var(--bg)}
.markdown-body{font-size:12px;line-height:1.6} @media (prefers-color-scheme:dark){body{background:var(--bgD)}}
.markdown-body pre{overflow:auto} .markdown-body{font-size:12.6px;max-width:920px;padding:64px 18px 80px;margin:0 auto;color:inherit}
.copy-btn{position:absolute;top:.4rem;right:.4rem;font-size:10px;padding:.125rem .375rem;border-radius:.375rem;background:rgba(17,17,17,.9);color:#fff} code,kbd,pre,samp{font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:12px}
pre{border:1px solid #e5e7eb;border-radius:.5rem;position:relative} header{position:sticky;top:8px;z-index:9;display:grid;place-items:center;height:0}
.hero-grad{--g:radial-gradient(60% 60% at 50% 40%,rgba(120,119,198,.15),rgba(255,255,255,0) 60%);background: #brand{pointer-events:none;user-select:none;letter-spacing:.5px;font:700 13px/1 Inter;padding:8px 16px;border-radius:999px;background:linear-gradient(180deg,#fff,#f5f5f5);border:1px solid #e1e4e8;box-shadow:0 1px 0 rgba(0,0,0,.02),0 12px 24px -16px rgba(0,0,0,.2);color:#111}
var(--g),conic-gradient(from 180deg at 50% 50%,#f0f5ff,#fff,#f0f5ff)} @media (prefers-color-scheme:dark){#brand{background:linear-gradient(180deg,#16191f,#0e1116);border:1px solid #2b313a;color:#fff}}
.badge{border:1px solid #e5e7eb;background:#fff;border-radius:.5rem;padding:.125rem .375rem;font-size:10px} #brand:disabled{opacity:.95}
kbd{border:1px solid #e5e7eb;border-bottom-width:2px;border-radius:.375rem;background:#fff;padding:.05rem .3rem;font-size:10px} .hero{display:grid;place-items:center;text-align:center;margin:16px 0 6px}
a.anchor{color:#111827;text-decoration:none;border-bottom:1px dashed #d1d5db} .hero .stamp{display:inline-grid;place-items:center;gap:8px;color:inherit}
.hero .stamp .ring{opacity:.72}
.hero h1{font-weight:800;font-size:20px;margin:6px 0 10px;letter-spacing:.2px}
.hero p{margin:0 auto;max-width:720px;opacity:.85}
.badges{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;margin:12px 0 18px}
.badges .b{display:inline-flex;align-items:center;gap:6px;border:1px solid #e4e7eb;border-radius:999px;padding:4px 10px;background:linear-gradient(180deg,#fff,#fafafa)}
@media (prefers-color-scheme:dark){.badges .b{border-color:#2b313a;background:linear-gradient(180deg,#141821,#0c0f14)}}
hr.soft{border:0;height:1px;background:linear-gradient(90deg,transparent,#d6dbe2,transparent);margin:22px 0}
@media (prefers-color-scheme:dark){hr.soft{background:linear-gradient(90deg,transparent,#2b313a,transparent)}}
blockquote{border-left:3px solid #c7d1e6;padding:.2em .9em;margin:.6em 0;background:#f8fbff}
@media (prefers-color-scheme:dark){blockquote{border-color:#354157;background:#0c121b}}
.note{font-size:11.5px;opacity:.8}
.center{text-align:center}
kbd{border:1px solid #ccd1d7;border-bottom-color:#b6bcc3;padding:1px 4px;border-radius:4px;background:#fff;box-shadow:inset 0 -1px 0 #b6bcc3}
@media (prefers-color-scheme:dark){kbd{border-color:#333940;border-bottom-color:#242a31;background:#0c0f14;box-shadow:inset 0 -1px 0 #242a31}}
pre code.hljs{display:block;padding:12px;border-radius:10px}
.foot{opacity:.7}
small{opacity:.84}
svg{max-width:100%}
a{color:inherit}
</style> </style>
<script>
tailwind.config={theme:{extend:{fontFamily:{sans:['Inter','ui-sans-serif','system-ui'],mono:['Fira Code','ui-monospace']}}}}
</script>
</head> </head>
<body class="min-h-dvh bg-white text-gray-900 selection:bg-black/10 text-xs"> <body>
<header class="sticky top-0 z-20 bg-white/80 backdrop-blur border-b border-gray-200"> <header><button id=brand disabled aria-disabled=true title="You cant click this">Hi</button></header>
<div class="mx-auto max-w-3xl px-3 py-2 grid grid-cols-3 items-center">
<nav class="flex gap-2 items-center"> <main class="markdown-body" id=app></main>
<a href="#overview" class="badge">Overview</a>
<a href="#syntax" class="badge">Syntax</a> <!-- Content (Markdown). Use ~~~ fences to avoid backticks in this file -->
<a href="#blocks" class="badge">Blocks</a> <script id=md type=text/markdown>
</nav> <div class="hero">
<div class="flex items-center justify-center"> <div class="stamp">
<button aria-label="Hi" disabled class="pointer-events-none select-none h-8 px-4 rounded-full bg-gray-200 text-gray-900 font-semibold">Hi</button> <svg class="ring" viewBox="0 0 200 200" width="120" height="120" role="img" aria-label="Symbol ring">
</div> <defs><path id="circ" d="M100 100 m -64,0 a 64,64 0 1,1 128,0 a 64,64 0 1,1 -128,0"/></defs>
<div class="flex justify-end items-center gap-1"> <text font-size="11.6" fill="currentColor">
<a class="badge hidden sm:inline" href="https://github.com/hi-language" target="_blank" rel="noreferrer">GitHub</a> <textPath href="#circ" startOffset="0%">
<button id="copyAll" class="badge" title="Copy all examples">Copy all</button> : = # ? * [ ] { } ( ) ƒ · ¬ × : = # ? * [ ] { } ( )
</div> </textPath>
</text>
<circle cx="100" cy="100" r="3" fill="currentColor"/>
</svg>
<div><small>symbol-first ai-friendly code-golfable</small></div>
</div> </div>
</header> </div>
<main class="mx-auto max-w-3xl px-3"> # The Hi programming language <i data-lucide="sparkles" style="width:16px;height:16px;vertical-align:-2px;"></i>
<section class="hero-grad rounded-2xl border border-gray-200 mt-4 p-4 sm:p-6">
<div class="flex items-center gap-2 text-[11px] text-gray-600 mb-2">
<span class="badge">Symbolic</span>
<span class="badge">JS-inspired</span>
<span class="badge">AI-first</span>
<span class="badge">Code-golf friendly</span>
</div>
<div class="flex items-center gap-3">
<div class="h-12 w-12 rounded-xl bg-gradient-to-br from-black to-gray-600 text-white grid place-items-center font-extrabold">Hi</div>
<div>
<h1 class="text-base sm:text-lg font-extrabold leading-tight">Hi — a tiny, symbolic, AI-first programming language</h1>
<p class="text-[11px] sm:text-xs text-gray-600">Keep the core mostly symbols so everyone can read/write it. Let humans and AIs meet at the shortest path.</p>
</div>
</div>
<div class="mt-4 grid sm:grid-cols-[1fr,220px] gap-4"> Hi is a tiny, JSinspired language that prefers symbols over keywords. Fewer words fewer walls between people. And with an AIfirst mindset, we bias toward patterns that are easy to write, read, compress, and transform. The result feels like a playful toolbox that also respects production constraints.
<article id="mdOut" class="markdown-body"></article>
<aside class="rounded-xl border border-gray-200 bg-white/70 p-3">
<div class="text-[11px] text-gray-500 mb-2">Shape of a program</div>
<svg viewBox="0 0 220 180" width="100%" height="180" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="g1" x1="0" x2="1">
<stop offset="0%" stop-color="#111827"/>
<stop offset="100%" stop-color="#4b5563"/>
</linearGradient>
</defs>
<rect x="1" y="1" width="218" height="178" rx="12" fill="#fff" stroke="#e5e7eb"/>
<g font-family="Inter" font-size="10" fill="#111827">
<rect x="18" y="18" width="70" height="32" rx="7" fill="#f3f4f6" stroke="#e5e7eb"/>
<text x="53" y="38" text-anchor="middle">Source.hi</text>
<rect x="132" y="18" width="70" height="32" rx="7" fill="#f3f4f6" stroke="#e5e7eb"/>
<text x="167" y="38" text-anchor="middle">Blocks</text>
<path d="M88 34h36" stroke="url(#g1)" stroke-width="1.2"/> <div class="badges">
<polygon points="125,34 119,31 119,37" fill="#4b5563"/> <span class="b"><i data-lucide="code-2"></i> JSfluent</span>
<span class="b"><i data-lucide="zap"></i> Symbolcore</span>
<span class="b"><i data-lucide="scissors"></i> Codegolf aware</span>
<span class="b"><i data-lucide="bot"></i> AIread/write</span>
<span class="b"><i data-lucide="package"></i> 1 Block to rule them all</span>
</div>
<rect x="18" y="74" width="184" height="36" rx="7" fill="#f9fafb" stroke="#e5e7eb"/> > Feeling note: I love how symbols level the playing field. Fewer English words = less bias. It makes me think of music notation dense, expressive, and multilingual.
<text x="110" y="96" text-anchor="middle">Symbols: <tspan fill="#374151">: = { } ( ) [ ] # ? *</tspan></text>
<rect x="18" y="128" width="184" height="32" rx="7" fill="#eef2ff" stroke="#e5e7eb"/> <hr class="soft">
<text x="110" y="147" text-anchor="middle">Object ∧ Function = Block</text>
</g>
</svg>
<div class="mt-2 text-[11px] text-gray-600">
In Hi, a Block is both an object and a function. The last expression returns. Private fields start with <code>#</code>.
</div>
</aside>
</div>
</section>
<footer class="py-8 text-center text-[11px] text-gray-500"> ## Hello, world
<div class="mb-2">Made with markdown-it, highlight.js (JS mode), and lucide icons.</div> ~~~js
<div>Hi is early and evolving. Syntax and semantics may change.</div> // Hello World in Hi
</footer>
</main>
<script id="md" type="text/markdown">
<a id="overview"></a>
### Why Hi?
- Corely symbolic: fewer keywords, more universal glyphs. Symbols travel better across languages and scripts.
- JS-inspired pragmatism, but not JS. If you know JS, youll grok Hi fast.
- AI-first: short, rigid tokens make parsing/generation simpler for LLMs. Great for code-golf, great for machines.
> Printing uses `_()` — think “say”. Comments are `//`.
```js
// Hello, world
_("Hi world") _("Hi world")
~~~
- `_` is the standard print/write function.
- Code fences use JS highlighting for now.
## Declarations and assignments
~~~js
// Symbols over keywords:
name: "Orion" // Declaration
times = 3 // Assignment
~~~
- `:` declares a name.
- `=` assigns to an existing name.
## Blocks unify data and behavior
In Hi, `{}` makes a Block. Its always both an object and a function. That means you can store properties and also call it.
~~~js
// Function Block
sayHi: {
_("Hi")
}
sayHi() // call like a function
~~~
~~~js
// Object Block
player: {
name: "Orion" // public
#hp: 100 // private
}
_(player.name) // "Orion"
~~~
~~~js
// Hybrid Block (object + private state + behavior)
counter: {
#value: 0
inc: {
value = value + 1
_("The count is now: " + value)
}
}
counter.inc() // "The count is now: 1"
counter.inc() // "The count is now: 2"
~~~
- In JS you cant have a bare object that is callable and also carries private state without factories/closures. Here its natural.
- My feeling: this is surprisingly calming. The thingness and the action live together, so I dont have to keep mental tabs on where state hides. It reminds me of little selfcontained organisms.
### A quick philosophy riff
Blocks make programs read like small poems: name a thing with `:`, give it a heart with `#private` state, give it hands as callable parts, and let it speak with `_`.
## Parameters
~~~js
withParams: (str) {
_(str)
}
withParams("Hey!") // "Hey!"
~~~
## Truthiness (designed for clarity and golfing)
~~~js
0 // falsy (the official false)
!0 // truthy (the official true)
4 // truthy
"" // falsy (truthy if non-empty)
{} // falsy (truthy if non-empty)
[] // falsy (truthy if non-empty)
-0 // falsy / null / undefined (collapses empties)
== // equivalent to JS ===
~~~
- Short to type, easy for AI to normalize, and compact for code golfing.
## Conditionals as expressions with Blocks
~~~js
// if
(cond) ? { /* then */ }
// if / else
(cond) ? { /* then */ } : { /* else */ }
~~~
Like Rust, the last expression in a Block is returned.
~~~js
tern: (cond) ? {"A"} : {"B"}
// A lovely multi-branch:
score: 85
grade: (score > 90) ? {"A"}
: (score > 80) ? {"B"}
: {"C"}
_(grade) // "B"
~~~
> Unification vibe: conditions choose Blocks, not statements. Data and behavior stay composable. This makes composition and refactoring feel like sliding tiles instead of rewriting grammar.
## Arrays
~~~js
primes: [2, 3, 5, 7]
// Access
firstPrime: primes[0]
// Mutation
primes[0] = 1
_(primes) // [1, 3, 5, 7]
~~~
## Loops
~~~js
// for
(i: 0; i < 5; i = i + 1) * {
_(i)
}
// while
(!0) * {
// ...do stuff forever (truthy)...
^ // break
}
// flow control
>> // continue
^ // break
~~~
### Bridging examples
Sometimes the smallest examples teach the most.
~~~js
// 1) Tiny math util
add: (a, b) { a + b }
_(add(2, 5)) // 7
// 2) A Block that is both config and runnable
job: {
name: "daily-report"
#runs: 0
run: {
runs = runs + 1
_("running " + name + " #" + runs)
}
}
job.run() // "running daily-report #1"
// 3) Method-style call reads well
user: {
name: "Kai"
hello: { _("Hi " + name) }
}
user.hello() // "Hi Kai"
// 4) Short-circuit with truthy/falsy style
safeName: user.name ? { user.name } : { "Anonymous" }
~~~
> Feeling note: the private `#` makes me smile. Privacy as a first thought, not an afterthought, nudges me to design better modules.
<hr class="soft">
## Why symbols? Why now?
- Worldfriendly: Symbols sidestep English heavy keywords.
- AIfriendly: Tokens are short, consistent, easy to learn and predict. Models thrive on regular patterns.
- Golffriendly: Less keystrokes, fewer ceremony characters, more signal.
I feel a little thrill when a language removes accidental complexity. The code shrinks and my intent gets louder.
## Design snapshot
- `:` declare `=` assign
- `{}` Block = object function
- `#name` private field in its Block
- `()` call or params
- `? :` expressions that yield values (Blocks)
- `*` loop operator
- `>>` continue `^` break
- `0` false `!0` true `-0` empty/nullish collapse
- `==` is JS `===`
## A tiny mental model
~~~js
// A program is a map of names → Blocks.
// A Block is:
// - a bag of properties (public + #private)
// - a callable body (optional)
// - a scope for its internals
// - an expression that returns its last value
~~~
### A miniature sketch that ties it all
~~~js
main: {
title: "Hi"
#visits: 0
greet: (who) { _("Hi, " + who) }
tick: {
visits = visits + 1
_("visits=" + visits)
}
run: {
greet("world")
tick()
(visits > 1) ? {"returning"} : {"first-time"}
}
}
_(main.run()) // "returning" after second call
~~~
> Personal aside: the above reads like a little organism with memory and reflexes. I can almost feel the shape of the program in my hands.
<hr class="soft">
<div class="center">
<i data-lucide="beaker" style="width:16px;height:16px;vertical-align:-3px;"></i>
<strong>Status:</strong> Hi is in active development. Syntax and semantics may evolve.
<div class="note">We currently use JS highlighting in code fences until a dedicated Hi lexer lands.</div>
</div>
</script>
<!-- libs -->
<script src=https://cdn.jsdelivr.net/npm/markdown-it@13.0.1/dist/markdown-it.min.js integrity=sha256-9XJMEdXL4iQOA06pW2FQk1rXyiZg8Wmrl9M4m1pG56o= crossorigin=anonymous></script>
<script src=https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js integrity=sha512-B9LYv1kbEKj4QywiJH7+UO7J9aD50S88H8+C4qQJY4kW3fH8c1G0k7L3CybA4g2w+O1QfM+2b0gM7bZ2BfY7xA== crossorigin=anonymous referrerpolicy=no-referrer></script>
<script src=https://unpkg.com/lucide@latest/dist/umd/lucide.min.js></script>
<!-- render -->
<script>
(()=>{const $=e=>document.querySelector(e),md=window.markdownit({html:!0,linkify:!0,typographer:!0,highlight:(s,l)=>{try{return hljs.highlight(s,{language:'javascript'}).value}catch{return hljs.highlightAuto(s).value}}});$("#app").innerHTML=md.render($("#md").textContent.trim());lucide&&lucide.createIcons({attrs:{'stroke-width':1.75}})})();
</script>
<footer class="markdown-body foot center"><small>© <span id=y></span> Hi language team • Built with markdown-it, GitHub Markdown CSS, Lucide, and highlight.js.</small></footer>
<script>y.textContent=(new Date).getFullYear()</script>
</body>
</html>