code: function _removePreserve(ctx, input, options) {
    // recurse through arrays
    if(_isArray(input)) {
      var output = [];
      for(var i = 0; i < input.length; ++i) {
        var result = _removePreserve(ctx, input[i], options);
        // drop nulls from arrays
        if(result !== null) {
          output.push(result);
        }
      }
      input = output;
    }
    else if(_isObject(input)) {
      // remove @preserve
      if('@preserve' in input) {
        if(input['@preserve'] === '@null') {
          return null;
        }
        return input['@preserve'];
      }
  
      // skip @values
      if(_isValue(input)) {
        return input;
      }
  
      // recurse through @lists
      if(_isList(input)) {
        input['@list'] = _removePreserve(ctx, input['@list'], options);
        return input;
      }
  
      // recurse through properties
      for(var prop in input) {
        var result = _removePreserve(ctx, input[prop], options);
        var container = jsonld.getContextValue(ctx, prop, '@container');
        if(options.compactArrays && _isArray(result) && result.length === 1 &&
          container === null) {
          result = result[0];
        }
        input[prop] = result;
      }
    }
    return input;
  }
docs: Removes the @preserve keywords as the last step of the framing algorithm.
  
  @param ctx the active context used to compact the input.
  @param input the framed, compacted output.
  @param options the compaction options used.
  
  @return the resulting output.