четверг, 28 мая 2015 г.

JavaScript Object Hierarchy Visualization Tree Function

// hierarchy(obj, prefix='', opts={})
// Функция 'hierarchy' возвращает строку, представляющую из себя иерархию элементов объекта 'obj', соединенных с помощью символов труб в формате Unicode.
// 'obj' должен представлять из себя дерево, состоящее из вложенных друг в друга объектов, имеющих метки 'label' и массивы узлов 'nodes'.
// 'label' это строка с текстом, который выводится на соотвествующем уровне узла, а 'nodes' - это массив зависимостей текущего узла.
// Если узел является строкой, то эта строка будет использована в качестве метки 'label', а вместо узла 'nodes' для нее будет использован пустой массив.
// 'prefix' - это строка, которая вставляется перед основным содержимым на каждом шаге сформированного графа. Используется внутри алгоритма  рекурсивного обхода дерева.
// Если метка 'label' имеет внутри себя символы перехода на новую строку (\n), то в этом случае они будут использованы в качестве перехода на новую строку в месте вывода текста метки, учитывая текущий отступ и 'prefix' на данному уровне.
// Для отключения вывода результата выполнения функции в формате Unicode при предпочтении вывода результата в формате ANSI установите значение opts.unicode в false.

function hierarchy (obj, prefix, opts) {

    if (prefix === undefined) {prefix = '';}
    if (!opts) {opts = {};}

    function chr (s) {
        var chars = {
            '│' : '|',
            '└' : '`',
            '├' : '+',
            '─' : '-',
            '┬' : '-'
        };
        return opts.unicode === false ? chars[s] : s;
    };
 
    if (typeof obj === 'string') {
        obj = {label: obj};
    }
 
    var nodes = obj.nodes || []
        , lines = (obj.label || '').split('\n')
        , splitter = '\n' + prefix + (nodes.length ? chr('│') : ' ') + ' ';
 
    return prefix
           + lines.join(splitter) + '\n'
           + nodes.map(function (node, ix) {
                                    var last = ix === nodes.length - 1
                                       , more = node.nodes && node.nodes.length
                                       , prefix_ = prefix + (last ? ' ' : chr('│')) + ' ';

                                    return prefix
                                           + (last ? chr('└') : chr('├')) + chr('─')
                                           + (more ? chr('┬') : chr('─')) + ' '
                                           + hierarchy(node, prefix_, opts).slice(prefix.length + 2);
                               }).join('');

}

// Пример использования без префикса 'prefix' и опций 'opts'

var result = hierarchy(
    {
          label: 'beep'
        , nodes: [
              'ity'
            , {
                  label: 'boop'
                , nodes: [
                      {
                            label: 'o_O'
                          , nodes: [
                                {
                                      label: 'oh'
                                    , nodes: [
                                          'hello'
                                        , 'puny'
                                      ]
                                }
                              , 'human'
                            ]
                      }
                    , 'party\ntime!'
                  ]
              }
          ]
    }
);

console.log(result);

// beep
// ├── ity
// └─┬ boop
//   ├─┬ o_O
//   │ ├─┬ oh
//   │ │ ├── hello
//   │ │ └── puny
//   │ └── human
//   └── party
//          time!

// Пример использования с префиксом 'prefix' и опциями 'opts'

var result = hierarchy(
      {
          label: 'beep'
        , nodes: [
              'ity'
            , {
                  label: 'boop'
                , nodes: [
                      {
                            label: 'o_O'
                          , nodes: [
                                {
                                      label: 'oh'
                                    , nodes: [
                                          'hello'
                                        , 'puny'
                                      ]
                                }
                              , 'human'
                            ]
                      }
                    , 'party\ntime!'
                  ]
              }
          ]
      }
    , '...'
    , {unicode: false}
);

console.log(result);

// ...beep
// ...+-- ity
// ...`-- boop
// ...  +-- o_O
// ...  | +-- oh
// ...  | | +-- hello
// ...  | | `-- puny
// ...  | `-- human
// ...  `-- party
// ...      time!

Комментариев нет:

Отправить комментарий