code:
import { Document, scalarOptions } from './index'
import { CST } from './parse-cst'
import { Type } from './util'

export const binaryOptions: scalarOptions.Binary
export const boolOptions: scalarOptions.Bool
export const intOptions: scalarOptions.Int
export const nullOptions: scalarOptions.Null
export const strOptions: scalarOptions.Str

export class Schema {
  /** Default: `'tag:yaml.org,2002:'` */
  static defaultPrefix: string
  static defaultTags: {
    /** Default: `'tag:yaml.org,2002:map'` */
    MAP: string
    /** Default: `'tag:yaml.org,2002:seq'` */
    SEQ: string
    /** Default: `'tag:yaml.org,2002:str'` */
    STR: string
  }
  constructor(options: Schema.Options)
  /**
   * Convert any value into a `Node` using this schema, recursively turning
   * objects into collections.
   *
   * @param wrapScalars If `true`, also wraps plain values in `Scalar` objects;
   *   if undefined or `false` and `value` is not an object, it will be returned
   *   directly.
   * @param tag Use to specify the collection type, e.g. `"!!omap"`. Note that
   *   this requires the corresponding tag to be available in this schema.
   */
  createNode(
    value: any,
    wrapScalars?: boolean,
    tag?: string,
    ctx?: Schema.CreateNodeContext
  ): Node
  /**
   * Convert a key and a value into a `Pair` using this schema, recursively
   * wrapping all values as `Scalar` or `Collection` nodes.
   *
   * @param ctx To not wrap scalars, use a context `{ wrapScalars: false }`
   */
  createPair(key: any, value: any, ctx?: Schema.CreateNodeContext): Pair
  merge: boolean
  name: Schema.Name
  sortMapEntries: ((a: Pair, b: Pair) => number) | null
  tags: Schema.Tag[]
}

export namespace Schema {
  type Name = 'core' | 'failsafe' | 'json' | 'yaml-1.1'

  interface Options {
    /**
     * Array of additional tags to include in the schema, or a function that may
     * modify the schema's base tag array.
     */
    customTags?: (TagId | Tag)[] | ((tags: Tag[]) => Tag[])
    /**
     * Enable support for `<<` merge keys.
     *
     * Default: `false` for YAML 1.2, `true` for earlier versions
     */
    merge?: boolean
    /**
     * The base schema to use.
     *
     * Default: `"core"` for YAML 1.2, `"yaml-1.1"` for earlier versions
     */
    schema?: Name
    /**
     * When stringifying, sort map entries. If `true`, sort by comparing key values with `<`.
     *
     * Default: `false`
     */
    sortMapEntries?: boolean | ((a: Pair, b: Pair) => number)
    /**
     * @deprecated Use `customTags` instead.
     */
    tags?: Options['customTags']
  }

  interface CreateNodeContext {
    wrapScalars?: boolean
    [key: string]: any
  }

  interface StringifyContext {
    forceBlockIndent?: boolean
    implicitKey?: boolean
    indent?: string
    indentAtStart?: number
    inFlow?: boolean
    [key: string]: any
  }

  type TagId =
    | 'binary'
    | 'bool'
    | 'float'
    | 'floatExp'
    | 'floatNaN'
    | 'floatTime'
    | 'int'
    | 'intHex'
    | 'intOct'
    | 'intTime'
    | 'null'
    | 'omap'
    | 'pairs'
    | 'set'
    | 'timestamp'

  type Tag = CustomTag | DefaultTag

  interface BaseTag {
    /**
     * An optional factory function, used e.g. by collections when wrapping JS objects as AST nodes.
     */
    createNode?: (
      schema: Schema,
      value: any,
      ctx: Schema.CreateNodeContext
    ) => YAMLMap | YAMLSeq | Scalar
    /**
     * If a tag has multiple forms that should be parsed and/or stringified differently, use `format` to identify them.
     */
    format?: string
    /**
     * Used by `YAML.createNode` to detect your data type, e.g. using `typeof` or
     * `instanceof`.
     */
    identify(value: any): boolean
    /**
     * The `Node` child class that implements this tag. Required for collections and tags that have overlapping JS representations.
     */
    nodeClass?: new () => any
    /**
     * Used by some tags to configure their stringification, where applicable.
     */
    options?: object
    /**
     * Optional function stringifying the AST node in the current context. If your
     * data includes a suitable `.toString()` method, you can probably leave this
     * undefined and use the default stringifier.
     *
     * @param item The node being stringified.
     * @param ctx Contains the stringifying context variables.
     * @param onComment Callback to signal that the stringifier includes the
     *   item's comment in its output.
     * @param onChompKeep Callback to signal that the output uses a block scalar
     *   type with the `+` chomping indicator.
     */
    stringify?: (
      item: Node,
      ctx: Schema.StringifyContext,
      onComment?: () => void,
      onChompKeep?: () => void
    ) => string
    /**
     * The identifier for your data type, with which its stringified form will be
     * prefixed. Should either be a !-prefixed local `!tag`, or a fully qualified
     * `tag:domain,date:foo`.
     */
    tag: string
  }

  interface CustomTag extends BaseTag {
    /**
     * A JavaScript class that should be matched to this tag, e.g. `Date` for `!!timestamp`.
     * @deprecated Use `Tag.identify` instead
     */
    class?: new () => any
    /**
     * Turns a CST node into an AST node. If returning a non-`Node` value, the
     * output will be wrapped as a `Scalar`.
     */
    resolve(doc: Document, cstNode: CST.Node): Node | any
  }

  interface DefaultTag extends BaseTag {
    /**
     * If `true`, together with `test` allows for values to be stringified without
     * an explicit tag. For most cases, it's unlikely that you'll actually want to
     * use this, even if you first think you do.
     */
    default: true
    /**
     * Alternative form used by default tags; called with `test` match results.
     */
    resolve(...match: string[]): Node | any
    /**
     * Together with `default` allows for values to be stringified without an
     * explicit tag and detected using a regular expression. For most cases, it's
     * unlikely that you'll actually want to use these, even if you first think
     * you do.
     */
    test: RegExp
  }
}

export class Node {
  /** A comment on or immediately after this */
  comment?: string | null
  /** A comment before this */
  commentBefore?: string | null
  /** Only available when `keepCstNodes` is set to `true` */
  cstNode?: CST.Node
  /**
   * The [start, end] range of characters of the source parsed
   * into this node (undefined for pairs or if not parsed)
   */
  range?: [number, number] | null
  /** A blank line before this node and its commentBefore */
  spaceBefore?: boolean
  /** A fully qualified tag, if required */
  tag?: string
  /** A plain JS representation of this node */
  toJSON(arg?: any): any
  /** The type of this node */
  type?: Type | Pair.Type
}

export class Scalar extends Node {
  constructor(value: any)
  type?: Scalar.Type
  /**
   * By default (undefined), numbers use decimal notation.
   * The YAML 1.2 core schema only supports 'HEX' and 'OCT'.
   */
  format?: 'BIN' | 'HEX' | 'OCT' | 'TIME'
  value: any
  toJSON(arg?: any, ctx?: AST.NodeToJsonContext): any
  toString(): string
}
export namespace Scalar {
  type Type =
    | Type.BLOCK_FOLDED
    | Type.BLOCK_LITERAL
    | Type.PLAIN
    | Type.QUOTE_DOUBLE
    | Type.QUOTE_SINGLE
}

export class Alias extends Node {
  type: Type.ALIAS
  source: Node
  cstNode?: CST.Alias
  toString(ctx: Schema.StringifyContext): string
}

export class Pair extends Node {
  constructor(key: any, value?: any)
  type: Pair.Type.PAIR | Pair.Type.MERGE_PAIR
  /** Always Node or null when parsed, but can be set to anything. */
  key: any
  /** Always Node or null when parsed, but can be set to anything. */
  value: any
  cstNode?: never // no corresponding cstNode
  toJSON(arg?: any, ctx?: AST.NodeToJsonContext): object | Map<any, any>
  toString(
    ctx?: Schema.StringifyContext,
    onComment?: () => void,
    onChompKeep?: () => void
  ): string
}
export namespace Pair {
  enum Type {
    PAIR = 'PAIR',
    MERGE_PAIR = 'MERGE_PAIR'
  }
}

export class Merge extends Pair {
  type: Pair.Type.MERGE_PAIR
  /** Always Scalar('<<'), defined by the type specification */
  key: AST.PlainValue
  /** Always YAMLSeq<Alias(Map)>, stringified as *A if length = 1 */
  value: YAMLSeq
  toString(ctx?: Schema.StringifyContext, onComment?: () => void): string
}

export class Collection extends Node {
  type?: Type.MAP | Type.FLOW_MAP | Type.SEQ | Type.FLOW_SEQ | Type.DOCUMENT
  items: any[]
  schema?: Schema

  /**
   * Adds a value to the collection. For `!!map` and `!!omap` the value must
   * be a Pair instance or a `{ key, value }` object, which may not have a key
   * that already exists in the map.
   */
  add(value: any): void
  addIn(path: Iterable<any>, value: any): void
  /**
   * Removes a value from the collection.
   * @returns `true` if the item was found and removed.
   */
  delete(key: any): boolean
  deleteIn(path: Iterable<any>): boolean
  /**
   * Returns item at `key`, or `undefined` if not found. By default unwraps
   * scalar values from their surrounding node; to disable set `keepScalar` to
   * `true` (collections are always returned intact).
   */
  get(key: any, keepScalar?: boolean): any
  getIn(path: Iterable<any>, keepScalar?: boolean): any
  /**
   * Checks if the collection includes a value with the key `key`.
   */
  has(key: any): boolean
  hasIn(path: Iterable<any>): boolean
  /**
   * Sets a value in this collection. For `!!set`, `value` needs to be a
   * boolean to add/remove the item from the set.
   */
  set(key: any, value: any): void
  setIn(path: Iterable<any>, value: any): void
}

export class YAMLMap extends Collection {
  type?: Type.FLOW_MAP | Type.MAP
  items: Array<Pair>
  hasAllNullValues(): boolean
  toJSON(arg?: any, ctx?: AST.NodeToJsonContext): object | Map<any, any>
  toString(
    ctx?: Schema.StringifyContext,
    onComment?: () => void,
    onChompKeep?: () => void
  ): string
}

export class YAMLSeq extends Collection {
  type?: Type.FLOW_SEQ | Type.SEQ
  delete(key: number | string | Scalar): boolean
  get(key: number | string | Scalar, keepScalar?: boolean): any
  has(key: number | string | Scalar): boolean
  set(key: number | string | Scalar, value: any): void
  hasAllNullValues(): boolean
  toJSON(arg?: any, ctx?: AST.NodeToJsonContext): any[]
  toString(
    ctx?: Schema.StringifyContext,
    onComment?: () => void,
    onChompKeep?: () => void
  ): string
}

export namespace AST {
  interface NodeToJsonContext {
    anchors?: any[]
    doc: Document
    keep?: boolean
    mapAsMap?: boolean
    maxAliasCount?: number
    onCreate?: (node: Node) => void
    [key: string]: any
  }

  interface BlockFolded extends Scalar {
    type: Type.BLOCK_FOLDED
    cstNode?: CST.BlockFolded
  }

  interface BlockLiteral extends Scalar {
    type: Type.BLOCK_LITERAL
    cstNode?: CST.BlockLiteral
  }

  interface PlainValue extends Scalar {
    type: Type.PLAIN
    cstNode?: CST.PlainValue
  }

  interface QuoteDouble extends Scalar {
    type: Type.QUOTE_DOUBLE
    cstNode?: CST.QuoteDouble
  }

  interface QuoteSingle extends Scalar {
    type: Type.QUOTE_SINGLE
    cstNode?: CST.QuoteSingle
  }

  interface FlowMap extends YAMLMap {
    type: Type.FLOW_MAP
    cstNode?: CST.FlowMap
  }

  interface BlockMap extends YAMLMap {
    type: Type.MAP
    cstNode?: CST.Map
  }

  interface FlowSeq extends YAMLSeq {
    type: Type.FLOW_SEQ
    items: Array<Node>
    cstNode?: CST.FlowSeq
  }

  interface BlockSeq extends YAMLSeq {
    type: Type.SEQ
    items: Array<Node | null>
    cstNode?: CST.Seq
  }
}


code:
const types = require('./dist/types')

exports.binaryOptions = types.binaryOptions
exports.boolOptions = types.boolOptions
exports.intOptions = types.intOptions
exports.nullOptions = types.nullOptions
exports.strOptions = types.strOptions

exports.Schema = types.Schema
exports.Alias = types.Alias
exports.Collection = types.Collection
exports.Merge = types.Merge
exports.Node = types.Node
exports.Pair = types.Pair
exports.Scalar = types.Scalar
exports.YAMLMap = types.YAMLMap
exports.YAMLSeq = types.YAMLSeq

license: mit


code:
import types from './dist/types.js'

export const binaryOptions = types.binaryOptions
export const boolOptions = types.boolOptions
export const intOptions = types.intOptions
export const nullOptions = types.nullOptions
export const strOptions = types.strOptions

export const Schema = types.Schema
export const Alias = types.Alias
export const Collection = types.Collection
export const Merge = types.Merge
export const Node = types.Node
export const Pair = types.Pair
export const Scalar = types.Scalar
export const YAMLMap = types.YAMLMap
export const YAMLSeq = types.YAMLSeq


code:
'use strict'
Object.defineProperty(exports, '__esModule', { value: true })

const legacy = require('../dist/legacy-exports')
exports.binary = legacy.binary
exports.default = [exports.binary]

legacy.warnFileDeprecation(__filename)


code:
const legacy = require('../dist/legacy-exports')
module.exports = legacy.omap
legacy.warnFileDeprecation(__filename)


code:
const legacy = require('../dist/legacy-exports')
module.exports = legacy.pairs
legacy.warnFileDeprecation(__filename)


code:
const legacy = require('../dist/legacy-exports')
module.exports = legacy.set
legacy.warnFileDeprecation(__filename)


code:
'use strict'
Object.defineProperty(exports, '__esModule', { value: true })

const legacy = require('../dist/legacy-exports')
exports.default = [legacy.intTime, legacy.floatTime, legacy.timestamp]
exports.floatTime = legacy.floatTime
exports.intTime = legacy.intTime
exports.timestamp = legacy.timestamp

legacy.warnFileDeprecation(__filename)


code:
import { Document } from './index'
import { CST } from './parse-cst'
import { AST, Pair, Scalar, Schema } from './types'

export function findPair(items: any[], key: Scalar | any): Pair | undefined

export function parseMap(doc: Document, cst: CST.Map): AST.BlockMap
export function parseMap(doc: Document, cst: CST.FlowMap): AST.FlowMap
export function parseSeq(doc: Document, cst: CST.Seq): AST.BlockSeq
export function parseSeq(doc: Document, cst: CST.FlowSeq): AST.FlowSeq

export function stringifyNumber(item: Scalar): string
export function stringifyString(
  item: Scalar,
  ctx: Schema.StringifyContext,
  onComment?: () => void,
  onChompKeep?: () => void
): string

export function toJSON(
  value: any,
  arg?: any,
  ctx?: Schema.CreateNodeContext
): any

export enum Type {
  ALIAS = 'ALIAS',
  BLANK_LINE = 'BLANK_LINE',
  BLOCK_FOLDED = 'BLOCK_FOLDED',
  BLOCK_LITERAL = 'BLOCK_LITERAL',
  COMMENT = 'COMMENT',
  DIRECTIVE = 'DIRECTIVE',
  DOCUMENT = 'DOCUMENT',
  FLOW_MAP = 'FLOW_MAP',
  FLOW_SEQ = 'FLOW_SEQ',
  MAP = 'MAP',
  MAP_KEY = 'MAP_KEY',
  MAP_VALUE = 'MAP_VALUE',
  PLAIN = 'PLAIN',
  QUOTE_DOUBLE = 'QUOTE_DOUBLE',
  QUOTE_SINGLE = 'QUOTE_SINGLE',
  SEQ = 'SEQ',
  SEQ_ITEM = 'SEQ_ITEM'
}

interface LinePos {
  line: number
  col: number
}

export class YAMLError extends Error {
  name:
    | 'YAMLReferenceError'
    | 'YAMLSemanticError'
    | 'YAMLSyntaxError'
    | 'YAMLWarning'
  message: string
  source?: CST.Node

  nodeType?: Type
  range?: CST.Range
  linePos?: { start: LinePos; end: LinePos }

  /**
   * Drops `source` and adds `nodeType`, `range` and `linePos`, as well as
   * adding details to `message`. Run automatically for document errors if
   * the `prettyErrors` option is set.
   */
  makePretty(): void
}

export class YAMLReferenceError extends YAMLError {
  name: 'YAMLReferenceError'
}

export class YAMLSemanticError extends YAMLError {
  name: 'YAMLSemanticError'
}

export class YAMLSyntaxError extends YAMLError {
  name: 'YAMLSyntaxError'
}

export class YAMLWarning extends YAMLError {
  name: 'YAMLWarning'
}


code:
const util = require('./dist/util')

exports.findPair = util.findPair
exports.toJSON = util.toJSON
exports.parseMap = util.parseMap
exports.parseSeq = util.parseSeq

exports.stringifyNumber = util.stringifyNumber
exports.stringifyString = util.stringifyString
exports.Type = util.Type

exports.YAMLError = util.YAMLError
exports.YAMLReferenceError = util.YAMLReferenceError
exports.YAMLSemanticError = util.YAMLSemanticError
exports.YAMLSyntaxError = util.YAMLSyntaxError
exports.YAMLWarning = util.YAMLWarning


code:
import util from './dist/util.js'

export const findPair = util.findPair
export const toJSON = util.toJSON

export const parseMap = util.parseMap
export const parseSeq = util.parseSeq

export const stringifyNumber = util.stringifyNumber
export const stringifyString = util.stringifyString

export const Type = util.Type

export const YAMLError = util.YAMLError
export const YAMLReferenceError = util.YAMLReferenceError
export const YAMLSemanticError = util.YAMLSemanticError
export const YAMLSyntaxError = util.YAMLSyntaxError
export const YAMLWarning = util.YAMLWarning


code:
.DS_Store
node_modules
/doc/

/lib/debug/


code:
language: node_js
node_js:
  - "5.0"
before_script:
  - npm install -g coffee-script
  - npm install -g browserify
  - npm install -g uglify-js


code:
{exec, spawn}   = require 'child_process'
fs              = require 'fs'
path            = require 'path'
esc             = (arg) -> (''+arg).replace(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/gm, '\\').replace(/\n/g, "'\n'").replace(/^$/, "''")

srcDir = path.normalize __dirname+'/src'
libDir = path.normalize __dirname+'/lib'
libDebugDir = path.normalize __dirname+'/lib/debug'
distDir = path.normalize __dirname+'/dist'
cliDir = path.normalize __dirname+'/cli'
binDir = path.normalize __dirname+'/bin'
specDir = path.normalize __dirname+'/test/spec'
modulesDir = path.normalize __dirname+'/node_modules'

task 'build', 'build project', ->

    # Compile
    do compile = ->
        unless fs.existsSync libDir
            fs.mkdirSync libDir
        unless fs.existsSync libDir+'/Exception'
            fs.mkdirSync libDir+'/Exception'
        toCompile = 'Yaml Utils Unescaper Pattern Parser Inline Escaper Dumper Exception/ParseException Exception/ParseMore Exception/DumpException'.split ' '
        do compileOne = ->
            name = toCompile.shift()
            outputDir = (if '/' in name then libDir+'/Exception' else libDir)
            exec 'coffee -b -o '+esc(outputDir)+' -c '+esc(srcDir+'/'+name+'.coffee'), (err, res) ->
                if err then throw err

                console.log "Compiled #{name}.js"
                if toCompile.length
                    compileOne()
                else
                    debugCompile()

    # Debug compile
    debugCompile = ->
        unless fs.existsSync libDebugDir
            fs.mkdirSync libDebugDir
        unless fs.existsSync libDebugDir+'/Exception'
            fs.mkdirSync libDebugDir+'/Exception'
        toCompile = 'Yaml Utils Unescaper Pattern Parser Inline Escaper Dumper Exception/ParseException Exception/ParseMore Exception/DumpException'.split ' '
        do compileOne = ->
            name = toCompile.shift()
            outputDir = (if '/' in name then libDebugDir+'/Exception' else libDebugDir)
            exec 'coffee -m -b -o '+esc(outputDir)+' -c '+esc(srcDir+'/'+name+'.coffee'), (err, res) ->
                if err then throw err

                console.log "Compiled #{name}.js (debug)"
                if toCompile.length
                    compileOne()
                else
                    browserify()

    # Browserify
    unless fs.existsSync distDir
        fs.mkdirSync distDir
    browserify = ->
        exec 'browserify -t coffeeify --extension=".coffee" '+esc(srcDir+'/Yaml.coffee')+' > '+esc(distDir+'/yaml.js'), (err, res) ->
            if err then throw err

            console.log "Browserified yaml.js"
            exec 'browserify --debug -t coffeeify --extension=".coffee" '+esc(srcDir+'/Yaml.coffee')+' > '+esc(distDir+'/yaml.debug.js'), (err, res) ->
                if err then throw err

                console.log "Browserified yaml.js (debug)"
                minify()

    # Minify
    minify = ->
        exec 'uglifyjs --mangle sort '+esc(distDir+'/yaml.js')+' > '+esc(distDir+'/yaml.min.js'), (err, res) ->
            if err then throw err

            console.log "Minified yaml.min.js"
            compileSpec()

    # Compile spec
    compileSpec = ->
        exec 'coffee -b -c '+esc(specDir+'/YamlSpec.coffee'), (err, res) ->
            if err then throw err

            console.log "Compiled YamlSpec.js"
            compileCLI()

    # Compile CLI
    compileCLI = ->
        unless fs.existsSync binDir
            fs.mkdirSync binDir

        # yaml2json
        str = fs.readFileSync cliDir+'/yaml2json.js'
        str = "#!/usr/bin/env node\n" + str
        fs.writeFileSync binDir+'/yaml2json', str
        fs.chmodSync binDir+'/yaml2json', '755'
        console.log "Bundled yaml2json"

        # json2yaml
        str = fs.readFileSync cliDir+'/json2yaml.js'
        str = "#!/usr/bin/env node\n" + str
        fs.writeFileSync binDir+'/json2yaml', str
        fs.chmodSync binDir+'/json2yaml', '755'
        console.log "Bundled json2yaml"

task 'test', 'test project', ->

    # Test
    spawn 'node', [modulesDir+'/jasmine-node/lib/jasmine-node/cli.js', '--verbose', '--coffee', specDir+'/YamlSpec.coffee'], stdio: "inherit"

task 'doc', 'generate documentation', ->

    # Generate
    spawn 'codo', [srcDir], stdio: "inherit"


code:
yaml.js
=======

![Build status](https://travis-ci.org/jeremyfa/yaml.js.svg?branch=develop)

Standalone JavaScript YAML 1.2 Parser & Encoder. Works under node.js and all major browsers. Also brings command line YAML/JSON conversion tools.

Mainly inspired from [Symfony Yaml Component](https://github.com/symfony/Yaml).

How to use
----------

Import yaml.js in your html page:

``` html
<script type="text/javascript" src="yaml.js"></script>
```

Parse yaml string:

``` js
nativeObject = YAML.parse(yamlString);
```

Dump native object into yaml string:

``` js
yamlString = YAML.stringify(nativeObject[, inline /* @integer depth to start using inline notation at */[, spaces /* @integer number of spaces to use for indentation */] ]);
```

Load yaml file:

``` js
nativeObject = YAML.load('file.yml');
```

Load yaml file:

``` js
YAML.load('file.yml', function(result)
{
    nativeObject = result;
});
```

Use with node.js
----------------

Install module:

``` bash
npm install yamljs
```

Use it:

``` js
YAML = require('yamljs');

// parse YAML string
nativeObject = YAML.parse(yamlString);

// Generate YAML
yamlString = YAML.stringify(nativeObject, 4);

// Load yaml file using YAML.load
nativeObject = YAML.load('myfile.yml');
```

Command line tools
------------------

You can enable the command line tools by installing yamljs as a global module:

``` bash
npm install -g yamljs
```

Then, two cli commands should become available: **yaml2json** and **json2yaml**. They let you convert YAML to JSON and JSON to YAML very easily.

**yaml2json**

```
usage: yaml2json [-h] [-v] [-p] [-i INDENTATION] [-s] [-r] [-w] input

Positional arguments:
  input                 YAML file or directory containing YAML files.

Optional arguments:
  -h, --help            Show this help message and exit.
  -v, --version         Show program's version number and exit.
  -p, --pretty          Output pretty (indented) JSON.
  -i INDENTATION, --indentation INDENTATION
                        Number of space characters used to indent code (use
                        with --pretty, default: 2).
  -s, --save            Save output inside JSON file(s) with the same name.
  -r, --recursive       If the input is a directory, also find YAML files in
                        sub-directories recursively.
  -w, --watch           Watch for changes.
```

**json2yaml**

```
usage: json2yaml [-h] [-v] [-d DEPTH] [-i INDENTATION] [-s] [-r] [-w] input

Positional arguments:
  input                 JSON file or directory containing JSON files.

Optional arguments:
  -h, --help            Show this help message and exit.
  -v, --version         Show program's version number and exit.
  -d DEPTH, --depth DEPTH
                        Set minimum level of depth before generating inline
                        YAML (default: 2).
  -i INDENTATION, --indentation INDENTATION
                        Number of space characters used to indent code
                        (default: 2).
  -s, --save            Save output inside YML file(s) with the same name.
  -r, --recursive       If the input is a directory, also find JSON files in
                        sub-directories recursively.
  -w, --watch           Watch for changes.
```

**examples**

``` bash
# Convert YAML to JSON and output resulting JSON on the console
yaml2json myfile.yml

# Store output inside a JSON file
yaml2json myfile.yml > output.json

# Output "pretty" (indented) JSON
yaml2json myfile.yml --pretty

# Save the output inside a file called myfile.json
yaml2json myfile.yml --pretty --save

# Watch a full directory and convert any YAML file into its JSON equivalent
yaml2json mydirectory --pretty --save --recursive

# Convert JSON to YAML and store output inside a JSON file
json2yaml myfile.json > output.yml

# Output YAML that will be inlined only after 8 levels of indentation
json2yaml myfile.json --depth 8

# Save the output inside a file called myfile.json with 4 spaces for each indentation
json2yaml myfile.json --indentation 4

# Watch a full directory and convert any JSON file into its YAML equivalent
json2yaml mydirectory --pretty --save --recursive


code:
#!/usr/bin/env node

/**
 * yaml2json cli program
 */

var YAML = require('../lib/Yaml.js');

var ArgumentParser = require('argparse').ArgumentParser;
var cli = new ArgumentParser({
    prog:           "json2yaml",
    version:        require('../package.json').version,
    addHelp:        true
});

cli.addArgument(
    ['-d', '--depth'],
    {
        action: 'store',
        type:   'int',
        help:   'Set minimum level of depth before generating inline YAML (default: 2).'
    }
);

cli.addArgument(
    ['-i', '--indentation'],
    {
        action: 'store',
        type:   'int',
        help:   'Number of space characters used to indent code (default: 2).',
    }
);

cli.addArgument(
    ['-s', '--save'],
    {
        help:   'Save output inside YML file(s) with the same name.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-r', '--recursive'],
    {
        help:   'If the input is a directory, also find JSON files in sub-directories recursively.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-w', '--watch'],
    {
        help:   'Watch for changes.',
        action: 'storeTrue'
    }
);

cli.addArgument(['input'], {
    help:   'JSON file or directory containing JSON files or - to read JSON from stdin.'
});

try {
    var options = cli.parseArgs();
    var path = require('path');
    var fs   = require('fs');
    var glob = require('glob');

    var rootPath = process.cwd();
    var parsePath = function(input) {
        if (input == '-') return '-';
        var output;
        if (!(input != null)) {
            return rootPath;
        }
        output = path.normalize(input);
        if (output.length === 0) {
            return rootPath;
        }
        if (output.charAt(0) !== '/') {
            output = path.normalize(rootPath + '/./' + output);
        }
        if (output.length > 1 && output.charAt(output.length - 1) === '/') {
            return output.substr(0, output.length - 1);
        }
        return output;
    };

    // Find files
    var findFiles = function(input) {
        if (input != '-' && input != null) {
            var isDirectory = fs.statSync(input).isDirectory();
            var files = [];

            if (!isDirectory) {
                files.push(input);
            }
            else {
                if (options.recursive) {
                    files = files.concat(glob.sync(input+'/**/*.json'));
                }
                else {
                    files = files.concat(glob.sync(input+'/*.json'));
                }
            }

            return files;
        }
        return null;
    };

    // Convert to JSON
    var convertToYAML = function(input, inline, save, spaces, str) {
        var yaml;
        if (inline == null) inline = 2;
        if (spaces == null) spaces = 2;

        if (str == null) {
            str = ''+fs.readFileSync(input);
        }
        yaml = YAML.dump(JSON.parse(str), inline, spaces);

        if (!save || input == null) {
            // Ouput result
            process.stdout.write(yaml);
        }
        else {
            var output;
            if (input.substring(input.length-5) == '.json') {
                output = input.substr(0, input.length-5) + '.yaml';
            }
            else {
                output = input + '.yaml';
            }

            // Write file
            var file = fs.openSync(output, 'w+');
            fs.writeSync(file, yaml);
            fs.closeSync(file);
            process.stdout.write("saved "+output+"\n");
        }
    };

    var input = parsePath(options.input);
    var mtimes = [];

    var runCommand = function() {
        try {
            var files = findFiles(input);
            if (files != null) {
                var len = files.length;
                for (var i = 0; i < len; i++) {
                    var file = files[i];
                    var stat = fs.statSync(file);
                    var time = stat.mtime.getTime();
                    if (!stat.isDirectory()) {
                        if (!mtimes[file] || mtimes[file] < time) {
                            mtimes[file] = time;
                            convertToYAML(file, options.depth, options.save, options.indentation);
                        }
                    }
                }
            } else {
                // Read from STDIN
                var stdin = process.openStdin();
                var data = "";
                stdin.on('data', function(chunk) {
                    data += chunk;
                });
                stdin.on('end', function() {
                    convertToYAML(null, options.depth, options.save, options.indentation, data);
                });
            }
        } catch (e) {
            process.stderr.write((e.message ? e.message : e)+"\n");
        }
    };

    if (!options.watch) {
        runCommand();
    } else {
        runCommand();
        setInterval(runCommand, 1000);
    }
} catch (e) {
    process.stderr.write((e.message ? e.message : e)+"\n");
}


code:
#!/usr/bin/env node

/**
 * yaml2json cli program
 */

var YAML = require('../lib/Yaml.js');

var ArgumentParser = require('argparse').ArgumentParser;
var cli = new ArgumentParser({
    prog:           "yaml2json",
    version:        require('../package.json').version,
    addHelp:        true
});

cli.addArgument(
    ['-p', '--pretty'],
    {
        help:   'Output pretty (indented) JSON.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-i', '--indentation'],
    {
        action: 'store',
        type:   'int',
        help:   'Number of space characters used to indent code (use with --pretty, default: 2).',
    }
);

cli.addArgument(
    ['-s', '--save'],
    {
        help:   'Save output inside JSON file(s) with the same name.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-r', '--recursive'],
    {
        help:   'If the input is a directory, also find YAML files in sub-directories recursively.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-w', '--watch'],
    {
        help:   'Watch for changes.',
        action: 'storeTrue'
    }
);

cli.addArgument(['input'], {
    help:   'YAML file or directory containing YAML files or - to read YAML from stdin.'
});

try {
    var options = cli.parseArgs();
    var path = require('path');
    var fs   = require('fs');
    var glob = require('glob');

    var rootPath = process.cwd();
    var parsePath = function(input) {
        if (input == '-') return '-';
        var output;
        if (!(input != null)) {
            return rootPath;
        }
        output = path.normalize(input);
        if (output.length === 0) {
            return rootPath;
        }
        if (output.charAt(0) !== '/') {
            output = path.normalize(rootPath + '/./' + output);
        }
        if (output.length > 1 && output.charAt(output.length - 1) === '/') {
            return output.substr(0, output.length - 1);
        }
        return output;
    };

    // Find files
    var findFiles = function(input) {
        if (input != '-' && input != null) {
            var isDirectory = fs.statSync(input).isDirectory();
            var files = [];

            if (!isDirectory) {
                files.push(input);
            }
            else {
                if (options.recursive) {
                    files = files.concat(glob.sync(input+'/**/*.yml'));
                    files = files.concat(glob.sync(input+'/**/*.yaml'));
                }
                else {
                    files = files.concat(glob.sync(input+'/*.yml'));
                    files = files.concat(glob.sync(input+'/*.yaml'));
                }
            }

            return files;
        }
        return null;
    };

    // Convert to JSON
    var convertToJSON = function(input, pretty, save, spaces, str) {
        var json;
        if (spaces == null) spaces = 2;
        if (str != null) {
            if (pretty) {
                json = JSON.stringify(YAML.parse(str), null, spaces);
            }
            else {
                json = JSON.stringify(YAML.parse(str));
            }
        } else {
            if (pretty) {
                json = JSON.stringify(YAML.parseFile(input), null, spaces);
            }
            else {
                json = JSON.stringify(YAML.parseFile(input));
            }
        }

        if (!save || input == null) {
            // Ouput result
            process.stdout.write(json+"\n");
        }
        else {
            var output;
            if (input.substring(input.length-4) == '.yml') {
                output = input.substr(0, input.length-4) + '.json';
            }
            else if (input.substring(input.length-5) == '.yaml') {
                output = input.substr(0, input.length-5) + '.json';
            }
            else {
                output = input + '.json';
            }

            // Write file
            var file = fs.openSync(output, 'w+');
            fs.writeSync(file, json);
            fs.closeSync(file);
            process.stdout.write("saved "+output+"\n");
        }
    };

    var input = parsePath(options.input);
    var mtimes = [];

    var runCommand = function() {
        try {
            var files = findFiles(input);
            if (files != null) {
                var len = files.length;

                for (var i = 0; i < len; i++) {
                    var file = files[i];
                    var stat = fs.statSync(file);
                    var time = stat.mtime.getTime();
                    if (!stat.isDirectory()) {
                        if (!mtimes[file] || mtimes[file] < time) {
                            mtimes[file] = time;
                            convertToJSON(file, options.pretty, options.save, options.indentation);
                        }
                    }
                }
            } else {
                // Read from STDIN
                var stdin = process.openStdin();
                var data = "";
                stdin.on('data', function(chunk) {
                    data += chunk;
                });
                stdin.on('end', function() {
                    convertToJSON(null, options.pretty, options.save, options.indentation, data);
                });
            }
        } catch (e) {
            process.stderr.write((e.message ? e.message : e)+"\n");
        }
    };

    if (!options.watch) {
        runCommand();
    } else {
        runCommand();
        setInterval(runCommand, 1000);
    }
} catch (e) {
    process.stderr.write((e.message ? e.message : e)+"\n");
}


yaml.js

description: Standalone JavaScript YAML 1.2 Parser & Encoder. Works under node.js and all major browsers. Also brings command line YAML/JSON conversion tools.

license: MIT


code:
/**
 * yaml2json cli program
 */

var YAML = require('../lib/Yaml.js');

var ArgumentParser = require('argparse').ArgumentParser;
var cli = new ArgumentParser({
    prog:           "json2yaml",
    version:        require('../package.json').version,
    addHelp:        true
});

cli.addArgument(
    ['-d', '--depth'],
    {
        action: 'store',
        type:   'int',
        help:   'Set minimum level of depth before generating inline YAML (default: 2).'
    }
);

cli.addArgument(
    ['-i', '--indentation'],
    {
        action: 'store',
        type:   'int',
        help:   'Number of space characters used to indent code (default: 2).',
    }
);

cli.addArgument(
    ['-s', '--save'],
    {
        help:   'Save output inside YML file(s) with the same name.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-r', '--recursive'],
    {
        help:   'If the input is a directory, also find JSON files in sub-directories recursively.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-w', '--watch'],
    {
        help:   'Watch for changes.',
        action: 'storeTrue'
    }
);

cli.addArgument(['input'], {
    help:   'JSON file or directory containing JSON files or - to read JSON from stdin.'
});

try {
    var options = cli.parseArgs();
    var path = require('path');
    var fs   = require('fs');
    var glob = require('glob');

    var rootPath = process.cwd();
    var parsePath = function(input) {
        if (input == '-') return '-';
        var output;
        if (!(input != null)) {
            return rootPath;
        }
        output = path.normalize(input);
        if (output.length === 0) {
            return rootPath;
        }
        if (output.charAt(0) !== '/') {
            output = path.normalize(rootPath + '/./' + output);
        }
        if (output.length > 1 && output.charAt(output.length - 1) === '/') {
            return output.substr(0, output.length - 1);
        }
        return output;
    };

    // Find files
    var findFiles = function(input) {
        if (input != '-' && input != null) {
            var isDirectory = fs.statSync(input).isDirectory();
            var files = [];

            if (!isDirectory) {
                files.push(input);
            }
            else {
                if (options.recursive) {
                    files = files.concat(glob.sync(input+'/**/*.json'));
                }
                else {
                    files = files.concat(glob.sync(input+'/*.json'));
                }
            }

            return files;
        }
        return null;
    };

    // Convert to JSON
    var convertToYAML = function(input, inline, save, spaces, str) {
        var yaml;
        if (inline == null) inline = 2;
        if (spaces == null) spaces = 2;

        if (str == null) {
            str = ''+fs.readFileSync(input);
        }
        yaml = YAML.dump(JSON.parse(str), inline, spaces);

        if (!save || input == null) {
            // Ouput result
            process.stdout.write(yaml);
        }
        else {
            var output;
            if (input.substring(input.length-5) == '.json') {
                output = input.substr(0, input.length-5) + '.yaml';
            }
            else {
                output = input + '.yaml';
            }

            // Write file
            var file = fs.openSync(output, 'w+');
            fs.writeSync(file, yaml);
            fs.closeSync(file);
            process.stdout.write("saved "+output+"\n");
        }
    };

    var input = parsePath(options.input);
    var mtimes = [];

    var runCommand = function() {
        try {
            var files = findFiles(input);
            if (files != null) {
                var len = files.length;
                for (var i = 0; i < len; i++) {
                    var file = files[i];
                    var stat = fs.statSync(file);
                    var time = stat.mtime.getTime();
                    if (!stat.isDirectory()) {
                        if (!mtimes[file] || mtimes[file] < time) {
                            mtimes[file] = time;
                            convertToYAML(file, options.depth, options.save, options.indentation);
                        }
                    }
                }
            } else {
                // Read from STDIN
                var stdin = process.openStdin();
                var data = "";
                stdin.on('data', function(chunk) {
                    data += chunk;
                });
                stdin.on('end', function() {
                    convertToYAML(null, options.depth, options.save, options.indentation, data);
                });
            }
        } catch (e) {
            process.stderr.write((e.message ? e.message : e)+"\n");
        }
    };

    if (!options.watch) {
        runCommand();
    } else {
        runCommand();
        setInterval(runCommand, 1000);
    }
} catch (e) {
    process.stderr.write((e.message ? e.message : e)+"\n");
}


code:
/**
 * yaml2json cli program
 */

var YAML = require('../lib/Yaml.js');

var ArgumentParser = require('argparse').ArgumentParser;
var cli = new ArgumentParser({
    prog:           "yaml2json",
    version:        require('../package.json').version,
    addHelp:        true
});

cli.addArgument(
    ['-p', '--pretty'],
    {
        help:   'Output pretty (indented) JSON.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-i', '--indentation'],
    {
        action: 'store',
        type:   'int',
        help:   'Number of space characters used to indent code (use with --pretty, default: 2).',
    }
);

cli.addArgument(
    ['-s', '--save'],
    {
        help:   'Save output inside JSON file(s) with the same name.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-r', '--recursive'],
    {
        help:   'If the input is a directory, also find YAML files in sub-directories recursively.',
        action: 'storeTrue'
    }
);

cli.addArgument(
    ['-w', '--watch'],
    {
        help:   'Watch for changes.',
        action: 'storeTrue'
    }
);

cli.addArgument(['input'], {
    help:   'YAML file or directory containing YAML files or - to read YAML from stdin.'
});

try {
    var options = cli.parseArgs();
    var path = require('path');
    var fs   = require('fs');
    var glob = require('glob');

    var rootPath = process.cwd();
    var parsePath = function(input) {
        if (input == '-') return '-';
        var output;
        if (!(input != null)) {
            return rootPath;
        }
        output = path.normalize(input);
        if (output.length === 0) {
            return rootPath;
        }
        if (output.charAt(0) !== '/') {
            output = path.normalize(rootPath + '/./' + output);
        }
        if (output.length > 1 && output.charAt(output.length - 1) === '/') {
            return output.substr(0, output.length - 1);
        }
        return output;
    };

    // Find files
    var findFiles = function(input) {
        if (input != '-' && input != null) {
            var isDirectory = fs.statSync(input).isDirectory();
            var files = [];

            if (!isDirectory) {
                files.push(input);
            }
            else {
                if (options.recursive) {
                    files = files.concat(glob.sync(input+'/**/*.yml'));
                    files = files.concat(glob.sync(input+'/**/*.yaml'));
                }
                else {
                    files = files.concat(glob.sync(input+'/*.yml'));
                    files = files.concat(glob.sync(input+'/*.yaml'));
                }
            }

            return files;
        }
        return null;
    };

    // Convert to JSON
    var convertToJSON = function(input, pretty, save, spaces, str) {
        var json;
        if (spaces == null) spaces = 2;
        if (str != null) {
            if (pretty) {
                json = JSON.stringify(YAML.parse(str), null, spaces);
            }
            else {
                json = JSON.stringify(YAML.parse(str));
            }
        } else {
            if (pretty) {
                json = JSON.stringify(YAML.parseFile(input), null, spaces);
            }
            else {
                json = JSON.stringify(YAML.parseFile(input));
            }
        }

        if (!save || input == null) {
            // Ouput result
            process.stdout.write(json+"\n");
        }
        else {
            var output;
            if (input.substring(input.length-4) == '.yml') {
                output = input.substr(0, input.length-4) + '.json';
            }
            else if (input.substring(input.length-5) == '.yaml') {
                output = input.substr(0, input.length-5) + '.json';
            }
            else {
                output = input + '.json';
            }

            // Write file
            var file = fs.openSync(output, 'w+');
            fs.writeSync(file, json);
            fs.closeSync(file);
            process.stdout.write("saved "+output+"\n");
        }
    };

    var input = parsePath(options.input);
    var mtimes = [];

    var runCommand = function() {
        try {
            var files = findFiles(input);
            if (files != null) {
                var len = files.length;

                for (var i = 0; i < len; i++) {
                    var file = files[i];
                    var stat = fs.statSync(file);
                    var time = stat.mtime.getTime();
                    if (!stat.isDirectory()) {
                        if (!mtimes[file] || mtimes[file] < time) {
                            mtimes[file] = time;
                            convertToJSON(file, options.pretty, options.save, options.indentation);
                        }
                    }
                }
            } else {
                // Read from STDIN
                var stdin = process.openStdin();
                var data = "";
                stdin.on('data', function(chunk) {
                    data += chunk;
                });
                stdin.on('end', function() {
                    convertToJSON(null, options.pretty, options.save, options.indentation, data);
                });
            }
        } catch (e) {
            process.stderr.write((e.message ? e.message : e)+"\n");
        }
    };

    if (!options.watch) {
        runCommand();
    } else {
        runCommand();
        setInterval(runCommand, 1000);
    }
} catch (e) {
    process.stderr.write((e.message ? e.message : e)+"\n");
}


code:
<!DOCTYPE html>

	<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

	<title>yaml.js demo</title>

<form action="" onsubmit="return false;">
	<textarea name="yaml" id="yaml" cols="70" rows="20">--- !clarkevans.com/^invoice
invoice: 34843
date   : 2001-01-23
bill-to: &id001
    given  : Chris
    family : Dumars
    address:
        lines: |
            458 Walkman Dr.
            Suite #292
        city    : Royal Oak
        state   : MI
        postal  : 48046
ship-to: *id001
product:
    - sku         : "BL394D"
      quantity    : 4
      description : Basketball
      price       : 450.00
    - sku         : BL4438H
      quantity    : 1
      description : Super Hoop
      price       : 2392.00
tax  : 251.42
total: 4443.52
comments: >
    Late afternoon is best.
    Backup contact is Nancy
    Billsmer @ 338-4338.
</textarea>
<input type="button" id="parse" name="parse" value="Parse »" onclick="document.getElementById('result').innerHTML='
'+JSON.stringify(YAML.parse(document.getElementById('yaml').value), null, 4)+'
'" />

</form>