javascriptgoogle-apps-scriptunicodeconverters

Styled Unicode Characters to Plain Text


I have this code that converts plain text to Unicode styled characters:

function convertText(text, style) {

  // 1. Convert the text to the bold type with the unicode.
  const conv = {
    c: function(text, obj) {return text.replace(new RegExp(`[${obj.reduce((s, {r}) => s += r, "")}]`, "g"), e => {
      const t = e.codePointAt(0);
      if ((t >= 48 && t <= 57) || (t >= 65 && t <= 90) || (t >= 97 && t <= 122)) {
        return obj.reduce((s, {r, d}) => {
          if (new RegExp(`[${r}]`).test(e)) s = String.fromCodePoint(e.codePointAt(0) + d);
          return s;
        }, "")
      }
      return e;
    })},
    bold: function(text) {return this.c(text, [{r: "0-9", d: 120734}, {r: "A-Z", d: 120211}, {r: "a-z", d: 120205}])},
    italic: function(text) {return this.c(text, [{r: "A-Z", d: 120263}, {r: "a-z", d: 120257}])},
    boldItalic: function(text) {return this.c(text, [{r: "A-Z", d: 120315}, {r: "a-z", d: 120309}])},
  };

  if(style == 'bold')
    return(conv.bold(text));
  else if(style == 'italic')
    return(conv.italic(text));
  else if(style == 'bolditalic')
    return(conv.boldItalic(text));
  else
    return text;
}

which I have found on this StackOverflow link: Google script string with style

I tried reversing the code to convert the styled unicode characters to plain text but failed. Hopefully somebody could reverse the code to get the plain text from the styled unicode characters.


Solution

  • Building on Tanaike's work, here's a function that will accept any text and return it formatted or plain, as requested.

    /**
    * Converts text to bold, italic or plain Unicode characters, as in
    * '𝗦𝗮𝗺𝗽𝗹𝗲 𝘁𝗲𝘅𝘁', '𝘚𝘢𝘮𝘱𝘭𝘦 𝘵𝘦𝘹𝘵', '𝙎𝙖𝙢𝙥𝙡𝙚 𝙩𝙚𝙭𝙩', 'Sample text'.
    * Numbers can be bolded but not italicized.
    *
    * @param {"A2:D42"} text Text strings to format.
    * @param {"bold italic"} style One of "bold", "italic", "bold italic" or "plain".
    * @return {String[][]} The formatted text.
    * @customfunction
    */
    function unicodeFormat(text, style) {
      // see https://stackoverflow.com/a/79113754/13045193
      const conv = {
        c: (text, spec) =>
          text.replace(new RegExp(`[${spec.reduce((s, { r }) => s += r, '')}]`, 'g'), e => {
            const t = e.codePointAt(0);
            if (!((48 <= t && t <= 57) || (65 <= t && t <= 90) || (97 <= t && t <= 122))) return e;
            return spec.reduce((s, { r, d }) => e.match(new RegExp(`[${r}]`)) ? String.fromCodePoint(e.codePointAt(0) + d) : s, '');
          }),
        plain: function (text) { return text.normalize('NFKC') },
        bold: function (text) { return this.c(text, [{ r: '0-9', d: 120734 }, { r: 'A-Z', d: 120211 }, { r: 'a-z', d: 120205 }]) },
        italic: function (text) { return this.c(text, [{ r: 'A-Z', d: 120263 }, { r: 'a-z', d: 120257 }]) },
        bolditalic: function (text) { return this.c(text, [{ r: '0-9', d: 120734 }, { r: 'A-Z', d: 120315 }, { r: 'a-z', d: 120309 }]) },
      };
      const s = String(style).toLowerCase().split(' ').sort().join('').replace(/[^a-z]/g, '');
      if (!conv[s]) throw new Error(`uniCodeFormat expected a style of "bold", "italic", "bold italic" or "plain", but got "${style}" instead.`);
      const _format = (text) =>
        Array.isArray(text)
          ? text.map(_format)
          : text || text === 0 ? conv[s](conv.plain(String(text))) : null;
      return _format(text);
    }
    

    Supports arrays of text. Can re-format already formatted text. The function can be called from another JavaScript function, or directly from a spreadsheet formula as a custom function.

    Here's a short test function that converts text to various formats, then converts those formatted strings back to plain text:

    function test() {
      const formattedArray = ['bold', 'italic', 'bold italic', 'plain']
        .map(format => unicodeFormat('Sample text 1234567890', format));
      const plainArray = unicodeFormat(formattedArray, 'plain');
      console.log(formattedArray);
      console.log(plainArray);
    }
    

    To test this as a custom function, enter text in column A and put this formula in row 1 of a free column:

    =unicodeFormat(A1:A, "bold italic")