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

This commit is contained in:
2025-09-15 00:19:19 -07:00
parent a3ce37555b
commit b58406cb63
+310 -102
View File
@@ -1,119 +1,327 @@
<!doctype html><html lang=en>
<head>
<meta charset=utf-8>
<meta name=viewport content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>Hi — a tiny, symbolic, AI-first programming language</title>
<meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1">
<title>Hi — a tiny, symbolic, AI‑first language</title>
<link rel=preconnect href=https://fonts.googleapis.com>
<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>
<script src="https://cdn.tailwindcss.com"></script>
<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://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/styles/github.min.css">
<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>
<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://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css integrity=sha512-3mb8zCey3p+3w0lI04lH8mKeb4d0x1c6PXo2g0Q9yQkQhy/c6v2dGEZ7V6o0H6YugyS0r5uEIAJ0u8oHNoq6tA== crossorigin=anonymous referrerpolicy=no-referrer>
<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}
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}
code,pre,.font-mono{font-family:"Fira Code",ui-monospace,Menlo,Consolas,monospace}
.markdown-body{font-size:12px;line-height:1.6}
.markdown-body pre{overflow:auto}
.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}
pre{border:1px solid #e5e7eb;border-radius:.5rem;position:relative}
.hero-grad{--g:radial-gradient(60% 60% at 50% 40%,rgba(120,119,198,.15),rgba(255,255,255,0) 60%);background:
var(--g),conic-gradient(from 180deg at 50% 50%,#f0f5ff,#fff,#f0f5ff)}
.badge{border:1px solid #e5e7eb;background:#fff;border-radius:.5rem;padding:.125rem .375rem;font-size:10px}
kbd{border:1px solid #e5e7eb;border-bottom-width:2px;border-radius:.375rem;background:#fff;padding:.05rem .3rem;font-size:10px}
a.anchor{color:#111827;text-decoration:none;border-bottom:1px dashed #d1d5db}
html{color-scheme:light dark}
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)}
@media (prefers-color-scheme:dark){body{background:var(--bgD)}}
.markdown-body{font-size:12.6px;max-width:920px;padding:64px 18px 80px;margin:0 auto;color:inherit}
code,kbd,pre,samp{font-family:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;font-size:12px}
header{position:sticky;top:8px;z-index:9;display:grid;place-items:center;height:0}
#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}
@media (prefers-color-scheme:dark){#brand{background:linear-gradient(180deg,#16191f,#0e1116);border:1px solid #2b313a;color:#fff}}
#brand:disabled{opacity:.95}
.hero{display:grid;place-items:center;text-align:center;margin:16px 0 6px}
.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>
<script>
tailwind.config={theme:{extend:{fontFamily:{sans:['Inter','ui-sans-serif','system-ui'],mono:['Fira Code','ui-monospace']}}}}
</script>
</head>
<body class="min-h-dvh bg-white text-gray-900 selection:bg-black/10 text-xs">
<header class="sticky top-0 z-20 bg-white/80 backdrop-blur border-b border-gray-200">
<div class="mx-auto max-w-3xl px-3 py-2 grid grid-cols-3 items-center">
<nav class="flex gap-2 items-center">
<a href="#overview" class="badge">Overview</a>
<a href="#syntax" class="badge">Syntax</a>
<a href="#blocks" class="badge">Blocks</a>
</nav>
<div class="flex items-center justify-center">
<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>
</div>
<div class="flex justify-end items-center gap-1">
<a class="badge hidden sm:inline" href="https://github.com/hi-language" target="_blank" rel="noreferrer">GitHub</a>
<button id="copyAll" class="badge" title="Copy all examples">Copy all</button>
</div>
<body>
<header><button id=brand disabled aria-disabled=true title="You can’t click this">Hi</button></header>
<main class="markdown-body" id=app></main>
<!-- Content (Markdown). Use ~~~ fences to avoid backticks in this file -->
<script id=md type=text/markdown>
<div class="hero">
<div class="stamp">
<svg class="ring" viewBox="0 0 200 200" width="120" height="120" role="img" aria-label="Symbol ring">
<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>
<text font-size="11.6" fill="currentColor">
<textPath href="#circ" startOffset="0%">
: = # ? * [ ] { } ( ) → ƒ · ¬ ∧ ∨ × ⊕ : = # ? * [ ] { } ( ) →
</textPath>
</text>
<circle cx="100" cy="100" r="3" fill="currentColor"/>
</svg>
<div><small>symbol-first • ai-friendly • code-golfable</small></div>
</div>
</header>
</div>
<main class="mx-auto max-w-3xl px-3">
<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>
# The “Hi” programming language <i data-lucide="sparkles" style="width:16px;height:16px;vertical-align:-2px;"></i>
<div class="mt-4 grid sm:grid-cols-[1fr,220px] gap-4">
<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>
Hi is a tiny, JS‑inspired language that prefers symbols over keywords. Fewer words → fewer walls between people. And with an AI‑first 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.
<path d="M88 34h36" stroke="url(#g1)" stroke-width="1.2"/>
<polygon points="125,34 119,31 119,37" fill="#4b5563"/>
<div class="badges">
<span class="b"><i data-lucide="code-2"></i> JS‑fluent</span>
<span class="b"><i data-lucide="zap"></i> Symbol‑core</span>
<span class="b"><i data-lucide="scissors"></i> Code‑golf aware</span>
<span class="b"><i data-lucide="bot"></i> AI‑read/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"/>
<text x="110" y="96" text-anchor="middle">Symbols: <tspan fill="#374151">: = { } ( ) [ ] # ? *</tspan></text>
> 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.
<rect x="18" y="128" width="184" height="32" rx="7" fill="#eef2ff" stroke="#e5e7eb"/>
<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>
<hr class="soft">
<footer class="py-8 text-center text-[11px] text-gray-500">
<div class="mb-2">Made with markdown-it, highlight.js (JS mode), and lucide icons.</div>
<div>Hi is early and evolving. Syntax and semantics may change.</div>
</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, you’ll 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
## Hello, world
~~~js
// Hello World in Hi
_("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. It’s 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 can’t have a bare object that is callable and also carries private state without factories/closures. Here it’s natural.
- My feeling: this is surprisingly calming. The “thingness” and the “action” live together, so I don’t have to keep mental tabs on where state hides. It reminds me of little self‑contained 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?
- World‑friendly: Symbols sidestep English heavy keywords.
- AI‑friendly: Tokens are short, consistent, easy to learn and predict. Models thrive on regular patterns.
- Golf‑friendly: 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>