SafeHTMLSubstitution.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. const pug = require('pug-runtime')
  2. const SPLIT_REGEX = /<(\d+)>(.*?)<\/\1>/g
  3. function render(locale, components) {
  4. const output = []
  5. function addPlainText(text) {
  6. if (!text) return
  7. output.push(pug.escape(text))
  8. }
  9. // 'PRE<0>INNER</0>POST' -> ['PRE', '0', 'INNER', 'POST']
  10. // '<0>INNER</0>' -> ['', '0', 'INNER', '']
  11. // '<0></0>' -> ['', '0', '', '']
  12. // '<0>INNER</0><0>INNER2</0>' -> ['', '0', 'INNER', '', '0', 'INNER2', '']
  13. // '<0><1>INNER</1></0>' -> ['', '0', '<1>INNER</1>', '']
  14. // 'PLAIN TEXT' -> ['PLAIN TEXT']
  15. // NOTE: a test suite is verifying these cases: SafeHTMLSubstituteTests
  16. const chunks = locale.split(SPLIT_REGEX)
  17. // extract the 'PRE' chunk
  18. addPlainText(chunks.shift())
  19. while (chunks.length) {
  20. // each batch consists of three chunks: ['0', 'INNER', 'POST']
  21. const [idx, innerChunk, intermediateChunk] = chunks.splice(0, 3)
  22. const component = components[idx]
  23. const componentName =
  24. typeof component === 'string' ? component : component.name
  25. // pug is doing any necessary escaping on attribute values
  26. const attributes = (component.attrs && pug.attrs(component.attrs)) || ''
  27. output.push(
  28. `<${componentName + attributes}>`,
  29. ...render(innerChunk, components),
  30. `</${componentName}>`
  31. )
  32. addPlainText(intermediateChunk)
  33. }
  34. return output.join('')
  35. }
  36. module.exports = {
  37. SPLIT_REGEX,
  38. render,
  39. }