npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@bem/walk

v1.0.0-2

Published

Walk easily thru BEM file structure

Downloads

22

Readme

bem-walk

Tool for traversing a BEM project's file system.

NPM Status Travis Status Windows Status Coverage Status Dependency Status

It returns the following information about found files:

Quick start

Note To use bem-walk, you must install Node.js 4.0+.

1. Install bem-walk

$ npm install --save @bem/walk

2. Enable bem-walk

Create a JavaScript file with any name and add the following string:

const walk = require('@bem/walk');

Note You will use this JavaScript file for all the following steps.

3. Define file system levels

Define the project's file system levels in the config object.

const config = {
    // project levels
    levels: {
        'lib/bem-core/common.blocks': {
            // `naming` — file naming scheme
            naming: 'two-dashes'
        },
        'common.blocks': {
            // `scheme` — file system scheme
            scheme: 'nested'
        }
    }
};

Specify either the file naming scheme or the file system type for each level. This lets you get information about BEM entities using their names or using the names of files and directories.

The table shows the possible values that can be set for each of the schemes.

| Key | Scheme | Default value | Possible values | |----|------|-----|----------| | naming | File naming.|origin| origin, two-dashes| | scheme | File system.|nested|nested, flat|

More information:

Note Instead of defining the project's levels manually, use the bem-config tool.

const config = require('bem-config')();
const levelMap = config.levelMapSync();
const stream = walk(levels, levelMap);

4. Define the paths to traverse

Specify the paths to walk in the levels object.

Path options:

  • Relative to the root directory.

    const levels = [
        'libs/bem-core/common.blocks',
        'common.blocks'
    ];
  • Absolute.

    const levels = [
        '/path/to/project/lib/bem-core/common.blocks',
        '/path/to/project/common.blocks'
    ];

5. Get information about found files

Pass the walk() method the levels and config objects.

Streaming is used for getting data about found files. When a portion of data is received, the data event is generated and information about the found file is added to the files array. If an error occurs, bem-walk stops processing the request and returns a response containing the error ID and description. The end event occurs when all the data has been received from the stream.

const files = [];

const stream = walk(levels, config);
// adds information about a found file to the end of the "files" array
stream.on('data', file => files.push(file));

stream.on('error', console.error);

stream.on('end', () => console.log(files));

Complete code sample

When all these steps have been completed, the full code of the JavaScript file should look like this:

const walk = require('@bem/walk');
const config = require('bem-config')();
const levels = [
    'libs/bem-components/common.blocks',
    'common.blocks'
];
const files = [];

const stream = walk(levels, {
        levels: config.levelMapSync()
    })
    .on('data', file => files.push(file))
    .on('error', console.error)
    .on('end', () => console.log(files));

Note This sample uses the bem-config package.

API

walk method

walk(levels, config);

Description

Traverses the directories described in the levels parameter and returns stream.Readable.

Input parameters

Requirements for the search are defined in the levels and config parameters.

| Parameter | Type | Description | |----------|-----|----------| |levels|string[]|Paths to traverse| |config|object|Project levels|

Output data

Readable stream (stream.Readable) that has the following events:

| Event | Description | |----------|-----| |'data'|Returns a JavaScript object with information about a found file. The example below shows a JSON interface with elements that are in the response for the walk method. Objects and keys have sample values. Example {  "cell": {    "entity": { "block": "page" },    "layer": "libs/bem-core/desktop.blocks",    "tech": "bemhtml"  },  "path": "libs/bem-core/desktop.blocks/page/page.bemhtml.js"}cell — BEM cell instance.entity — BEM entity name instance.layer — Directory path.tech — Implementation technology.path — Relative path to the file.| | 'error' | Generated if an error occurred while traversing the levels. Returns an object with the error description.| | 'end' | Generated when bem-walk finishes traversing the levels defined in the levels object. |

Usage examples

Typical tasks that use the resulting JavaScript objects:

Grouping

Grouping found files by block name.

const walk = require('@bem/walk');
const config = require('bem-config')();
const util = require('util');
const levels = [
    'libs/bem-components/common.blocks',
    'common.blocks'
];
const groups = {};

const stream = walk(levels, {
        levels: config.levelMapSync()
    })
    .on('data', file => {
        // Getting the block name for a found file.
        const block = file.entity.block;

        // Adding information about the found file.
        (groups[block] = []).push(file);
    })
    .on('error', console.error)
    .on('end', () => console.log(util.inspect(groups, {
        depth: null
    })));

/*
{ button:
   [ BemFile {
      cell: BemCell {
         entity: BemEntityName { block: 'button', mod: { name: 'togglable', val: 'radio' } },
         tech: 'spec.js',
         layer: 'libs/bem-components/common.blocks'
      },
      path: 'libs/bem-components/common.blocks/button/_togglable/
        button_togglable_radio.spec.js' } ] },
 ...
}
*/

Filtering

Finding files for the popup block.

const walk = require('@bem/walk');
const config = require('bem-config')();
const levels = [
    'libs/bem-components/common.blocks',
    'common.blocks'
];
const files = [];

const stream = walk(levels, {
        levels: config.levelMapSync()
    })
    .on('data', file => {
        // Getting the block name for a found file.
        const block = file.entity.block;

        // Adding information about the found file.
        if (block == 'popup') {
            files.push(file);
        }
    })
    .on('error', console.error)
    .on('end', () => console.log(files));

/*
[BemFile {
   cell: BemCell {
     entity: BemEntityName { block: 'popup', mod: { name: 'target', val: true } },
     tech: 'js',
     layer: 'libs/bem-components/common.blocks'
   },
   path: 'libs/bem-components/common.blocks/popup/_target/popup_target.js'
},
...
]
*/

Transformation

Finding BEM files, reading the contents, and creating the new source property.

const fs = require('fs');
const walk = require('@bem/walk');
const config = require('bem-config')();
const stringify = require('JSONStream').stringify;
const through2 = require('through2');
const levels = [
    'libs/bem-components/common.blocks',
    'common.blocks'
];

const stream = walk(levels, {
        levels: config.levelMapSync()
    })
    .pipe(through2.obj(function(file, enc, callback) {
        try {
            // Certain technologies (for example, `i18n`) might be directories instead of files.
            if (fs.statSync(file.path).isFile()) {
                // Writing the file content to the `source` field.
                file.source = fs.readFileSync(file.path, 'utf-8');
                this.push(file);
            }

        } catch (err) {
            callback(err);
        }
    }))
    .pipe(stringify())
    .pipe(process.stdout);

/*
[{"cell":{
    "entity":{"block":"search","elem":"header"},
    "tech":"css",
    "layer":"common.blocks"
  },
  "path":"common.blocks/search/__header/search__header.css",
  "source":".search__header {\n\tdisplay: block;\n\tfont-size: 20px;\n\tcolor:
  rgba(0,0,0,0.84);\n\tmargin: 0;\n\tpadding: 0 0 16px;\n\n}\n\n"},
...
]
*/