JSFiddle - React, Tailwind, and code Playground

by jrunning

HTML

<textarea rows="5" cols="15">
5 6 5 1 6
4 8 7 6 2
5 7 7 7 3
2 4 8 8 6
4 1 3 4 3
</textarea>

[[1,2,3],
[4,5,6],
[7,8,0]]
<table id="legend">
  <tbody>
  	<tr><th>0</th><td></td></tr>
    <tr><th>1</th><td data-h></td></tr>
    <tr><th>2</th><td data-v></td></tr>
    <tr><th>3</th><td data-ul></td></tr>
    <tr><th>4</th><td data-ur></td></tr>
    <tr><th>5</th><td data-dr></td></tr>
    <tr><th>6</th><td data-dl></td></tr>
    <tr><th>7</th><td data-ul-dr></td></tr>
    <tr><th>8</th><td data-ur-dl></td></tr>
  </tbody>
</table>

<table id="render">
  <tbody>
  </tbody>
</table>

CSS

* {
  font-family: sans-serif;
}

html {
  --curve-ul: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 0,50 a 50,50 0 0 0 50,-50" stroke="blue" fill="none" stroke-width="25"/></svg>');
  --curve-ur: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 50,0 a 50,50 0 0 0 50,50" stroke="blue" fill="none" stroke-width="25"/></svg>');
  --curve-dl: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 50,100 a 50,50 0 0 0 -50,-50" stroke="blue" fill="none" stroke-width="25"/></svg>');
  --curve-dr: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 100,50 a 50,50 0 0 0 -50,50" stroke="blue" fill="none" stroke-width="25"/></svg>');
  --curve-h: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 0,50 h 100" stroke="blue" fill="none" stroke-width="25"/></svg>');
  --curve-v: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100"><path d="M 50,0 v 100" stroke="blue" fill="none" stroke-width="25"/></svg>');
}

#render, #render tr, #render td {
  padding: 0;
  margin: 0;
  border-collapse: collapse;
}

#render td {
  margin: 0;
  padding: 0;
  border: 1px solid gray;
  width: 33px;
  height: 33px;
  background-size: cover;
}

[data-ul] { background-image: var(--curve-ul); }
[data-ur] { background-image: var(--curve-ur); }
[data-dl] { background-image: var(--curve-dl); }
[data-dr] { background-image: var(--curve-dr); }
[data-ul-dr] { background-image: var(--curve-ul), var(--curve-dr); }
[data-ur-dl] { background-image: var(--curve-ur), var(--curve-dl); }
[data-h] { background-image: var(--curve-h); }
[data-v] { background-image: var(--curve-v); }

textarea {
  font-family: monospace;
}

#legend {
	float: right;
}

#legend td {
  width: 20px;
  height: 20px;
  border: 1px...

JavaScript

const tileInts = [
  null, // 0 
  'h',  // 1 ─
  'v',  // 2 │
  'ul', // 3 ╯
  'ur', // 4 ╰
  'dr', // 5 ╭
  'dl', // 6 ╮
  'ulDr', // 7 ╯╭
  'urDl', // 8 ╮╰
];

function render(target, data) {
  while (target.rows.length > 0) {
    target.deleteRow(-1);
  }
  data.forEach(rowData => {
    const row = target.insertRow();
    rowData.forEach(value => {
      const cell = row.insertCell();
      if (value !== 0) {
        cell.dataset[tileInts[value]] = ''; 
      }
    });
  });
}

function parseText(text) {
  const rows = text.split('\n');
  const data = [];
  rows.forEach(row => {
  	const values = [];
  	const matchDigits = /\d/g;
  	let match;
  	while((match = matchDigits.exec(row))) {
  		values.push(parseInt(match[0]));
  	}
  	if (values.length  > 0) {
  		data.push(values);
  	}
  });
  return data;
}

const textarea = document.querySelector('textarea');
const renderTarget = document.getElementById('render');

render(renderTarget, parseText(textarea.value));

textarea.addEventListener('input',
  evt => render(renderTarget, parseText(evt.target.value)));