96 lines
4.5 KiB
JavaScript
96 lines
4.5 KiB
JavaScript
// Original 5×7 bitmap glyphs. All rendering is local; no fonts or API are fetched.
|
||
const patterns = {
|
||
A: '01110/10001/10001/11111/10001/10001/10001',
|
||
B: '11110/10001/10001/11110/10001/10001/11110',
|
||
C: '01111/10000/10000/10000/10000/10000/01111',
|
||
D: '11110/10001/10001/10001/10001/10001/11110',
|
||
E: '11111/10000/10000/11110/10000/10000/11111',
|
||
F: '11111/10000/10000/11110/10000/10000/10000',
|
||
G: '01111/10000/10000/10111/10001/10001/01111',
|
||
H: '10001/10001/10001/11111/10001/10001/10001',
|
||
I: '11111/00100/00100/00100/00100/00100/11111',
|
||
J: '00111/00010/00010/00010/10010/10010/01100',
|
||
K: '10001/10010/10100/11000/10100/10010/10001',
|
||
L: '10000/10000/10000/10000/10000/10000/11111',
|
||
M: '10001/11011/10101/10101/10001/10001/10001',
|
||
N: '10001/11001/10101/10011/10001/10001/10001',
|
||
O: '01110/10001/10001/10001/10001/10001/01110',
|
||
P: '11110/10001/10001/11110/10000/10000/10000',
|
||
Q: '01110/10001/10001/10001/10101/10010/01101',
|
||
R: '11110/10001/10001/11110/10100/10010/10001',
|
||
S: '01111/10000/10000/01110/00001/00001/11110',
|
||
T: '11111/00100/00100/00100/00100/00100/00100',
|
||
U: '10001/10001/10001/10001/10001/10001/01110',
|
||
V: '10001/10001/10001/10001/10001/01010/00100',
|
||
W: '10001/10001/10001/10101/10101/10101/01010',
|
||
X: '10001/10001/01010/00100/01010/10001/10001',
|
||
Y: '10001/10001/01010/00100/00100/00100/00100',
|
||
Z: '11111/00001/00010/00100/01000/10000/11111',
|
||
0: '01110/10001/10011/10101/11001/10001/01110',
|
||
1: '00100/01100/00100/00100/00100/00100/01110',
|
||
2: '01110/10001/00001/00010/00100/01000/11111',
|
||
3: '11110/00001/00001/01110/00001/00001/11110',
|
||
4: '00010/00110/01010/10010/11111/00010/00010',
|
||
5: '11111/10000/10000/11110/00001/00001/11110',
|
||
6: '01110/10000/10000/11110/10001/10001/01110',
|
||
7: '11111/00001/00010/00100/01000/01000/01000',
|
||
8: '01110/10001/10001/01110/10001/10001/01110',
|
||
9: '01110/10001/10001/01111/00001/00001/01110',
|
||
' ': '000/000/000/000/000/000/000',
|
||
'!': '1/1/1/1/1/0/1',
|
||
'?': '01110/10001/00001/00010/00100/00000/00100',
|
||
'.': '0/0/0/0/0/0/1',
|
||
',': '00/00/00/00/00/01/10',
|
||
':': '0/1/0/0/1/0/0',
|
||
';': '00/01/00/00/01/01/10',
|
||
'-': '000/000/000/111/000/000/000',
|
||
'_': '00000/00000/00000/00000/00000/00000/11111',
|
||
'+': '00000/00100/00100/11111/00100/00100/00000',
|
||
'=': '00000/00000/11111/00000/11111/00000/00000',
|
||
'/': '00001/00001/00010/00100/01000/10000/10000',
|
||
'\\': '10000/10000/01000/00100/00010/00001/00001',
|
||
'(': '001/010/100/100/100/010/001',
|
||
')': '100/010/001/001/001/010/100',
|
||
'[': '111/100/100/100/100/100/111',
|
||
']': '111/001/001/001/001/001/111',
|
||
'{': '001/010/010/100/010/010/001',
|
||
'}': '100/010/010/001/010/010/100',
|
||
'<': '0001/0010/0100/1000/0100/0010/0001',
|
||
'>': '1000/0100/0010/0001/0010/0100/1000',
|
||
"'": '1/1/0/0/0/0/0',
|
||
'"': '101/101/000/000/000/000/000',
|
||
'`': '10/01/00/00/00/00/00',
|
||
'#': '01010/11111/01010/01010/11111/01010/00000',
|
||
'$': '00100/01111/10100/01110/00101/11110/00100',
|
||
'%': '11001/11010/00010/00100/01000/01011/10011',
|
||
'&': '01100/10010/10100/01000/10101/10010/01101',
|
||
'*': '00000/10101/01110/11111/01110/10101/00000',
|
||
'@': '01110/10001/10111/10101/10111/10000/01111',
|
||
'^': '00100/01010/10001/00000/00000/00000/00000',
|
||
'|': '1/1/1/1/1/1/1',
|
||
'~': '00000/00000/01001/10110/00000/00000/00000',
|
||
};
|
||
|
||
export const styles = ['block', 'banner', 'slant', 'compact'];
|
||
|
||
export function normalizeText(text) {
|
||
return text.replace(/ı/g, 'i').normalize('NFD').replace(/[\u0300-\u036f]/g, '').toUpperCase();
|
||
}
|
||
|
||
export function render(text, style = 'block') {
|
||
if (!styles.includes(style)) throw new Error('Unknown lettering style');
|
||
if (text.length > 500) throw new Error('Text is too long');
|
||
return normalizeText(text).replace(/\r\n?/g, '\n').split('\n').map(line => {
|
||
const characters = [...line.replace(/\t/g, ' ')];
|
||
const glyphs = characters.map(char => (patterns[char] || patterns['?']).split('/'));
|
||
return Array.from({length: 7}, (_, row) => {
|
||
const pixels = glyphs.map((glyph, i) => [...glyph[row]].map(pixel => {
|
||
if (style === 'banner') return pixel === '1' ? characters[i] : ' ';
|
||
if (style === 'compact') return pixel === '1' ? '#' : ' ';
|
||
return pixel === '1' ? '##' : ' ';
|
||
}).join('')).join(style === 'compact' || style === 'banner' ? ' ' : ' ');
|
||
return (style === 'slant' ? ' '.repeat(6 - row) : '') + pixels.trimEnd();
|
||
}).join('\n');
|
||
}).join('\n\n');
|
||
}
|