docs: function unified() {
    var attachers = []
    var transformers = trough()
    var namespace = {}
    var frozen = false
    var freezeIndex = -1
  
    // Data management.
    processor.data = data
  
    // Lock.
    processor.freeze = freeze
  
    // Plugins.
    processor.attachers = attachers
    processor.use = use
  
    // API.
    processor.parse = parse
    processor.stringify = stringify
    processor.run = run
    processor.runSync = runSync
    processor.process = process
    processor.processSync = processSync
  
    // Expose.
    return processor
  
    // Create a new processor based on the processor in the current scope.
    function processor() {
      var destination = unified()
      var length = attachers.length
      var index = -1
  
      while (++index < length) {
        destination.use.apply(null, attachers[index])
      }
  
      destination.data(extend(true, {}, namespace))
  
      return destination
    }
  
    // Freeze: used to signal a processor that has finished configuration.
    //
    // For example, take unified itself.  It’s frozen.  Plugins should not be
    // added to it.  Rather, it should be extended, by invoking it, before
    // modifying it.
    //
    // In essence, always invoke this when exporting a processor.
    function freeze() {
      var values
      var plugin
      var options
      var transformer
  
      if (frozen) {
        return processor
      }
  
      while (++freezeIndex < attachers.length) {
        values = attachers[freezeIndex]
        plugin = values[0]
        options = values[1]
        transformer = null
  
        if (options === false) {
          continue
        }
  
        if (options === true) {
          values[1] = undefined
        }
  
        transformer = plugin.apply(processor, values.slice(1))
  
        if (typeof transformer === 'function') {
          transformers.use(transformer)
        }
      }
  
      frozen = true
      freezeIndex = Infinity
  
      return processor
    }
  
    // Data management.  Getter / setter for processor-specific informtion.
    function data(key, value) {
      if (string(key)) {
        // Set `key`.
        if (arguments.length === 2) {
          assertUnfrozen('data', frozen)
  
          namespace[key] = value
  
          return processor
        }
  
        // Get `key`.
        return (own.call(namespace, key) && namespace[key]) || null
      }
  
      // Set space.
      if (key) {
        assertUnfrozen('data', frozen)
        namespace = key
        return processor
      }
  
      // Get space.
      return namespace
    }
  
    // Plugin management.
    //
    // Pass it:
    // *   an attacher and options,
    // *   a preset,
    // *   a list of presets, attachers, and arguments (list of attachers and
    //     options).
    function use(value) {
      var settings
  
      assertUnfrozen('use', frozen)
  
      if (value === null || value === undefined) {
        // Empty.
      } else if (typeof value === 'function') {
        addPlugin.apply(null, arguments)
      } else if (typeof value === 'object') {
        if ('length' in value) {
          addList(value)
        } else {
          addPreset(value)
        }
      } else {
        throw new Error('Expected usable value, not `' + value + '`')
      }
  
      if (settings) {
        namespace.settings = extend(namespace.settings || {}, settings)
      }
  
      return processor
  
      function addPreset(result) {
        addList(result.plugins)
  
        if (result.settings) {
          settings = extend(settings || {}, result.settings)
        }
      }
  
      function add(value) {
        if (typeof value === 'function') {
          addPlugin(value)
        } else if (typeof value === 'object') {
          if ('length' in value) {
            addPlugin.apply(null, value)
          } else {
            addPreset(value)
          }
        } else {
          throw new Error('Expected usable value, not `' + value + '`')
        }
      }
  
      function addList(plugins) {
        var length
        var index
  
        if (plugins === null || plugins === undefined) {
          // Empty.
        } else if (typeof plugins === 'object' && 'length' in plugins) {
          length = plugins.length
          index = -1
  
          while (++index < length) {
            add(plugins[index])
          }
        } else {
          throw new Error('Expected a list of plugins, not `' + plugins + '`')
        }
      }
  
      function addPlugin(plugin, value) {
        var entry = find(plugin)
  
        if (entry) {
          if (plain(entry[1]) && plain(value)) {
            value = extend(entry[1], value)
          }
  
          entry[1] = value
        } else {
          attachers.push(slice.call(arguments))
        }
      }
    }
  
    function find(plugin) {
      var length = attachers.length
      var index = -1
      var entry
  
      while (++index < length) {
        entry = attachers[index]
  
        if (entry[0] === plugin) {
          return entry
        }
      }
    }
  
    // Parse a file (in string or vfile representation) into a unist node using
    // the `Parser` on the processor.
    function parse(doc) {
      var file = vfile(doc)
      var Parser
  
      freeze()
      Parser = processor.Parser
      assertParser('parse', Parser)
  
      if (newable(Parser)) {
        return new Parser(String(file), file).parse()
      }
  
      return Parser(String(file), file) // eslint-disable-line new-cap
    }
  
    // Run transforms on a unist node representation of a file (in string or
    // vfile representation), async.
    function run(node, file, cb) {
      assertNode(node)
      freeze()
  
      if (!cb && typeof file === 'function') {
        cb = file
        file = null
      }
  
      if (!cb) {
        return new Promise(executor)
      }
  
      executor(null, cb)
  
      function executor(resolve, reject) {
        transformers.run(node, vfile(file), done)
  
        function done(err, tree, file) {
          tree = tree || node
          if (err) {
            reject(err)
          } else if (resolve) {
            resolve(tree)
          } else {
            cb(null, tree, file)
          }
        }
      }
    }
  
    // Run transforms on a unist node representation of a file (in string or
    // vfile representation), sync.
    function runSync(node, file) {
      var complete = false
      var result
  
      run(node, file, done)
  
      assertDone('runSync', 'run', complete)
  
      return result
  
      function done(err, tree) {
        complete = true
        bail(err)
        result = tree
      }
    }
  
    // Stringify a unist node representation of a file (in string or vfile
    // representation) into a string using the `Compiler` on the processor.
    function stringify(node, doc) {
      var file = vfile(doc)
      var Compiler
  
      freeze()
      Compiler = processor.Compiler
      assertCompiler('stringify', Compiler)
      assertNode(node)
  
      if (newable(Compiler)) {
        return new Compiler(node, file).compile()
      }
  
      return Compiler(node, file) // eslint-disable-line new-cap
    }
  
    // Parse a file (in string or vfile representation) into a unist node using
    // the `Parser` on the processor, then run transforms on that node, and
    // compile the resulting node using the `Compiler` on the processor, and
    // store that result on the vfile.
    function process(doc, cb) {
      freeze()
      assertParser('process', processor.Parser)
      assertCompiler('process', processor.Compiler)
  
      if (!cb) {
        return new Promise(executor)
      }
  
      executor(null, cb)
  
      function executor(resolve, reject) {
        var file = vfile(doc)
  
        pipeline.run(processor, {file: file}, done)
  
        function done(err) {
          if (err) {
            reject(err)
          } else if (resolve) {
            resolve(file)
          } else {
            cb(null, file)
          }
        }
      }
    }
  
    // Process the given document (in string or vfile representation), sync.
    function processSync(doc) {
      var complete = false
      var file
  
      freeze()
      assertParser('processSync', processor.Parser)
      assertCompiler('processSync', processor.Compiler)
      file = vfile(doc)
  
      process(file, done)
  
      assertDone('processSync', 'process', complete)
  
      return file
  
      function done(err) {
        complete = true
        bail(err)
      }
    }
  }