text: // @flow
  import fs from 'fs'
  import path from 'path'
  import peg from 'pegjs'
  import emojiData from 'emoji-datasource'
  import {invert} from 'lodash'
  
  // from https://github.com/twitter/twemoji/blob/gh-pages/twemoji-generator.js
  function UTF162JSON (text) {
    let r = []
    for (let i = 0; i < text.length; i++) {
      r.push('\\u' + ('000' + text.charCodeAt(i).toString(16)).slice(-4))
    }
    return r.join('')
  }
  
  function genEmojiData () {
    const emojiIndexByChar = {}
    const emojiLiterals = []
    const emojiCharacters = new Set()
    function addEmojiLiteral (unified, name, skinTone) {
      const chars = unified.split('-').map(c => String.fromCodePoint(parseInt(c, 16)))
      const literals = chars.map(c => UTF162JSON(c)).join('')
  
      emojiIndexByChar[chars.join('')] = `:${name}:` + (skinTone ? `:skin-tone-${skinTone}:` : '')
      emojiLiterals.push(literals)
      chars.forEach(c => emojiCharacters.add(c))
    }
  
    emojiData.forEach(emoji => {
      if (emoji.skin_variations) {
        Object.keys(emoji.skin_variations).forEach((v, idx) => addEmojiLiteral(v, emoji.short_name, idx + 1))
      }
      emoji.variations.forEach(v => addEmojiLiteral(v, emoji.short_name))
      addEmojiLiteral(emoji.unified, emoji.short_name)
    })
  
    emojiLiterals.sort((a, b) => b.length - a.length)
  
    return {emojiIndexByChar, emojiLiterals, emojiCharacters}
  }
  
  function buildParser () {
    const {emojiIndexByChar, emojiLiterals, emojiCharacters} = genEmojiData()
    const emojiRegex = `/${emojiLiterals.join('|')}/g`
    const emojiCharacterClass = `${Array.from(emojiCharacters).join('')}`
  
    const sourcePath = process.argv[2]
    const source = fs.readFileSync(sourcePath, {encoding: 'utf8'})
  
    const generatedSource = source
      .replace('__EMOJI_CHARACTERS__', emojiCharacterClass)
      .replace(/__INLINE_MACRO__<([^>]*)>/g, '($1 InlineDelimiter* InlineStart ((InlineDelimiter+ $1 InlineStart) / ($1 InlineCont))*)')
  
    // the regexes here get recompiled on every parse if we put it in the initializer, so we force it to run at import time.
    // $FlowIssue flow doesn't accept this tagged template literal
    const prependJS = String.raw`
      const linkExp = /^(:?\/\/)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}(?::[0-9]{1,6})?\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/=]*)/i
      const dotDotExp = /[^/]\.\.[^/]/
      const emojiExp = ${emojiRegex}
      const emojiIndexByChar = ${JSON.stringify(emojiIndexByChar)}
      const emojiIndexByName = ${JSON.stringify(invert(emojiIndexByChar))}
    `
  
    const appendJS = `
      module.exports.emojiIndexByChar = emojiIndexByChar
      module.exports.emojiIndexByName = emojiIndexByName
    `
  
    const parserJS = peg.generate(generatedSource, {output: 'source', format: 'commonjs'})
    const fullParserJS = prependJS + parserJS + appendJS
  
    const parserPath = path.format({...path.parse(sourcePath), base: undefined, ext: '.js'})
    fs.writeFileSync(parserPath, fullParserJS, {encoding: 'utf8'})
  }
  
  buildParser()
  