npm package: @mb3/speck
Description: Simple lead comment parser that generates JSON from block comments.
Author: MB3 Technologies Inc
Latest version: 1.5.0

# Speck

[![Build Status](https://circleci.com/gh/mb3online/speck.png?style=shield&circle-token=82e5fd42642bca9bd02b2bfc0a534a0dd0c81b91)](https://circleci.com/gh/mb3online/speck) [![Code Climate](https://codeclimate.com/github/MB3Online/speck/badges/gpa.svg)](https://codeclimate.com/github/MB3Online/speck) [![Test Coverage](https://codeclimate.com/github/MB3Online/speck/badges/coverage.svg)](https://codeclimate.com/github/MB3Online/speck/coverage)

#### A simple parser to generate JSON from leading block comments.

> See [Atom Speck Language](https://atom.io/packages/language-speck) for a language package that does syntax highlighting within comments for speck.


## Usage

### CLI
```
    Usage: speck [options] -i [dir]

    Options:

      -h, --help             output usage information
      -V, --version          output the version number
      -i, --input [dir]      Input Directory
      -c, --config [config]  The relative path to a directory where a speck.json config file can be found
      -o, --output [dir]     Output directory
      -t, --types [values]   A list of all file types to parse separated by comma[,]
      --validate             Validate speck files
      --php                  Use php parser.
```

### speck.json

> You can use speck with a config file like the one below. It can be used to ignore paths by globs and store all other options for a simpler CLI execution. Speck will search the CWD for a speck.json file or you can specify which directory to look in with the `-c` or `--config` option.

```json
{
    "ignore": [
        "!**/src{/,*}**",
        "**/*.spec.js"
    ]
}
```

### Generating Jest Test Shells

Input

```javascript
/* speck
  'name': 'JestSpeckPlugin'
  'extends': 'SpeckPlugin'
  'type': 'Plugin'
  'description': 'Generates a Jest test shell with the given interactions.'
  'interactions': [
    'can parse interactions from a file.',
    'can generate a test shell from a file.',
    'can append to a file cleanly.',
    'can create a new test file cleanly.'
  ]
*/
export class JestSpeckPlugin extends SpeckPlugin {
  // ...
}
```

Output

```javascript
import {JestSpeckPlugin} from '../relative/path/to/jest.plugin.js';

describe('JestSpeckPlugin', () => {
  it('should parse interactions from a file.', () => {
    fail('Not Implemented');
  });

  it('should generate a test shell from a file.', () => {
    fail('Not Implemented');
  });

  it('should append to a file cleanly.', () => {
    fail('Not Implemented');
  });

  it('should create a new test file cleanly.', () => {
    fail('Not Implemented');
  });
});
```

## Example

Input:

```javascript
/* speck
  'class name': 'Comment'
  'description': 'Parses a comment from within a file.'
  'comment structure': 'Block comments should be written in cson'
  'example usage':
     'js': '''let c = new Comment('@title: hello');
       c.parse().toJSON(); // { title: 'hello' }'''
     'markdown': '''# Speck.Comment
       ## Features
       + Multiline
       + Json (nested is also suppoted)
       + Pluggable'''
  'multi line': '''This is a test
   for multiline comments'''
  'list items': [
   0,1,2,3,4
  ]
 */

 export class SomeJSClass {
   // ...
 }
```

Output:

```json
{
    "class name": "Comment",
    "description": "Parses a comment from within a file.",
    "comment structure": "Block comments should be written in cson",
    "example usage": {
        "js": "let c = new Comment('@title: hello');\nc.parse().toJSON(); // { title: 'hello' }",
        "markdown": "# Speck.Comment\n## Features\n+ Multiline\n+ Json (nested is also suppoted)\n+ Pluggable"
    },
    "multi line": "This is a test\nfor multiline comments",
    "list items": [
        0,
        1,
        2,
        3,
        4
    ]
}
```


## Extending

This repo is a base for the parser, it will take any block comments and generate JSON output. The base class doesn't ship with an implementation and will fail if run as follows:

```
import Speck from 'speck';

const parser = new Speck(...);

parser
  .gather()
  .parse(); // Throws an error.
```

However, it does ship with a Speck implemented using the babel parser [babylon](https://github.com/babel/babylon), this is the default when running the CLI:

```
import BabelSpeck from 'speck';

const parser = new BabelSpeck(...);

parser
  .gather()
  .parser(); // Generates JSON from ES6 code.
```

It also ships with a custom php tokenizer to parse leading comments.

To use Speck with other languages to generate JSON from leading block comments you must implement the `getComments` method.

Example

```
import Speck from 'speck';

export default BabelSpeck extends Speck {
  getComments(code) {
    // Parse out, and return, leading comments from code.

    return babylon.parse(code, OPTIONS)
      .comments
      .filter(comment => comment.type === 'CommentBlock')
      .map(comment => comment.value);
  }
}
```

## Plugins

Plugins for speck are simple, all you need to do is export a class with a run function that takes three parameters:
- [`logger`](https://github.com/mb3online/speck/blob/master/src/logger.js)
- `file`: the source file path
- `json`: the json results from the source file speck comments

```javascript
export default class ExmplePlugin {
    run(logger, file, json): void {
        // ...
    }
}
```

If you need to pass options to the plugin at runtime, you can specify the configuration in the `speck.json` config file as an object that will be passed to the constructor of the plugin.

```javascript
export default class ExamplePlugin {
    constructor(options = {}) {
        // ...
    }
}
```

> All plugins are run after the base parsing of speck has been complete.

To see an example of how to write a Speck Plugin see [MB3-jest-speck-plugin](https://npmjs.com/packages/mb3-jest-speck-plugin)


## Development

- to test `yarn test`
- to build `yarn run build` -> this will also run the tests
- to run `yarn start -- [options]` OR `./script/speck.js [options]` OR `yarn link; speck [options]`

### Environment Setup

- make sure you have node version `> 6.2.x` ([n](https://www.npmjs.com/package/n) is an easy way to manage your node on MAC only.) run : `yarn add -g n; sudo n stable`

- make sure you have php 7 (`brew update; brew install homebrew/php/php70`)

- checkout the repo and `yarn install; yarn add -g gulp; yarn add -g jasmine`