четверг, 4 июня 2015 г.

JavaScript Build Folder Tree Visualization

var fs = require('fs') // file system module
    , path = require('path'); // file path module

// Function dirTree() returns json tree of directory structure
function dirTree (rootDirectoryPath) {
    rootDirectoryPath = rootDirectoryPath.replace(/\/+$/ , ''); // clean trailing '/'(s)
   
    var directoryElement
        , treeObject;
       
    if (fs.existsSync(rootDirectoryPath)) {directoryElement = fs.lstatSync(rootDirectoryPath); // extract tree element if root exists
    } else {return 'Error: root does not exist.';
    }
   
    // tree treeObjectect info
    var treeObject = {
          path: rootDirectoryPath
        , name: path.basename(rootDirectoryPath)
        , type: 'unknown'
        , children: []
    };
   
    if (directoryElement.isDirectory()) {
        // execute for each child and call tree recursively
        treeObject.children = fs.readdirSync(rootDirectoryPath).map(function(child){return dirTree(rootDirectoryPath + '/' + child);});
                                                                      treeObject.type = 'folder';
    } else if (directoryElement.isFile()) {             treeObject.type = 'file';
    } else if (directoryElement.isSymbolicLink()) {treeObject.type = 'link';
    } else {                                                       treeObject.type = 'unknown';
    }
   
    return treeObject; // return tree
}

/*

// Пример использования dirTree()

console.log(JSON.stringify(dirTree('./node_modules')));
console.log(dirTree('./node_modules'));

*/

// hierarchy(obj, prefix='', opts={})
// Функция 'hierarchy' возвращает строку, представляющую из себя иерархию элементов объекта 'obj', соединенных с помощью символов труб в формате Unicode.
// 'obj' должен представлять из себя дерево, состоящее из вложенных друг в друга объектов, имеющих метки 'name' и массивы узлов 'children'.
// 'name' - это строка с текстом, который выводится на соотвествующем уровне узла, а 'children' - это массив зависимостей текущего узла.
// Если узел является строкой, то эта строка будет использована в качестве метки 'name', а вместо узла 'children' для нее будет использован пустой массив.
// 'prefix' - это строка, которая вставляется перед основным содержимым на каждом шаге сформированного графа. Используется внутри алгоритма  рекурсивного обхода дерева.
// Если метка 'name' имеет внутри себя символы перехода на новую строку (\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 = {name: obj};
    }
 
    var children = obj.children || []
        , lines = (obj.name || '').split('\n')
        , splitter = '\n' + prefix + (children.length ? chr('│') : ' ') + ' ';
 
    return prefix
           + lines.join(splitter) + '\n'
           + children.map(function (child, ix) {
                                    var last = ix === children.length - 1
                                       , more = child.children && child.children.length
                                       , prefix_ = prefix + (last ? ' ' : chr('│')) + ' ';

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

}

/*

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

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

console.log(result);

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

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

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

console.log(result);

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

*/

console.log(hierarchy(dirTree('./node_modules')));

/*
if (module.parent === undefined) {
    // child dirTree.js ~/foo/bar
    var util = require('util');
    console.log(util.inspect(dirTree(process.argv[2]), false, null));
}
*/

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

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