npm package: @hibryda/count-sloc-h
Description: A tool for counting SLoCs with support of COCOMO I metrics and globbing, made specifically to address Vue's polymorphic files. Deep fork of Edvin Havic's <edvinhavic@gmail.com> node-sloc
Author: Hibryda
Latest version: 0.0.1

# NodeJS SLoCs counter with COCOMO I metrics

## count-sloc-h

A ES6 module for counting SLoCs with support of COCOMO I metrics and globbing, made specifically to address Vue's polymorphic files. Deep fork (very deep, almost rewrite) of Edvin Havic's [node-sloc](https://www.npmjs.com/package/node-sloc) package.

The module has several useful features:

- returns metrics in both aggregated and per-file form

- produces several objects containing the following:
  
  - timestamp
  
  - totals of all metrics
  
  - flat list of files with associated metrics
  
  - files' tree
  
  - aggregated counts for all file types
  
  - aggregated counts for actual, separate, languages
  
  - aggregated counts for polymorphic files (like Vue, which is the only defined atm, however definitions of others are planned)
  
  - COCOMO I assessment of effort, duration and staffing. COCOMO II is planned to be included as well.

- supports globbing in excluded files

- supports multiple sources (directories or files)

- is asynchronous and skips globbed out destinations without scanning

- allows for excluding parts of files from counting



### Installation

```shell
npm -i @hibryda/count-sloc-h
```

or

```shell
yarn add @hibryda/count-sloc-h
```



### Interface

The module exposes the class `CountSlocH` which must/can be provided with the following options:

- `path` <String>|<Array> [required]
  
  path or paths to scan for files. If they overlap, duplicates are eliminated

- `ignore` <String>|<Array> [optional]
  
  glob or path to exclude from results. Defaults to `node_modules/`

- `root` <String> [optional]
  
  common absolute root part of of path to remove from filepaths when delivering results. Defaults to empty string

- `extensions`<Array> [optional]
  
  List of extensions to look after. Adds provided extensions to standard lookup list

- `ignoreDefault` <Boolean> [optional]
  
  Instructs object to ignore default lookup list and use only provided extenstions. Works only in tandem with the previous command

- `logger` <Object> [optional]
  
  alternative logger to present output in terminal - defaults to standard `console`

- `logLevel` <Number> [optional]
  
  Number in range from 0 to 3, where 0 displays nothing, 3 displays all messages, defaults to 3

- `logMargin` <Number> [optional]
  
  Specifies margin (in characters) that must be taken into account when shortening filepaths displayed in terminal during search. Important when alternative console, like `consola` are used (due to labels). Defaults to 10.

- `logPadUp` <Number> [optional]
  
  In alternative consoles single line messages can take up 2 lines for aesthetic reasons - this parameter allows for getting rid of surplus lines. Defaults to 1

- `cocomoModel` <String> [optional]
  
  Specifies model used in COCOMO calculations. Defaults to `basic` and it's the only option at the moment

- `cocomoMode` <String> [optional]
  
  Specifies mode of calculations. Available are: `organic`, `semiDetached`, `embedded`

In addition to options, parts of files can be skipped by using two switches:

- `[countsloch:off]` excludes this and subsequent lines from counting

- `[countsloch:on]` swiches counting on again

Switches must be surrounded inside files in language-specific comment markers. For instance, in JavaScript it would look as follows:

```js
const countSloc = async (file, envObj) => {
// [countsloch:off]
    return new Promise((resolve, reject) => {
        const extension = file
            .split('.')
            .pop()
            .toLowerCase()
        let isLangMulti = false
// [countsloch:on]
        let allComments = getCommentChars(extension)
```

###

### Usage

The default export of the module provides an instance. However there's also a named export `CountSlocH` which exposes the class itself.

Both accept options to be initiated.

```js
import { CountSlocH } from 'count-sloc-h'
;(async () => {
    const csh = new CountSlocH({
        root: '/home/hibryda/apps/project1',
        path: ['/home/hibryda/apps/project1/subproject1', './project1/subproject2', '../index.vue'],
        ignore: ['node_modules/', '*.json', '.nuxt'],
        logger: consola
    })

    const slocsCounts = await csh.scan()

    consola.log(slocCounts)
})()
```

After initiation, the following methods are available:

- `scan` <no parameters> [async]
  
  Performs scan and returns an object with counts

- `update` <Object> [required]
  
  Updates the instance with new options

- `getExtensions` <no parameters>
  
  Returns an array of extensions defined in module

The output of `scan` method presents as follows:

```js
metrics: {
    timestamp: 1610827135710
},
totals: { files: 15, loc: 1558, sloc: 1401, comments: 157, blanks: 40, lines: 1598, skipped: 0 },
files: {
    '674680299911|||/subproject1/charts.js': {
        fileWithoutRoot: '/subproject1/charts.js',
        loc: 17,
        sloc: 7,
        comments: 10,
        blanks: 2,
        lines: 19,
        skipped: 0
    },
    '476981730777|||/subproject1/charts-mod.js': {
        fileWithoutRoot: '/subproject1/charts-mod.js',
        loc: 216,
        sloc: 211,
        comments: 5,
        blanks: 5,
        lines: 221,
        skipped: 0
    }

    ...

},
tree: {
    project1: {
        subproject1: {
            'charts.js': {
                filename: '/subproject1/charts.js',
                lang: 'js',
                multi: false,
                loc: 17,
                sloc: 7,
                comments: 10,
                blanks: 2,
                lines: 19,
                skipped: 0
            },
            'charts-mod.js': {
                fileWithoutRoot: '/subproject1/charts-mod.js',
                lang: 'js',
                multi: false,
                loc: 216,
                sloc: 211,
                comments: 5,
                blanks: 5,
                lines: 221,
                skipped: 0
            }

            ...

        }
    }
},
allLangs: {
    js: { files: 3, loc: 136, sloc: 89, comments: 47, blanks: 7, lines: 143, skipped: 0 },

    ...

    vue: { files: 12, loc: 1422, sloc: 1312, comments: 110, blanks: 33, lines: 1455, skipped: 0 }
},
langs: { js: { files: 3, loc: 136, sloc: 89, comments: 47, blanks: 7, lines: 143, skipped: 0 } ... },
multi: { vue: { files: 12, loc: 1422, sloc: 1312, comments: 110, blanks: 33, lines: 1455, skipped: 0 } ... },
cocomo: {
    effort: 22.84699009797671,
    duration: 8.505139152658836,
    staffing: 2.9487509187608016
}
```

### License

MIT - enjoy