# All files / lib to-string.js

98.26% Statements 113/115
95% Branches 19/20
100% Functions 4/4
98.26% Lines 113/115

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    1162x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    11x
    11x
    11x
    11x
    11x
    11x
    10x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    11x
    1x
    1x
    1x
    11x
    11x
    11x
    11x
    11x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    16x
    16x
    16x
    16x
    3x
    3x
    3x
    3x
    3x
    1x
    1x
    2x
    3x
    16x
    16x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    2x
    29x
    29x
    29x
    29x

    29x
    29x
    29x
    29x
    29x
    10x
    15x
    15x
    10x
    29x
    29x
    13x
    13x
    29x
    29x
    3x
    3x
    3x
    3x
    3x
    4x
    3x
    3x
    3x
    3x
    29x
    29x
    29x
     import createTree from './tree/create';
    import { TransactionConfig, ValidInput, VTree, VTreeAttributes } from './util/types';
    import Transaction, { defaultTasks, tasks } from './transaction';
    import release from './release';

    const { keys } = Object;

    /**
     * Renders input to a string.
     *
     * Works like outerHTML by rendering a VTree and returning the source. This
     * will accept any input that `outerHTML` normally accepts. This is a true
     * render, but omits the DOM patching task.
     *
     * @param {ValidInput} input
     * @param {TransactionConfig} config
     * @return {string}
     */
    export default function toString(input, config = {}) {
      const oldTree = createTree();
      const activeTasks = new Set(config.tasks || defaultTasks);

      // Replace the `endAsPromise` task with the string return value.
      activeTasks.delete(tasks.endAsPromise);
      activeTasks.add(function endAsString(/** @type {Transaction} */ transaction) {
        return serializeVTree(transaction.oldTree);
      });

      config.tasks = [...activeTasks];
      config.inner = true;

      let markup = '';

      try {
        markup = /** @type {string} */ (
          Transaction.create(oldTree, input, config).start()
        );
      }
      catch (e) {
        release(oldTree);
        throw e;
      }

      release(oldTree);

      return markup;
    }

    /**
     * serializeAttributes
     *
     * Takes in a diffHTML VTree attributes object and turns it into a key=value
     * string.
     *
     * @param {VTreeAttributes} attributes
     * @return {String}
     */
    function serializeAttributes(attributes) {
      const attrs = keys(attributes);

      return attrs.length ? ' ' + attrs.map((keyName) => {
        const value = attributes[keyName];
        const isFalsy = !value;
        const isDynamic = typeof value === 'object' || typeof value === 'function';

        if (value === true) {
          return keyName;
        }

        return `${keyName}${(!isFalsy && !isDynamic) ? `="${String(value)}"` : ''}`;
      }).join(' ') : '';
    }

    /**
     * serializeVTree
     *
     * Takes in a diffHTML VTree object and turns it into a string of HTML.
     *
     * @param {VTree=} vTree
     * @return {String}
     */
    function serializeVTree(vTree) {
      let output = '';

      if (!vTree) {
        return output;
      }

      const { childNodes, nodeType, nodeName: tag, nodeValue, attributes } = vTree;

      // Document fragment.
      if (nodeType === 11) {
        for (let i = 0; i < childNodes.length; i++) {
          output += serializeVTree(childNodes[i]);
        }
      }
      // Empty element.
      else if (!(childNodes.length) && nodeType === 1) {
        output += `<${tag}${serializeAttributes(attributes)}></${tag}>`;
      }
      // Text Nodes.
      else if (nodeType === 3) {
        output += nodeValue;
      }
      // Presentational DOM Node.
      else if (childNodes.length) {
        const children = childNodes.map(childNode =>
          `${serializeVTree(childNode)}`
        ).join('');

        output += `<${tag}${serializeAttributes(attributes)}>${children}</${tag}>`;
      }

      return output;
    }