Compare commits
	
		
			3 Commits
		
	
	
		
			cd6deac0b4
			...
			1888f794b1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1888f794b1 | |||
| ad22fd715e | |||
| c01ebee0ae | 
							
								
								
									
										28
									
								
								ime.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ime.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | <!DOCTYPE html> | ||||||
|  | <html> | ||||||
|  |     <head> | ||||||
|  |         <meta charset="utf-8"> | ||||||
|  |         <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||||||
|  |         <title>ime test</title> | ||||||
|  |         <meta name="description" content=""> | ||||||
|  |         <meta name="viewport" content="width=device-width, initial-scale=1"> | ||||||
|  |         <style> | ||||||
|  |             @font-face { | ||||||
|  |                 font-family: "heonian"; | ||||||
|  |                 src: url('HeonianAlone.otf'); | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             textarea { | ||||||
|  |                 font-family: "heonian"; | ||||||
|  |                 font-size: 32px; | ||||||
|  |             } | ||||||
|  |         </style> | ||||||
|  |     </head> | ||||||
|  |     <body> | ||||||
|  |         <p>type in ime, wow!!!!!!!!!!!</p> | ||||||
|  |         <textarea type="text" class="ime"> | ||||||
|  |         </textarea> | ||||||
|  |          | ||||||
|  |         <script src="./ime.js" async defer></script> | ||||||
|  |     </body> | ||||||
|  | </html> | ||||||
							
								
								
									
										397
									
								
								ime.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										397
									
								
								ime.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,397 @@ | |||||||
|  | let input = []; | ||||||
|  | 
 | ||||||
|  | let currentWord = []; | ||||||
|  | 
 | ||||||
|  | let selected = -1; | ||||||
|  | 
 | ||||||
|  | window.onload = () => { | ||||||
|  |     document.querySelectorAll(".ime").forEach(input => { | ||||||
|  |         input.addEventListener("keydown", (key) => { | ||||||
|  |             imeDown(key, input); | ||||||
|  |         }); | ||||||
|  |         input.addEventListener("mousedown", (e) => { | ||||||
|  |             e.preventDefault(); | ||||||
|  |             input.focus(); | ||||||
|  |             imeUpdate(input); | ||||||
|  |         }) | ||||||
|  |     }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeDown(keyEvent, inputField) { | ||||||
|  |     keyEvent.preventDefault(); | ||||||
|  |     switch (keyEvent.key) { | ||||||
|  |         case "Backspace": | ||||||
|  |             if (selected == -1) { | ||||||
|  |                 if (currentWord.join("") == "") { | ||||||
|  |                     currentWord = input.pop() || []; | ||||||
|  |                 } else { | ||||||
|  |                     imeRestore(currentWord); | ||||||
|  |                     // currentWord.pop();
 | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 imeRestore(input[selected]); | ||||||
|  |                 // input[selected].pop();
 | ||||||
|  |                 if (input[selected].join("") == "") { | ||||||
|  |                     input.splice(selected,1); | ||||||
|  |                     imeMove("left"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case "Enter": | ||||||
|  |             if (selected == -1) { | ||||||
|  |                 if (currentWord.join() == "") { //blame js :)
 | ||||||
|  |                     let s = document.createElement("p"); | ||||||
|  |                     s.innerText = input.join(""); | ||||||
|  |                     document.body.appendChild(s); | ||||||
|  |                     input = []; | ||||||
|  |                     selected = -1; | ||||||
|  |                 } else { | ||||||
|  |                     input.push(currentWord); | ||||||
|  |                     currentWord = []; | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 if (selected+1 >= input.length) { | ||||||
|  |                     selected = -1; | ||||||
|  |                 } else { | ||||||
|  |                     selected += 1; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             imeReset(); | ||||||
|  |             break; | ||||||
|  |         case "Space": | ||||||
|  |             //adds a '
 | ||||||
|  |             break; | ||||||
|  |         case "ArrowLeft": | ||||||
|  |             imeMove("left"); | ||||||
|  |             break; | ||||||
|  |         case "ArrowRight": | ||||||
|  |             imeMove("right"); | ||||||
|  |             break; | ||||||
|  |         case "ArrowDown": | ||||||
|  |             imeMove("start"); | ||||||
|  |             break; | ||||||
|  |         case "ArrowUp": | ||||||
|  |             imeMove("end"); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             imeInput(keyEvent.key); | ||||||
|  |             if (selected == -1) { | ||||||
|  |                 currentWord = inputFull; | ||||||
|  |             } else { | ||||||
|  |                 input[selected] = inputFull; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |     imeUpdate(inputField); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeUpdate(inputField) { | ||||||
|  |     let renderText = ""; | ||||||
|  |     input.forEach((w) => { | ||||||
|  |         renderText += w.join(""); | ||||||
|  |     }) | ||||||
|  |     inputField.value = renderText + currentWord.join(""); | ||||||
|  |     if (selected == -1) { | ||||||
|  |         inputField.setSelectionRange(renderText.length, renderText.length+currentWord.join("").length); | ||||||
|  |     } else { | ||||||
|  |         from = 0; | ||||||
|  |         for (let x = 0; x < selected; x++) { | ||||||
|  |             from += input[x].join("").length; | ||||||
|  |         } | ||||||
|  |         to = from+input[selected].join("").length; | ||||||
|  |         inputField.setSelectionRange(from, to); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function clamp(min, max, value) { | ||||||
|  |     return Math.max(min, Math.min(max, value)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeMove(direction) { | ||||||
|  |     let d = 1; | ||||||
|  |     if (currentWord.join("") != "") { | ||||||
|  |         input.push(currentWord); | ||||||
|  |         currentWord = []; | ||||||
|  |         d = 2; | ||||||
|  |     } | ||||||
|  |     switch (direction) { | ||||||
|  |         case "start": | ||||||
|  |             selected = 0; | ||||||
|  |             break; | ||||||
|  |         case "end": | ||||||
|  |             selected = -1; | ||||||
|  |             break; | ||||||
|  |         case "left": | ||||||
|  |             if (selected == -1) selected = input.length; | ||||||
|  |             selected -= 1 * d; | ||||||
|  |             if (selected != -1) { | ||||||
|  |                 selected = clamp(0,input.length,selected); | ||||||
|  |                 //is there even a point in clamping it here,,,,
 | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case "right": | ||||||
|  |             selected += 1 * d; | ||||||
|  |             selected = clamp(0,input.length,selected); | ||||||
|  |             //tbh same here, like.
 | ||||||
|  |             //oh well   ig ???/
 | ||||||
|  |             if (selected == input.length) { | ||||||
|  |                 selected = -1; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  |     imeReset(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let inputState = 0; //STARTING, COMPOSTING, TRAILING, Fucking Nothing, ...cleanup
 | ||||||
|  | let stateState = 0; //depends on the state
 | ||||||
|  | let inputFull = []; | ||||||
|  | let inputCurrent = ""; | ||||||
|  | 
 | ||||||
|  | let hVowels = { //standalone, composing, trailing
 | ||||||
|  |     "a": ["0", "5", "A"], | ||||||
|  |     "e": ["1", "6", "B"], | ||||||
|  |     "i": ["2", "7", "C"], | ||||||
|  |     "o": ["3", "8", "D"], | ||||||
|  |     "u": ["4", "9", "E"] | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | let hConsonants = { //0 = standalone, 1 = composing, 2-6 = vowels
 | ||||||
|  |     "g": "01", | ||||||
|  |     "s": "02", | ||||||
|  |     "r": "03", | ||||||
|  |     "n": "04", | ||||||
|  |     "c": "05", | ||||||
|  |     "m": "06", | ||||||
|  |     "j": "07", | ||||||
|  |     "f": "08", | ||||||
|  |     "t": "09", | ||||||
|  |     "k": "0A", | ||||||
|  |     "w": "0B", | ||||||
|  |     "l": "0C", | ||||||
|  |     "p": "0D", | ||||||
|  |     "b": "0E", | ||||||
|  |     "d": "0F", | ||||||
|  |     "h": "10", | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | function getUnicodeVowel(vowel, sot) { | ||||||
|  |     if (sot == "standalone") sot = 0; | ||||||
|  |     if (sot == "composing") sot = 1; | ||||||
|  |     if (sot == "trailing") sot = 2; | ||||||
|  |     return String.fromCharCode(parseInt("E00" + hVowels[vowel][sot], 16)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function getUnicodeConsonant(consonant, scv) { | ||||||
|  |     if (scv == "standalone") {scv = 0;} | ||||||
|  |     else if (scv == "trailing") {scv = 1;} | ||||||
|  |     else {scv = Number(hVowels[scv][0])+2} | ||||||
|  |     return String.fromCharCode(parseInt("E" + hConsonants[consonant] + "" + scv, 16)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function inverse(obj){ | ||||||
|  |     var retobj = {}; | ||||||
|  |     for(var key in obj){ | ||||||
|  |         retobj[obj[key]] = key; | ||||||
|  |     } | ||||||
|  |     return retobj; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | let hVowelsK = Object.keys(hVowels) | ||||||
|  | let hConsonantsK = Object.keys(hConsonants); | ||||||
|  | let hConsonantsR = inverse(hConsonants); | ||||||
|  | 
 | ||||||
|  | function debugInput(key) { | ||||||
|  |     console.log("pre "+key+": inputstate - "+inputState +", statestate - "+ stateState); | ||||||
|  |     console.log("inputfull: " + inputFull.join(" ") + ", inputcurrent:" + inputCurrent); | ||||||
|  |     imeInput(key); | ||||||
|  |     console.log("post "+key+": inputstate - "+inputState +", statestate - "+ stateState); | ||||||
|  |     console.log("inputfull: " + inputFull.join(" ") + ", inputcurrent:" + inputCurrent); | ||||||
|  |     console.log("------------------------------") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeReset() { | ||||||
|  |     stateState = 0; | ||||||
|  |     inputState = 0; | ||||||
|  |     inputFull = []; | ||||||
|  |     inputCurrent = ""; | ||||||
|  |     if (selected == -1) { | ||||||
|  |         currentWord = []; | ||||||
|  |     } else { | ||||||
|  |         input[selected] = []; | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeInfo(decHex) { | ||||||
|  |     try { | ||||||
|  |         let hex = decHex.codePointAt(0).toString(16); | ||||||
|  |         hex[1] = parseInt(hex[1], 16); | ||||||
|  |         hex[2] = parseInt(hex[2], 16); | ||||||
|  |         hex[3] = parseInt(hex[3], 16); | ||||||
|  |         let ka = (hex[1] == 0 && hex[2] == 0) ? "a" : "k"; | ||||||
|  |         if (ka == "k") { | ||||||
|  |             if (hex[3] == 1) { | ||||||
|  |                 //trailing
 | ||||||
|  |                 return([ka,"trailing"]) | ||||||
|  |             } else if (hex[3] == 0) { | ||||||
|  |                 //standalone
 | ||||||
|  |                 //full reset / no restore necessary
 | ||||||
|  |                 return([ka,"standalone"]) | ||||||
|  |             } else { | ||||||
|  |                 //composing
 | ||||||
|  |                 return([ka,"composing"]) | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             if (hex[3] <= 8) { | ||||||
|  |                 //standalone
 | ||||||
|  |                 return([ka,"standalone"]) | ||||||
|  |             } else { | ||||||
|  |                 //trailing
 | ||||||
|  |                 return([ka,"trailing"]) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } catch { | ||||||
|  |         return ""; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeChange(inState, stState, pop, array) { | ||||||
|  |     inputState = inState; | ||||||
|  |     stateState = stState; | ||||||
|  |     if (pop) { | ||||||
|  |         array.pop(); | ||||||
|  |     } | ||||||
|  |     inputFull = array; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeRestore(array) { | ||||||
|  |     let hex = array[array.length-1].codePointAt(0).toString(16); | ||||||
|  |     hex[1] = parseInt(hex[1], 16); | ||||||
|  |     hex[2] = parseInt(hex[2], 16); | ||||||
|  |     hex[3] = parseInt(hex[3], 16); | ||||||
|  |     let previous = imeInfo(array[array.length-2])[1]; | ||||||
|  |     let ka = (hex[1] == 0 && hex[2] == 0) ? "a" : "k"; | ||||||
|  |     if (ka == "k") { | ||||||
|  |         if (hex[3] == 1) { | ||||||
|  |             //trailing
 | ||||||
|  |             if (previous == "trailing") { | ||||||
|  |                 //trailing twice
 | ||||||
|  |                 console.log("2.1"); | ||||||
|  |                 imeChange(2,1,true,array); | ||||||
|  |             } else { | ||||||
|  |                 //trailing once
 | ||||||
|  |                 console.log("2.0"); | ||||||
|  |                 imeChange(2,0,true,array); | ||||||
|  |             } | ||||||
|  |         } else if (hex[3] == 0) { | ||||||
|  |             console.log(array.length); | ||||||
|  |             if (array.length != 1) { | ||||||
|  |                 //0.1, i think?
 | ||||||
|  |                 console.log("0.1"); | ||||||
|  |                 imeChange(0,1,true,array); | ||||||
|  |             } else { | ||||||
|  |                 //standalone
 | ||||||
|  |                 console.log("full reset"); | ||||||
|  |                 imeReset(); | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             //composing
 | ||||||
|  |             if (previous == "standalone") { | ||||||
|  |                 //0.1??
 | ||||||
|  |                 //recreate?? last digit???
 | ||||||
|  |                 let c = hConsonantsR[[hex[1], hex[2]].join("").toUpperCase()]; | ||||||
|  |                 array.pop(); | ||||||
|  |                 array.push(getUnicodeConsonant(c, "standalone")); | ||||||
|  |                 inputCurrent = c; | ||||||
|  | 
 | ||||||
|  |                 console.log("0.1"); | ||||||
|  |                 imeChange(0,1,false,array); | ||||||
|  |             } else { | ||||||
|  |                 //0.2???? fuck it lets try and find out ig
 | ||||||
|  |                 //recreate?? last digit???
 | ||||||
|  |                 let c = hConsonantsR[[hex[1], hex[2]].join("").toUpperCase()]; | ||||||
|  |                 array.pop(); | ||||||
|  |                 array.push(getUnicodeConsonant(c, "standalone")); | ||||||
|  |                 inputCurrent = c; | ||||||
|  | 
 | ||||||
|  |                 console.log("0.2"); | ||||||
|  |                 imeChange(0,2,false,array); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } else { | ||||||
|  |         if (hex[3] <= 8) { | ||||||
|  |             //standalone
 | ||||||
|  |             console.log("full reset"); | ||||||
|  |             imeReset(); | ||||||
|  |         } else { | ||||||
|  |             //trailing
 | ||||||
|  |             if (previous == "trailing") { | ||||||
|  |                 //trailing twice
 | ||||||
|  |                 console.log("2.1"); | ||||||
|  |                 imeChange(2,1,true,array); | ||||||
|  |             } else { | ||||||
|  |                 //trailing once
 | ||||||
|  |                 console.log("2.0"); | ||||||
|  |                 imeChange(2,0,true,array); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function imeInput(key) { | ||||||
|  |     key = key.toLowerCase(); | ||||||
|  |     if (!hConsonantsK.includes(key) && !hVowelsK.includes(key)) return; | ||||||
|  |     switch (inputState) { | ||||||
|  |         case 0: //starting
 | ||||||
|  |             if (stateState == 0) { | ||||||
|  |                 if (hVowelsK.includes(key)) { | ||||||
|  |                     inputFull.push(getUnicodeVowel(key, "standalone")); | ||||||
|  |                     inputState = 2; | ||||||
|  |                 } else { | ||||||
|  |                     inputFull.push(getUnicodeConsonant(key, "standalone")); | ||||||
|  |                     stateState = 1; | ||||||
|  |                     inputCurrent = key; | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             } else if (stateState == 1) { | ||||||
|  |                 if (hVowelsK.includes(key)) { | ||||||
|  |                     inputState = 1; | ||||||
|  |                     stateState = 0; | ||||||
|  |                 } else { | ||||||
|  |                     inputFull.push(getUnicodeConsonant(key, "trailing")); | ||||||
|  |                     inputCurrent = key; | ||||||
|  |                     stateState = 2; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } else if (stateState == 2) { | ||||||
|  |                 if (hVowelsK.includes(key)) { | ||||||
|  |                     inputState = 1; | ||||||
|  |                     stateState = 0; | ||||||
|  |                 } else break; | ||||||
|  |             } | ||||||
|  |         case 1: //composing
 | ||||||
|  |             if (hVowelsK.includes(key)) { | ||||||
|  |                 inputState = 2; | ||||||
|  |                 inputFull.pop(); | ||||||
|  |                 inputFull.push(getUnicodeConsonant(inputCurrent, key)); | ||||||
|  |                 inputCurrent = ""; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case 2: //trailing
 | ||||||
|  |             if (hVowelsK.includes(key)) { | ||||||
|  |                 inputFull.push(getUnicodeVowel(key, "trailing")); | ||||||
|  |                 stateState += 1; | ||||||
|  |             } else { | ||||||
|  |                 inputFull.push(getUnicodeConsonant(key, "trailing")); | ||||||
|  |                 stateState += 1; | ||||||
|  |             } | ||||||
|  |             if (stateState == 2) { | ||||||
|  |                 stateState = 0; | ||||||
|  |                 inputState = 3; | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         case 3: //go to next word uwu
 | ||||||
|  |             //todo :)
 | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										56
									
								
								ime.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								ime.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | |||||||
|  | 
 | ||||||
|  | Description of IME: | ||||||
|  | 
 | ||||||
|  | 5 states: | ||||||
|  |     - STARTING | ||||||
|  |     - COMPOSING | ||||||
|  |     - TRAILING | ||||||
|  | 
 | ||||||
|  |     Nomenclature:    [Whole] / [Up|Down] | ||||||
|  | 
 | ||||||
|  |     At any times, enter can be pressed to finish the input process. | ||||||
|  |     Pressing enter with input process already finished will send the message. | ||||||
|  | 
 | ||||||
|  | STATE 1 - STARTING | ||||||
|  |     Any first letter input is displayed as non-composing non-trailing symbol. | ||||||
|  |     The big standalone variant. | ||||||
|  | 
 | ||||||
|  |     Consonant    [K] | ||||||
|  |     Vowel         [A] | ||||||
|  | 
 | ||||||
|  |     If CONSONANT was inputted: | ||||||
|  |         - Move to COMPOSING if next a VOWEL is inputted. | ||||||
|  |         - Repeat this step if not, but adding the input as a trailing letter instead (uppercase). This can only happen once. | ||||||
|  |     If VOWEL was inputted, move to TRAILING. | ||||||
|  | 
 | ||||||
|  | STATE 2 - COMPOSING | ||||||
|  | 
 | ||||||
|  |     Only vowels are  inputted. It is transcribed to heonian as a downside letter. | ||||||
|  | 
 | ||||||
|  |     Vowel          -> [K|A] | ||||||
|  | 
 | ||||||
|  |     Move to TRAILING. | ||||||
|  | 
 | ||||||
|  | STATE 3 - TRAILING. (UP TO 2 TIMES) | ||||||
|  |     Any letter input is displayed as a trailing symbol. | ||||||
|  |      Aka uppercase. | ||||||
|  | 
 | ||||||
|  |     1-3            -> [A][N| ] | ||||||
|  |     1-3-3        -> [A][N| ][N| ] | ||||||
|  |     1-2-3         -> [K|A][N| ] | ||||||
|  |     1-2-3-3         -> [K|A][N| ][N| ] | ||||||
|  |     1-1-2-3         -> [K][K|A][N| ] | ||||||
|  |     1-1-2-3-3     -> [K][K|A][N| ][N| ] | ||||||
|  | 
 | ||||||
|  |     This process can be repeated up to two times. | ||||||
|  | 
 | ||||||
|  | https://cronut.cafe/~lustlion/myrheon/test/ | ||||||
|  | 0xE -> Heonian Letter | ||||||
|  | next two digits: Vowels / What Consonant | ||||||
|  | last digit: Standalone / Trailing / Composing | ||||||
|  | 
 | ||||||
|  | simplified: | ||||||
|  | 1. First letter inputted is standalone except if composing. | ||||||
|  | 2. There can only be one composing per syllable, if it manages to go composing it goes to trailing. | ||||||
|  | 3. You can input up to two letters before either composing or ending the syllable. | ||||||
|  | 4. You can have 0, 1 or 2 trailing letters. | ||||||
							
								
								
									
										6
									
								
								main.js
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								main.js
									
									
									
									
									
								
							| @ -1,8 +1,3 @@ | |||||||
| //since this _entire thing_ will be generated,
 |  | ||||||
| //you could "theoretically" (you definitive can)
 |  | ||||||
| //just sorta. skip the whole "scan all words" bit,
 |  | ||||||
| //which is why that's in a separate function
 |  | ||||||
| 
 |  | ||||||
| let words = {} | let words = {} | ||||||
| 
 | 
 | ||||||
| let currentFont = "r"; | let currentFont = "r"; | ||||||
| @ -116,7 +111,6 @@ function init() { | |||||||
|             document.querySelector("#popup-container").style.pointerEvents = "none"; |             document.querySelector("#popup-container").style.pointerEvents = "none"; | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|     // above are commented out until wordlist is added~
 |  | ||||||
|     document.querySelector("#font-button").addEventListener("click", () => {fontButton();}); |     document.querySelector("#font-button").addEventListener("click", () => {fontButton();}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user