JSFiddle - React, Tailwind, and code Playground

by Kingdaro

HTML

<p><textarea id='input'></textarea></p>
<p><div id='output-html'></div></p>
<p><pre id='output-raw'></pre></p>

CSS

body {
  background: white;
  font: 14pt sans-serif;
}

#input {
  width: 500px;
  height: 200px;
}

#output-html, #output-raw {
  background: rgba(0, 0, 0, 0.03);
  border-bottom: 2px solid rgba(0, 0, 0, 0.03);
  padding: 8px;
}

#output-raw {
  white-space: normal;
}

Babel + JSX

// the "module", if you will
let parseBBC = (function() {
  let bbcPatternString = "\\[(\\w+)(?:=(.+?))?\\](.*?)\\[\\/\\1\\]"
  let bbcPattern = new RegExp(bbcPatternString, 'i')
  let bbcPatternGlobal = new RegExp(bbcPatternString, 'gi')

  return function parseBBC(source, parser) {
    return source.replace(bbcPatternGlobal, match => {
      let info = match.match(bbcPattern)
      let content = parseBBC(info[3], parser)
      let tag = info[1]
      let property = info[2]
      return parser(content, tag, property)
    })
  }
})()


// example stuff
let $input = document.getElementById('input')
let $outputHtml = document.getElementById('output-html')
let $outputRaw = document.getElementById('output-raw')

// parsers are functions that return a string for each BBC match found
// e.g for the below: [b]hello world[/b] --> <b>hello world</b>
// content is the text between BBC tags, e.g. "hello world"
// tag is the bbc tag in the match, e.g. "b"
// prop is for when there's a BBC property, e.g. [color=red]red text[/color], prop would be "red"

// example parser
let parser = (content, tag, prop) => {
	switch (tag) {
  	case 'b':
    case 'i':
    case 'u':
    case 'sub':
    case 'sup':
    case 'pre':
    case 'code':
    	return `<${tag}>${content}</${tag}>`
    
    case 'url':
    	return `<a href="${prop}" target='_blank'>${content}</a>`
     
    case 'color':
    	return `<span style="color: ${prop}">${content}</span>`
  }
}

let outputBBC = source => {
	let output = parseBBC(source, parser)
  $outputHtml.innerHTML = output.replace(/\n/g, '<br>')
  $outputRaw.innerText = output
}

$input.addEventListener('input', event => {
	outputBBC(event.target.value)
})
outputBBC($input.value = `[b]bold[/b]
[i]italics[/i]
[u][b]nested[/b][/u]

[url=http://google.com/]link![/url] [url=http://google.com/][color=red]colored link![/color][/url]

[url=http://google.com/][sup]sup link[/sup][/url] and a [url=http://google.com/][sub]sub...