JSFiddle - React, Tailwind, and code Playground

by Lazaro Contreras

HTML

<canvas id="canvas" width="500" height="300"></canvas>
    <div
      id="textBox"
      contenteditable="true"
      style="
        font-weight: bold;
        font-size: 20px;
        font-family: Helvetica;
        color: rgb(153, 0, 56);
      "
    >
      Este es un <em>texto</em> <span>de </span><span style="text-decoration-line: underline;background: rgb(255, 0, 0);">prueba 
      ajapagaqaya,a</span><span>, </span><span style="background: rgb(255, 243, 153);">con el cual la finalidad es llenar o recrear <em>texto</em> para ser probado o mostrado en <strong>sitios, paginas, documentos</strong> de muestra</span>, una vez explicado eso solo queda redactar sobre nada en absoluto manteniendo un <em>texto</em> enfocado en si mismo durante lo que se van recopilando las palabras u oraciones, siendo posible el incrementar la cantidad de <em>texto</em> disponible para ser mostrado.
    </div>

TypeScript

console.clear();
// function fromEntries(xs: any[]) {
//   return xs.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {});
// }
//
// function entries(xs: any) {
//   let ownProps = Object.keys(xs);
//   let i = ownProps.length;
//   let resArray = new Array(i);
//   while (i--) {
//     resArray[i] = [ownProps[i], xs[ownProps[i]]];
//   }
//
//   return resArray;
// }
//
// function getStyle(attrs: any) {
//   let obj = fromEntries(entries(attrs.style).filter(([k, v]) => v !== ""));
//   return obj;
// }

interface Style {
  fontSize?: number;
  fontStyle?: string;
  background?: string;
  fontColor?: string;
  fontWeight?: string;
  fontFamily?: string;
  textDecorationLine?: string;
}

function getStyle(attrs: any) {
  let obj: Style = {};
  if (attrs.style.fontSize !== "")
    obj.fontSize = +attrs.style.fontSize.replace(/[px]/g, "");
  if (attrs.style.fontStyle !== "") obj.fontStyle = attrs.style.fontStyle;
  if (attrs.style.backgroundColor !== "")
    obj.background = attrs.style.backgroundColor;
  if (attrs.style.color !== "") obj.fontColor = attrs.style.color;
  if (attrs.style.fontWeight !== "") obj.fontWeight = attrs.style.fontWeight;
  if (attrs.style.fontFamily !== "") obj.fontFamily = attrs.style.fontFamily;
  if (attrs.style.textDecorationLine !== "")
    obj.textDecorationLine = attrs.style.textDecorationLine;
  // fromEntries(entries(attrs.style).filter(([k, v]) => v !== ""));
  return obj;
}

class Box {
  x: number = 0;
  y: number = 0;
  width: number = 0;
  height: number = 0;
}

class StyleGroup {
  value: string = "";
  box: Box = new Box();
  measure?: TextMetrics;
  fontSize = 12;
  fontStyle = "";
  background = "none";
  fontColor = "#000000";
  fontWeight = "normal";
  fontFamily = "Verdana";
  textDecorationLine = null;
}

function getAllChildStyle(
  element: any,
  styleGroups: StyleGroup[] = [],
  style: any = []
): StyleGroup[] {
  if (element.hasChildNodes()) {
    let childLength = element.childNodes.length;
    style =...