Last active
September 21, 2022 16:34
-
-
Save meylingtaing/5cdd8d0fe72674a71f94f813c4362969 to your computer and use it in GitHub Desktop.
my ascii art colorizer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" | |
content="width=device-width, initial-scale=1, shrink-to-fit=no"> | |
<link rel="stylesheet" href="main.css"> | |
<link rel="stylesheet" href="colors.css"> | |
<link rel="stylesheet" | |
href="https://fonts.googleapis.com/css?family=Oxygen+Mono"> | |
<title>Ascii Art Colorizer</title> | |
</head> | |
<body> | |
<div id="page-content"> | |
<style id="page-style"> | |
#ascii-art-grid { | |
font-size: 1.5em; | |
font-family: 'Oxygen Mono', monospace; | |
line-height: normal; | |
/* Disable highlight. Stackoverflow told me how to do this. */ | |
-moz-user-select: none; | |
-webkit-user-select: none; | |
-ms-user-select:none; | |
user-select:none; | |
-o-user-select:none; | |
} | |
#ascii-art-grid-div { | |
margin-right: 2em; | |
} | |
.char-color { | |
outline: 1px solid #444; | |
} | |
.char-color.selected { | |
outline: 1px solid #FFF; | |
} | |
.char-color:hover { | |
cursor: pointer; | |
} | |
#generated-html { | |
overflow-y: scroll; | |
} | |
</style> | |
<!-- This is for the new color that we add. It gets populated via javascript --> | |
<style id="extra-style"></style> | |
<div style="text-align:center"> | |
<h1> | |
<a href="/">projects</a> | <a href="/blog">blog</a> | |
</h1> | |
<p> | |
<hr> | |
</p> | |
</div> | |
<div style="text-align:center"> | |
<a href="/ascii/original">[original]</a> | |
<a href="/ascii/fanart">[fan art]</a> | |
<b>color-izer</b> | |
<a href="/ascii/howto">[how I display ascii art]</a> | |
</div><br> | |
The code for this is now in a <a href="https://gist.github.com/meylingtaing/5cdd8d0fe72674a71f94f813c4362969">gist</a>! | |
<br><br> | |
<span class="new-color-color">Add new color:</span> | |
<input type="text" placeholder="class name" id="color-class-name-input" /> | |
<input type="text" placeholder="css color" id="color-value-input" /> | |
<input type="button" value="+" id="add-color-link" /> | |
<br><br> | |
<div id="color-links"> | |
<a href="#" class="white change-color-link" data-color="white">white</a> | |
<a href="#" class="gray change-color-link" data-color="gray">gray</a> | |
<a href="#" class="lightgray change-color-link" data-color="lightgray">lightgray</a> | |
<a href="#" class="yellow change-color-link" data-color="yellow">yellow</a> | |
<a href="#" class="floyellow change-color-link" data-color="floyellow">floyellow</a> | |
<a href="#" class="yellorange change-color-link" data-color="yellorange">yellorange</a> | |
<a href="#" class="orange change-color-link" data-color="orange">orange</a> | |
<a href="#" class="gold change-color-link" data-color="gold">gold</a> | |
<a href="#" class="lightgold change-color-link" data-color="lightgold">lightgold</a> | |
<a href="#" class="pink change-color-link" data-color="pink">pink</a> | |
<a href="#" class="darkpink change-color-link" data-color="darkpink">darkpink</a> | |
<a href="#" class="redpink change-color-link" data-color="redpink">redpink</a> | |
<a href="#" class="orangepink change-color-link" data-color="orangepink">orangepink</a> | |
<a href="#" class="lightblue change-color-link" data-color="lightblue">lightblue</a> | |
<a href="#" class="lightblue2 change-color-link" data-color="lightblue2">lightblue2</a> | |
<a href="#" class="lightblue3 change-color-link" data-color="lightblue3">lightblue3</a> | |
<a href="#" class="mediumblue change-color-link" data-color="mediumblue">mediumblue</a> | |
<a href="#" class="darkblue change-color-link" data-color="darkblue">darkblue</a> | |
<a href="#" class="indigo change-color-link" data-color="indigo">indigo</a> | |
<a href="#" class="indigo2 change-color-link" data-color="indigo2">indigo2</a> | |
<a href="#" class="violet change-color-link" data-color="violet">violet</a> | |
<a href="#" class="purple change-color-link" data-color="purple">purple</a> | |
<a href="#" class="blue change-color-link" data-color="blue">blue</a> | |
<a href="#" class="red change-color-link" data-color="red">red</a> | |
<a href="#" class="red2 change-color-link" data-color="red2">red2</a> | |
<a href="#" class="darkred change-color-link" data-color="darkred">darkred</a> | |
<a href="#" class="tan change-color-link" data-color="tan">tan</a> | |
<a href="#" class="lighttan change-color-link" data-color="lighttan">lighttan</a> | |
<a href="#" class="brown change-color-link" data-color="brown">brown</a> | |
<a href="#" class="darkbrown change-color-link" data-color="darkbrown">darkbrown</a> | |
<a href="#" class="choco change-color-link" data-color="choco">choco</a> | |
<a href="#" class="darkchoco change-color-link" data-color="darkchoco">darkchoco</a> | |
<a href="#" class="green change-color-link" data-color="green">green</a> | |
<a href="#" class="darkgreen change-color-link" data-color="darkgreen">darkgreen</a> | |
<a href="#" class="darkergreen change-color-link" data-color="darkergreen">darkergreen</a> | |
<a href="#" class="limegreen change-color-link" data-color="limegreen">limegreen</a> | |
<a href="#" class="yellowgreen change-color-link" data-color="yellowgreen">yellowgreen</a> | |
<a href="#" class="black change-color-link" data-color="black">black</a> | |
<a href="#" class="ascii-art-caption change-color-link" data-color="ascii-art-caption">ascii‑art‑caption</a> | |
</div> | |
<br> | |
<button id="clear-selected">Clear Selected</button> | |
<div id="ascii-art-grid-div"> | |
<pre id="ascii-art-grid"></pre> | |
</div> | |
<div id="error-message" class="red"></div> | |
<textarea id="ascii-art-input" cols="80" rows="10"> | |
Paste ascii art here...</textarea> | |
<br> | |
<button id="submit-ascii-art">Start Color-izing</button> | |
<button id="generate-html">Generate HTML/CSS</button> | |
<br><br> | |
<textarea id="generated-html" cols="46" rows="10"> | |
Generated HTML will go here</textarea> | |
<textarea id="generated-css" cols="30" rows="10"> | |
Generated CSS will go here</textarea> | |
<br> | |
<button id="parse-html">Parse HTML</button> | |
<script> | |
const default_color = 'gray'; | |
// The colors are stored in a 2d array. Each element of the array is a | |
// class name that represents a certain color in the colors css file | |
var color_arr = []; | |
// Number of lines in the ascii art | |
var rows; | |
// Set to 'selecting' when we are selecting (highlighting, mousedown) // characters in the ascii art grid | |
var selecting = ""; | |
// Keep track of all the css color values so we can more easily generate | |
// them later | |
var css_color_values = {}; | |
css_color_values["white"] = "#FFF"; | |
css_color_values["gray"] = "#999"; | |
css_color_values["lightgray"] = "#CCC"; | |
css_color_values["yellow"] = "yellow"; | |
css_color_values["floyellow"] = "#fdf001"; | |
css_color_values["yellorange"] = "#FD0"; | |
css_color_values["orange"] = "orange"; | |
css_color_values["gold"] = "#FF6"; | |
css_color_values["lightgold"] = "#FF8"; | |
css_color_values["pink"] = "lightpink"; | |
css_color_values["darkpink"] = "#E89"; | |
css_color_values["redpink"] = "#F86"; | |
css_color_values["orangepink"] = "#FB7"; | |
css_color_values["lightblue"] = "lightblue"; | |
css_color_values["lightblue2"] = "#8CF"; | |
css_color_values["lightblue3"] = "#8AF"; | |
css_color_values["mediumblue"] = "#78F"; | |
css_color_values["darkblue"] = "#545092"; | |
css_color_values["indigo"] = "#97F"; | |
css_color_values["indigo2"] = "#A7C"; | |
css_color_values["violet"] = "#E5F"; | |
css_color_values["purple"] = "#C3C"; | |
css_color_values["blue"] = "#37E"; | |
css_color_values["red"] = "red"; | |
css_color_values["red2"] = "#E34"; | |
css_color_values["darkred"] = "#C33"; | |
css_color_values["tan"] = "#FC8"; | |
css_color_values["lighttan"] = "#FD9"; | |
css_color_values["brown"] = "#D50"; | |
css_color_values["darkbrown"] = "#A30"; | |
css_color_values["choco"] = "#B85"; | |
css_color_values["darkchoco"] = "#963"; | |
css_color_values["green"] = "#3D5"; | |
css_color_values["darkgreen"] = "#3A5"; | |
css_color_values["darkergreen"] = "#171"; | |
css_color_values["limegreen"] = "#0F0"; | |
css_color_values["yellowgreen"] = "#CF7"; | |
css_color_values["black"] = "#000"; | |
function get_ascii_art_input() { | |
// Get the input string | |
var ascii_art = document.getElementById("ascii-art-input").value; | |
rows = ascii_art.split(/\n/); | |
// Get the size of the input | |
var num_rows = rows.length; | |
var num_cols = Math.max(...rows.map(x => x.length)); | |
// Create the colors array -- keep any colors we already modified | |
for (let i = 0; i < num_rows; i++) { | |
let new_color_arr = []; | |
for (let j = 0; j < rows[i].length; j++) { | |
if (typeof color_arr[i] != 'undefined' && | |
typeof color_arr[i][j] != 'undefined') | |
{ | |
new_color_arr[j] = color_arr[i][j]; | |
} | |
else { | |
new_color_arr[j] = default_color; | |
} | |
} | |
color_arr[i] = new_color_arr; | |
} | |
// Display it | |
display_grid(); | |
} | |
document.addEventListener('mouseup', stop_selecting); | |
function display_grid() { | |
var grid_html = ''; | |
rows.forEach(function (row, index) { | |
for (let i = 0; i < row.length; i++) { | |
let color = color_arr[index][i]; | |
grid_html = grid_html.concat( | |
'<span class="', color, ' char-color"', | |
'data-col="', i, '"', | |
' data-row="', index, '" data-color="', color, '">', | |
row.charAt(i), | |
'</span>' | |
); | |
} | |
grid_html = grid_html.concat("\n"); | |
}); | |
document.getElementById("ascii-art-grid").innerHTML = grid_html; | |
var char_elts = document.getElementsByClassName("char-color"); | |
for (let i = 0; i < char_elts.length; i++) { | |
char_elts[i].addEventListener('mousedown', start_selecting); | |
char_elts[i].addEventListener('mousemove', continue_selecting); | |
} | |
} | |
function start_selecting(e) { | |
var classes = this.className; | |
if (classes.match(/selected/)) { | |
selecting = "deselecting"; | |
this.classList.remove("selected"); | |
} | |
else { | |
selecting = "selecting"; | |
this.classList.add("selected"); | |
} | |
} | |
function continue_selecting(e) { | |
if (selecting == "selecting") { | |
this.classList.add("selected"); | |
} | |
else if (selecting == "deselecting"){ | |
this.classList.remove("selected"); | |
} | |
} | |
function stop_selecting(e) { | |
selecting = ""; | |
} | |
function clear_selected() { | |
var selected_elts = document.getElementsByClassName('selected'); | |
while (selected_elts.length > 0) { | |
selected_elts[0].classList.remove('selected'); | |
} | |
} | |
function change_char_color(e) { | |
// What color was selected? | |
var color_class = this.getAttribute('data-color'); | |
// Get all selected elements and change their color | |
var selected_elts = document.getElementsByClassName('selected'); | |
for (let i = 0; i < selected_elts.length; i++) { | |
let old_color = selected_elts[i].getAttribute('data-color'); | |
selected_elts[i].setAttribute('data-color', color_class); | |
selected_elts[i].classList.remove(old_color); | |
selected_elts[i].classList.add(color_class); | |
let row = selected_elts[i].getAttribute('data-row'); | |
let col = selected_elts[i].getAttribute('data-col'); | |
color_arr[row][col] = color_class; | |
} | |
return false; | |
} | |
function generate_html() { | |
// We run into issues if the first span consists of only spaces, so | |
// let's figure out the first color that's actually used and change | |
// the first set of spaces to that color | |
var first_char_color = default_color; | |
get_first_char_color: | |
for (let i = 0; i < color_arr.length; i++) { | |
for (let j = 0; j < color_arr[i].length; j++) { | |
let char = rows[i].charAt(j); | |
if (char != ' ') { | |
first_char_color = color_arr[i][j]; | |
break get_first_char_color; | |
} | |
} | |
} | |
// Go through the ascii art grid | |
var curr_color = first_char_color; | |
var html = '<span class="' + curr_color + '">'; | |
var colors_used = {}; | |
colors_used[curr_color] = 1; | |
var css = `.${curr_color} { color: ${css_color_values[curr_color]} }\n`; | |
for (let i = 0; i < color_arr.length; i++) { | |
for (let j = 0; j < color_arr[i].length; j++) { | |
// Check if the color has changed | |
let char = rows[i].charAt(j); | |
if ((char != ' ') && (color_arr[i][j] != curr_color)) { | |
curr_color = color_arr[i][j]; | |
html = html.concat( | |
'</span>', '<span class="', curr_color, '">'); | |
// Add it to the css if it's not there yet | |
if (colors_used[curr_color] != 1) { | |
css = css.concat(`.${curr_color} { color: ${css_color_values[curr_color]} }\n`); | |
colors_used[curr_color] = 1; | |
} | |
} | |
// Add the next letter | |
html = html.concat(rows[i].charAt(j)); | |
} | |
html = html.concat("\n"); | |
} | |
html = html.concat("</span>"); | |
document.getElementById('generated-html').value = html; | |
document.getElementById('generated-css').value = css; | |
} | |
function parse_html() { | |
display_error(''); | |
// Get the html input | |
var html = document.getElementById('generated-html').value; | |
var pre_elt = document.createElement('pre'); | |
// Error check?! | |
pre_elt.innerHTML = html; | |
// Walk through each span and fill out the color_arr | |
var nodes = pre_elt.childNodes; | |
var new_color_arr = []; | |
var i = 0; | |
var j = 0; | |
new_color_arr[0] = []; | |
for (node of nodes) { | |
let color; | |
if (node.nodeType != Node.ELEMENT_NODE || node.tagName != 'SPAN') { | |
display_error('Invalid input - not all nodes are <span>'); | |
} | |
else { | |
// Make sure it's just plain text inside the span | |
if (node.childNodes.length != 1) { | |
display_error( | |
'Invalid input - <span> has multiple nodes', | |
); | |
console.log(node.childNodes[1].nodeType); | |
console.log(node.childNodes[1]); | |
} | |
else if (node.childNodes[0].nodeType != Node.TEXT_NODE) { | |
display_error( | |
'Invalid input - <span> has something other than text', | |
); | |
console.log(node.childNodes[0].nodeType); | |
console.log(node.childNodes[0]); | |
} | |
color = node.getAttribute('class'); | |
let text = node.textContent; | |
for (let n = 0; n < text.length; n++) { | |
if (text.charAt(n) == '\n') { | |
i++; | |
j=0; | |
new_color_arr[i] = []; | |
} | |
else { | |
new_color_arr[i][j] = color; | |
j++; | |
} | |
} | |
} | |
} | |
color_arr = new_color_arr; | |
rows = pre_elt.textContent.split(/\n/); | |
display_grid(); | |
} | |
function change_new_color_color (e) { | |
if (e.keyCode === 13) { // Enter | |
var value = document.getElementById("color-value-input").value; | |
var style = document.getElementById("extra-style"); | |
style.innerHTML = `.new-color-color { color: ${value} }`; | |
} | |
} | |
function add_color_link() { | |
// TODO: Actually check and see if we were given valid inputs? | |
var name = document.getElementById("color-class-name-input").value; | |
var value = document.getElementById("color-value-input").value; | |
// First, add the css to this page | |
var style = document.getElementById("page-style"); | |
style.append(`.${name} { color: ${value} }\n`); | |
css_color_values[name] = value; | |
// And then add a link for it | |
var color_links_div = document.getElementById("color-links"); | |
var new_link = document.createElement('a'); | |
new_link.setAttribute('href', '#'); | |
new_link.setAttribute('class', name + " change-color-link"); | |
new_link.setAttribute('data-color', name); | |
new_link.innerHTML = name; | |
color_links_div.append(new_link); | |
color_links_div.append("\n"); | |
new_link.onclick = change_char_color; | |
// Clear out all the inputs (and the color preview) | |
document.getElementById("color-class-name-input").value = ''; | |
document.getElementById("color-value-input").value = ''; | |
document.getElementById("extra-style").innerHTML = ''; | |
} | |
function display_error(err) { | |
document.getElementById('error-message').textContent = err; | |
} | |
document.getElementById("submit-ascii-art").onclick = get_ascii_art_input; | |
document.getElementById("generate-html").onclick = generate_html; | |
document.getElementById("clear-selected").onclick = clear_selected; | |
document.getElementById("parse-html").onclick = parse_html; | |
document.getElementById("add-color-link").onclick = add_color_link; | |
document.getElementById("color-value-input").onkeyup = change_new_color_color; | |
var color_links = document.getElementsByClassName("change-color-link"); | |
for (let i = 0; i < color_links.length; i++) | |
color_links[i].onclick = change_char_color; | |
</script> | |
</div> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.white { color: #FFF } | |
.gray { color: #999 } | |
.lightgray { color: #CCC } | |
.yellow { color: yellow } | |
.floyellow { color: #fdf001 } | |
.yellorange { color: #FD0 } | |
.orange { color: orange } | |
.gold { color: #FF6 } | |
.lightgold { color: #FF8 } | |
.pink { color: lightpink } | |
.darkpink { color: #E89 } | |
.redpink { color: #F86 } | |
.orangepink { color: #FB7 } | |
.lightblue { color: lightblue } | |
.lightblue2 { color: #8CF } | |
.lightblue3 { color: #8AF } | |
.mediumblue { color: #78F } | |
.darkblue { color: #545092 } | |
.indigo { color: #97F } | |
.indigo2 { color: #A7C } | |
.violet { color: #E5F } | |
.purple { color: #C3C } | |
.blue { color: #37E } | |
.red { color: red } | |
.red2 { color: #E34 } | |
.darkred { color: #C33 } | |
.tan { color: #FC8 } | |
.lighttan { color: #FD9 } | |
.brown { color: #D50 } | |
.darkbrown { color: #A30 } | |
.choco { color: #B85 } | |
.darkchoco { color: #963 } | |
.green { color: #3D5 } | |
.darkgreen { color: #3A5 } | |
.darkergreen { color: #171 } | |
.limegreen { color: #0F0 } | |
.yellowgreen { color: #CF7 } | |
.black { color: #000 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
background-color: #333; | |
color: #CCC; | |
font-family: 'Oxygen Mono', monospace; | |
width: 90%; | |
margin: auto; | |
line-height: 1.5; | |
} | |
a { | |
color: #8DF; | |
text-decoration: underline; | |
} | |
a.footnote { | |
vertical-align: super; | |
font-size: smaller; | |
text-decoration: none; | |
color: #FF6; | |
} | |
a.reversefootnote { | |
text-decoration: none; | |
} | |
.continue-reading-link { | |
text-align: right; | |
} | |
/* Blog stuff */ | |
h2, h2 > a { | |
color: #EEE; | |
} | |
h3 { | |
color: #DDD; | |
} | |
h4 { | |
color: #999; | |
font-weight: normal; | |
} | |
hr { | |
border: 0; | |
border-top: 3px dashed #37E; | |
} | |
blockquote, blockquote strong { | |
color: #B9F; | |
} | |
table, tr, td, th { | |
border: 1px solid #999; | |
border-collapse: collapse; | |
padding: 3px; | |
} | |
table { | |
margin-bottom: 1em; | |
margin-left: auto; | |
margin-right: auto; | |
text-align: center; | |
} | |
strong { | |
color: #EEE; | |
} | |
p code { | |
color: #333; | |
background-color: #CCC; | |
font-weight: bold; | |
padding: .25em; | |
} | |
div.code { | |
color: #000; | |
background-color: #CCC; | |
padding: .25em; | |
padding-left: 1em; | |
overflow: scroll; | |
} | |
textarea { | |
background-color: #CCC; | |
font: monospace; | |
} | |
.tags a { | |
color: #999; | |
font-size: .75em; | |
} | |
@media (min-width: 55em) { | |
body { | |
width: 50em; | |
} | |
} | |
@media (max-width: 35em) { | |
.ascii-art { | |
font-size: .8em; | |
} | |
} | |
img { | |
max-width: 100%; | |
/* max-height: 90vh */; | |
margin: auto; | |
display: block; | |
} | |
#page-content { margin-top: 1em } | |
.ascii-art { | |
font-weight: bold; | |
line-height: 1.35; | |
} | |
.ascii-art i, .ascii-art-caption { | |
font-weight: normal; | |
color: #999; | |
font-style: italic; | |
} | |
.underline { text-decoration: underline } | |
.bold { font-weight: bold } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment