mirror of
https://github.com/hi-language/hi-language.github.io.git
synced 2026-01-14 08:38:36 +00:00
Feat: Hi intro docs site
This commit is contained in:
358
index.html
358
index.html
@@ -1 +1,357 @@
|
|||||||
Hi World
|
<!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 Language — Symbolic, World‑First</title>
|
||||||
|
|
||||||
|
<!-- Tailwind (for layout/spacing/utility) -->
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
|
||||||
|
<!-- GitHub Markdown skin + HLJS GitHub theme -->
|
||||||
|
<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"/>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:root{color-scheme:light}
|
||||||
|
html,body{height:100%}
|
||||||
|
.no-scrollbar::-webkit-scrollbar{display:none}
|
||||||
|
.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}
|
||||||
|
.markdown-body{font-size:16px;line-height:1.65}
|
||||||
|
.markdown-body :is(h1,h2,h3){scroll-margin-top:84px}
|
||||||
|
.markdown-body pre{overflow:auto}
|
||||||
|
.copy-btn{position:absolute;top:.5rem;right:.5rem;font-size:.75rem;padding:.25rem .5rem;border-radius:.5rem;background:#0f172a;color:#fff;opacity:.9}
|
||||||
|
.copy-btn:hover{opacity:1}
|
||||||
|
.toc-link{display:block;padding:.5rem .75rem;border-radius:.75rem}
|
||||||
|
.toc-link:hover{background:#f3f4f6}
|
||||||
|
.toc-active{background:#eef2ff}
|
||||||
|
.brand-dot{display:inline-flex;align-items:center;justify-content:center;height:28px;width:28px;border-radius:9999px;background:#0f172a;color:#fff}
|
||||||
|
header{backdrop-filter:saturate(180%) blur(8px)}
|
||||||
|
@media (min-width:1024px){
|
||||||
|
#contentWrap{grid-template-columns: 280px 1fr}
|
||||||
|
#sidebarLeft{position:sticky;top:64px;height:calc(100dvh - 64px);transform:none!important}
|
||||||
|
#sidebarOverlay{display:none!important}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- Alpine + Lucide + MarkdownIt + HLJS -->
|
||||||
|
<script defer src="https://unpkg.com/alpinejs"></script>
|
||||||
|
<script src="https://unpkg.com/lucide@latest"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.11.1/build/highlight.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body class="bg-white text-gray-900 selection:bg-black/10" x-data="{open:false}" @keydown.escape="open=false">
|
||||||
|
<!-- Topbar -->
|
||||||
|
<header class="sticky top-0 z-20 bg-white/85 border-b border-gray-200">
|
||||||
|
<div class="mx-auto max-w-6xl px-4 py-3 grid grid-cols-3 items-center">
|
||||||
|
<button class="h-8 w-8 rounded-xl bg-gray-100 hover:bg-gray-200 active:scale-[.99] transition flex items-center justify-center"
|
||||||
|
title="Menu" @click="open=true">
|
||||||
|
<i data-lucide="panel-left" class="h-5 w-5"></i>
|
||||||
|
</button>
|
||||||
|
<div class="justify-self-center text-base font-semibold tracking-tight select-none pointer-events-none">Hi</div>
|
||||||
|
<div class="justify-self-end"></div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<div id="contentWrap" class="mx-auto max-w-6xl lg:grid relative">
|
||||||
|
<!-- Left sidebar -->
|
||||||
|
<aside id="sidebarLeft" class="fixed inset-y-0 left-0 z-50 w-72 max-w-[85vw] bg-white border-r border-gray-200 shadow-xl transform -translate-x-full transition-transform duration-200 ease-out lg:static lg:shadow-none lg:w-auto">
|
||||||
|
<div class="p-3 border-b flex items-center gap-3">
|
||||||
|
<span class="brand-dot">✺</span>
|
||||||
|
<div class="min-w-0">
|
||||||
|
<div class="text-sm font-semibold truncate">Hi</div>
|
||||||
|
<div class="text-xs text-gray-500 truncate">A symbolic language for everyone</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<nav id="toc" class="p-2 overflow-y-auto no-scrollbar space-y-1 text-sm"></nav>
|
||||||
|
<div class="p-3 border-t text-xs text-gray-500">
|
||||||
|
<span>Still in development — more coming soon.</span>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
<div id="sidebarOverlay" class="fixed inset-0 z-40 bg-black/20 hidden" :class="open?'':'hidden'" @click="open=false"></div>
|
||||||
|
<script>
|
||||||
|
document.addEventListener('alpine:init',()=>{Alpine.effect(()=>{const a=document.getElementById('sidebarLeft');if(!a)return;a.style.transform=Alpine.store('open')?'translateX(0)':''})})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Main -->
|
||||||
|
<main id="main" class="min-h-[calc(100dvh-64px)]">
|
||||||
|
<section id="suneHtml" class="markdown-body px-4 sm:px-6 lg:px-10 py-8"></section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded',()=>{
|
||||||
|
|
||||||
|
const md = window.markdownit({html:false,linkify:true,typographer:true,breaks:true})
|
||||||
|
const slug = s=>s.toLowerCase().trim()
|
||||||
|
.replace(/["'’]/g,'')
|
||||||
|
.replace(/&/g,' and ')
|
||||||
|
.replace(/[^a-z0-9]+/g,'-')
|
||||||
|
.replace(/^-+|-+$/g,'')||'sec'
|
||||||
|
const $ = s=>document.querySelector(s)
|
||||||
|
const $$ = s=>[...document.querySelectorAll(s)]
|
||||||
|
const icons = ()=>window.lucide&&lucide.createIcons()
|
||||||
|
|
||||||
|
const DOC = String.raw`
|
||||||
|
# Hi
|
||||||
|
A new, symbolic programming language inspired by JavaScript — but with a "corely" symbolic design. Fewer keywords, more universal symbols. Hi aims to be approachable worldwide.
|
||||||
|
|
||||||
|
> Tip: All code snippets below use JavaScript syntax highlighting while Hi is still evolving.
|
||||||
|
|
||||||
|
## Hello, world
|
||||||
|
\`\`\`js
|
||||||
|
// This is hello world in Hi
|
||||||
|
_("Hi world")
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Symbols you’ll meet first
|
||||||
|
- \`: \` declaration
|
||||||
|
- \`= \` assignment
|
||||||
|
- \`{ ... }\` a Block (both object and function)
|
||||||
|
- \`#name\` private field in a Block
|
||||||
|
- \`_("...")\` print (show text)
|
||||||
|
- \`? :\` conditional (blocks return last value)
|
||||||
|
- \`* { ... }\` loop body
|
||||||
|
- \`>>\` continue, \`^\` break
|
||||||
|
|
||||||
|
Blocks are always both an object and a function. They can hold properties and executable code at once.
|
||||||
|
|
||||||
|
## Blocks
|
||||||
|
### Function Block
|
||||||
|
\`\`\`js
|
||||||
|
sayHi: {
|
||||||
|
_("Hi")
|
||||||
|
}
|
||||||
|
sayHi() // call the Block like a function
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Object Block
|
||||||
|
\`\`\`js
|
||||||
|
player: {
|
||||||
|
name: "Orion" // public
|
||||||
|
#hp: 100 // private
|
||||||
|
}
|
||||||
|
_(player.name) // "Orion"
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Hybrid Block
|
||||||
|
\`\`\`js
|
||||||
|
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
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
\`\`\`js
|
||||||
|
withParams: (str) {
|
||||||
|
_(str)
|
||||||
|
}
|
||||||
|
withParams("Hola") // prints Hola
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Truthiness and equality
|
||||||
|
Hi emphasizes clear truthiness:
|
||||||
|
\`\`\`js
|
||||||
|
0 // falsy (official false)
|
||||||
|
!0 // truthy (official true)
|
||||||
|
4 // truthy
|
||||||
|
"" // falsy (truthy if non-empty)
|
||||||
|
{} // falsy (truthy if contains fields or code ran)
|
||||||
|
[] // falsy (truthy if non-empty)
|
||||||
|
-0 // falsy / null / undefined equivalent-ish in Hi's model
|
||||||
|
|
||||||
|
// Equality is simple:
|
||||||
|
== // equivalent to JS ===
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Conditionals
|
||||||
|
Blocks return their last value (like Rust expressions).
|
||||||
|
\`\`\`js
|
||||||
|
// if
|
||||||
|
(cond) ? { _("yes") }
|
||||||
|
|
||||||
|
// if / else
|
||||||
|
(cond) ? { _("yes") } : { _("no") }
|
||||||
|
|
||||||
|
// as an expression
|
||||||
|
tern: (cond) ? { "A" } : { "B" }
|
||||||
|
_(tern) // prints A or B
|
||||||
|
|
||||||
|
// else-if chain
|
||||||
|
score: 85
|
||||||
|
grade: (score > 90) ? { "A" }
|
||||||
|
: (score > 80) ? { "B" }
|
||||||
|
: { "C" }
|
||||||
|
_(grade) // "B"
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Arrays
|
||||||
|
\`\`\`js
|
||||||
|
primes: [2, 3, 5, 7]
|
||||||
|
|
||||||
|
// Access
|
||||||
|
firstPrime: primes[0]
|
||||||
|
|
||||||
|
// Mutation
|
||||||
|
primes[0] = 1
|
||||||
|
_(primes) // [1, 3, 5, 7]
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Loops
|
||||||
|
Use \`* { ... }\` after a loop header. \`>>\` continues, \`^\` breaks.
|
||||||
|
\`\`\`js
|
||||||
|
// for
|
||||||
|
(i: 0; i < 5; i = i + 1) * {
|
||||||
|
_(i)
|
||||||
|
(i == 2) ? { >> } // continue at i==2 (skip rest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// while
|
||||||
|
(done: !0) * {
|
||||||
|
// ...
|
||||||
|
^ // break
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Putting it together
|
||||||
|
Here are a few small programs that connect the dots.
|
||||||
|
|
||||||
|
### FizzBuzz
|
||||||
|
\`\`\`js
|
||||||
|
fizzbuzz: (n) {
|
||||||
|
(n % 15 == 0) ? { "FizzBuzz" }
|
||||||
|
: (n % 3 == 0) ? { "Fizz" }
|
||||||
|
: (n % 5 == 0) ? { "Buzz" }
|
||||||
|
: { n }
|
||||||
|
}
|
||||||
|
|
||||||
|
(i: 1; i <= 16; i = i + 1) * {
|
||||||
|
_( fizzbuzz(i) )
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### A tiny accumulator
|
||||||
|
\`\`\`js
|
||||||
|
acc: {
|
||||||
|
#sum: 0
|
||||||
|
add: (x) { sum = sum + x }
|
||||||
|
get: { sum }
|
||||||
|
}
|
||||||
|
|
||||||
|
acc.add(6)
|
||||||
|
acc.add(7)
|
||||||
|
_( acc.get() ) // 13
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Recursive example
|
||||||
|
\`\`\`js
|
||||||
|
fib: (n) {
|
||||||
|
(n < 2) ? { n } : { fib(n-1) + fib(n-2) }
|
||||||
|
}
|
||||||
|
_( fib(6) ) // 8
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Design philosophy
|
||||||
|
Hi keeps its core "mostly symbols" to be friendlier across languages and writing systems. Keywords appear where they’re practical; everywhere else, symbols do the heavy lifting. The goal: an approachable, expressive language for the whole world.
|
||||||
|
|
||||||
|
—
|
||||||
|
|
||||||
|
Hi is in active development. Expect changes, clarifications, and more features, examples, and tooling soon. Stay tuned!
|
||||||
|
`
|
||||||
|
|
||||||
|
// Render docs
|
||||||
|
const root = $('#suneHtml')
|
||||||
|
root.innerHTML = md.render(DOC)
|
||||||
|
|
||||||
|
// Add ids to headings + build TOC
|
||||||
|
const heads = $$('h1, h2, h3', root) // query relative later
|
||||||
|
const tocEl = $('#toc')
|
||||||
|
const items=[]
|
||||||
|
$$('#suneHtml h1, #suneHtml h2, #suneHtml h3').forEach(h=>{
|
||||||
|
const level = +h.tagName.slice(1)
|
||||||
|
const id = h.id || slug(h.textContent||'')
|
||||||
|
h.id = id
|
||||||
|
// small anchor
|
||||||
|
const a=document.createElement('a')
|
||||||
|
a.href = '#'+id
|
||||||
|
a.className='ml-2 align-middle text-gray-300 hover:text-gray-500'
|
||||||
|
a.innerHTML = '<svg data-lucide="link-2" class="inline h-3.5 w-3.5"></svg>'
|
||||||
|
h.appendChild(a)
|
||||||
|
|
||||||
|
if(level<=3 && level>=1){
|
||||||
|
items.push({id,level,text:h.textContent.replace(/\s*$/,'')})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
tocEl.innerHTML = [
|
||||||
|
'<div class="px-3 py-2 text-xs font-medium text-gray-500 uppercase tracking-wide">Contents</div>',
|
||||||
|
...items.map(x=>{
|
||||||
|
const pad = x.level===1?'pl-3':x.level===2?'pl-5':'pl-8'
|
||||||
|
return `<a class="toc-link ${pad}" href="#${x.id}" data-id="${x.id}">${x.text}</a>`
|
||||||
|
})
|
||||||
|
].join('')
|
||||||
|
|
||||||
|
// Scroll handling
|
||||||
|
tocEl.addEventListener('click',e=>{
|
||||||
|
const a=e.target.closest('a[href^="#"]'); if(!a) return
|
||||||
|
e.preventDefault()
|
||||||
|
const id=a.getAttribute('href').slice(1)
|
||||||
|
const el=document.getElementById(id); if(!el) return
|
||||||
|
window.scrollTo({top:el.getBoundingClientRect().top+window.scrollY-72,behavior:'smooth'})
|
||||||
|
const overlay=$("#sidebarOverlay"); if(getComputedStyle(overlay).display!=='none') document.body.__x?.$data.open=false
|
||||||
|
})
|
||||||
|
|
||||||
|
// Scrollspy
|
||||||
|
const links = $$('#toc .toc-link')
|
||||||
|
const map = Object.fromEntries(links.map(a=>[a.dataset.id,a]))
|
||||||
|
const io = new IntersectionObserver(es=>{
|
||||||
|
es.forEach(({isIntersecting, target})=>{
|
||||||
|
if(!isIntersecting) return
|
||||||
|
const id=target.id; if(map[id]){
|
||||||
|
links.forEach(l=>l.classList.remove('toc-active'))
|
||||||
|
map[id].classList.add('toc-active')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},{rootMargin:'-60px 0px -70% 0px',threshold:1e-3})
|
||||||
|
$$('#suneHtml h1, #suneHtml h2').forEach(h=>io.observe(h))
|
||||||
|
|
||||||
|
// Highlight + small copy buttons
|
||||||
|
hljs.highlightAll()
|
||||||
|
$$('#suneHtml pre>code').forEach(code=>{
|
||||||
|
const pre=code.parentElement
|
||||||
|
pre.style.position='relative'
|
||||||
|
const btn=document.createElement('button')
|
||||||
|
btn.className='copy-btn'
|
||||||
|
btn.innerHTML='<svg data-lucide="copy" class="inline h-3.5 w-3.5 mr-1 -mt-0.5"></svg>Copy'
|
||||||
|
btn.addEventListener('click',async e=>{
|
||||||
|
e.stopPropagation()
|
||||||
|
try{
|
||||||
|
await navigator.clipboard.writeText(code.innerText)
|
||||||
|
btn.innerHTML='<svg data-lucide="check" class="inline h-3.5 w-3.5 mr-1 -mt-0.5"></svg>Copied'
|
||||||
|
icons(); setTimeout(()=>{btn.innerHTML='<svg data-lucide="copy" class="inline h-3.5 w-3.5 mr-1 -mt-0.5"></svg>Copy'; icons()},1200)
|
||||||
|
}catch{}
|
||||||
|
})
|
||||||
|
pre.appendChild(btn)
|
||||||
|
})
|
||||||
|
|
||||||
|
// Sidebar toggle (Alpine) for mobile
|
||||||
|
const side=$("#sidebarLeft"), overlay=$("#sidebarOverlay")
|
||||||
|
const open=()=>{side.classList.remove('-translate-x-full');overlay.classList.remove('hidden')}
|
||||||
|
const close=()=>{side.classList.add('-translate-x-full');overlay.classList.add('hidden')}
|
||||||
|
document.querySelector('button[title="Menu"]').addEventListener('click',open,{passive:true})
|
||||||
|
overlay.addEventListener('click',close,{passive:true})
|
||||||
|
|
||||||
|
// Icons
|
||||||
|
icons()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user