scripts/
static/
avatars/
fonts/
js/
hirad.js
2.9 KiB
hiril.js
3.0 KiB
radiant.svg
1.9 KiB
style.css
23.3 KiB
templates/
.gitignore
30 B
.gitsigners
112 B
AGENTS.md
7.5 KiB
LICENSE
89 B
README.md
1.9 KiB
deploy
723 B
discuss.go
16.7 KiB
git.go
3.5 KiB
git_cli.go
16.0 KiB
git_http.go
1.9 KiB
go.mod
572 B
go.sum
1.9 KiB
handler.go
11.3 KiB
handler_test.go
69.0 KiB
main.go
5.2 KiB
template.go
8.9 KiB
watch
272 B
static/js/hiril.js
raw
| 1 | (function (hiril) { |
| 2 | // |
| 3 | // hiril - Radiance IL Syntax Highlighter |
| 4 | // |
| 5 | // Copyright (c) 2020-2025 Alexis Sellier |
| 6 | // |
| 7 | const selector = hiril || '.language-ril'; |
| 8 | const keywords = ['fn', 'data', 'extern', 'mut', 'align']; |
| 9 | const instrs = [ |
| 10 | 'reserve', 'load', 'sload', 'store', 'blit', 'copy', |
| 11 | 'add', 'sub', 'mul', 'sdiv', 'udiv', 'srem', 'urem', 'neg', |
| 12 | 'eq', 'ne', 'slt', 'sge', 'ult', 'uge', |
| 13 | 'and', 'or', 'xor', 'shl', 'sshr', 'ushr', 'not', |
| 14 | 'zext', 'sext', 'call', 'ret', 'jmp', |
| 15 | 'switch', 'unreachable', 'ecall', 'ebreak' |
| 16 | ]; |
| 17 | const branchOps = ['br.eq', 'br.ne', 'br.slt', 'br.ult']; |
| 18 | const dataItems = ['str', 'sym', 'undef']; |
| 19 | const types = ['w8', 'w16', 'w32', 'w64']; |
| 20 | |
| 21 | // Syntax definition. |
| 22 | // |
| 23 | // The key becomes the class name of the span around the matched block of code. |
| 24 | const syntax = [ |
| 25 | ['comment', /(\/\/[^\n]*)/g], |
| 26 | ['string' , /("[^"]*")/g], |
| 27 | ['reg' , /(%[0-9]+)/g], |
| 28 | ['label' , /(@[A-Za-z_][A-Za-z#0-9_]*)/g], |
| 29 | ['symbol' , /(\$[A-Za-z_][A-Za-z0-9_]*)/g], |
| 30 | ['number' , /\b(-?[0-9]+|0x[a-fA-F0-9]+)\b/g], |
| 31 | ['delim' , /([{}();:,])/g], |
| 32 | ['keyword', new RegExp('\\b(' + keywords.join('|') + ')\\b', 'g')], |
| 33 | ['instr' , new RegExp('\\b(' + branchOps.join('|').replace(/\./g, '\\.') + ')\\b', 'g')], |
| 34 | ['instr' , new RegExp('\\b(' + instrs.join('|') + ')\\b', 'g')], |
| 35 | ['type' , new RegExp('\\b(' + dataItems.join('|') + ')\\b', 'g')], |
| 36 | ['type' , new RegExp('\\b(' + types.join('|') + ')\\b', 'g')], |
| 37 | ]; |
| 38 | |
| 39 | const table = {}; |
| 40 | |
| 41 | // Encode ASCII characters to Braille to avoid conflicts between patterns. |
| 42 | const encode = (str) => { |
| 43 | const encoded = [...str].map(c => |
| 44 | c.charCodeAt(0) <= 127 ? String.fromCharCode(c.charCodeAt(0) + 0x2800) : c |
| 45 | ).join(''); |
| 46 | table[encoded] = str; |
| 47 | |
| 48 | return encoded; |
| 49 | }; |
| 50 | |
| 51 | // Decode Braille back to ASCII. |
| 52 | const decode = (str) => |
| 53 | table[str] || [...str].map(c => { |
| 54 | const code = c.charCodeAt(0) - 0x2800; |
| 55 | return code >= 0 && code <= 127 ? String.fromCharCode(code) : c; |
| 56 | }).join(''); |
| 57 | |
| 58 | // Escape HTML special characters. |
| 59 | const escape = (str) => |
| 60 | str.replace(/</g, '<').replace(/>/g, '>'); |
| 61 | |
| 62 | // Highlight all matching elements. |
| 63 | for (const node of document.querySelectorAll(selector)) { |
| 64 | for (const child of node.childNodes) { |
| 65 | if (child.nodeType !== Node.TEXT_NODE) continue; |
| 66 | if (/^\$\s/.test(child.nodeValue.trim())) continue; // Skip shell snippets. |
| 67 | |
| 68 | for (const [cls, re] of syntax) { |
| 69 | child.nodeValue = child.nodeValue.replace(re, (_, m) => |
| 70 | '\u00ab' + encode(cls) + '\u00b7' + |
| 71 | encode(m) + |
| 72 | '\u00b7' + encode(cls) + '\u00bb' |
| 73 | ); |
| 74 | } |
| 75 | } |
| 76 | node.innerHTML = node.innerHTML.replace( |
| 77 | /\u00ab(.+?)\u00b7(.+?)\u00b7\1\u00bb/g, |
| 78 | (_, name, value) => { |
| 79 | value = value.replace(/\u00ab[^\u00b7]+\u00b7|\u00b7[^\u00bb]+\u00bb/g, ''); |
| 80 | return '<span class="' + decode(name) + '">' + |
| 81 | escape(decode(value)) + |
| 82 | '</span>'; |
| 83 | } |
| 84 | ); |
| 85 | } |
| 86 | |
| 87 | })(window.hiril); |