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>

<table id="legend">
  <tbody>
  	<tr>
      <td data-h></td>
      <td data-v></td>
      <td data-ul></td>
      <td data-ur></td>
      <td data-dr></td>
      <td data-dl></td>
      <td data-ul-dr></td>
      <td data-ur-dl></td>
    </tr>
    <tr>
      <th>1</th>
      <th>2</th>
      <th>3</th>
      <th>4</th>
      <th>5</th>
      <th>6</th>
      <th>7</th>
      <th>8</th>
    </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>');
}

svg {
  border: 1px solid blue;
  stroke: blue;
  stroke-width: 25px;
  fill: none;
}

#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:...

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) {
  try {
    return JSON.parse(text);
  } catch (e) {}
  
  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)));