A naïve attempt at parsing CSS in JavaScript – Part 2

Now that HTML encoding and decoding is working and the bug in WordPress causing parts of the JavaScript to be HTML encoded and therefore prevent the script from running properly is fixed, I can finally attempt running my comment parser again.

/* comment should be highlighted but nothing else */
p > span:first-child { font-weight: bold; }

Woo hoo! It works. This is the code:

<style>
#syntax-highlight-2 .comment {
  color: green;
}
</style>
<pre class="wp-block-code"><code id="syntax-highlight-2">/* comment should be highlighted but nothing else */
p &gt; span:first-child { font-weight: bold; }</code></pre>
<script>
(() => {
const encodeHtml = html => {
  const d = document.createElement('div');
  d.textContent = html;
  return d.innerHTML;
}

const decodeHtml = html => {
  const t = document.createElement('textarea');
  t.innerHTML = html;
  return t.value;
}

const parse = cssStr => {
  const state = {};
  let tokens = [];
  let cache = '';
  for (let i = 0; i < cssStr.length; i++) {
    // Consume comments
    if (!state.isComment && (cssStr[i] === '/') && (cssStr[i+1] === '*')) {
      state.isComment = true;
      if (cache) {
        tokens.push({t: 'comment', v: cache});
      }
      cache = '';
    }
    cache += cssStr[i];
    if (state.isComment && (cssStr[i-1] === '*') && (cssStr[i] === '/')) {
      state.isComment = false;
      tokens.push({t: 'comment', v: cache});
      cache = '';
    }
  }
  if (cache) {
    tokens.push({t: 'plain', v: cache});
  }
  return tokens;
}

const highlightSnippet = () => {
  const snippetElement = document.getElementById('syntax-highlight-2');
  const htmlEncodedCss = snippetElement.innerHTML;
  const html = decodeHtml(htmlEncodedCss);
  const tokens = parse(html);
  let output = '';
  tokens.forEach(token => {
    let part = '';
    switch(token.t) {
      case 'comment': part = `<span class="comment">${encodeHtml(token.v)}</span>`; break;
      default: part = `<span>${encodeHtml(token.v)}</span>`
    }
    output += part;
  });
  snippetElement.innerHTML = output;
}

highlightSnippet();

})();
</script>

Leave a Reply

Your email address will not be published.

Color scheme: