From 1d913218e9ab89f578e420db867b753e3fa3de90 Mon Sep 17 00:00:00 2001 From: Simon Lydell Date: Tue, 17 Sep 2013 18:02:25 +0200 Subject: [PATCH] Add `source` property to `position` This allows for source map generation when multiple source files are used to create a single output file. It could something simple as concatenating several files, or something more complex such as joining rules with the same selector. --- Readme.md | 3 ++ index.js | 3 +- test/cases/charset.json | 12 ++++--- test/cases/colon-space.json | 9 ++++-- test/cases/comment.json | 27 ++++++++++------ test/cases/comment.url.json | 21 ++++++++---- test/cases/document.json | 15 ++++++--- test/cases/import.json | 15 ++++++--- test/cases/import.messed.json | 15 ++++++--- test/cases/keyframes.complex.json | 33 ++++++++++++------- test/cases/keyframes.json | 27 ++++++++++------ test/cases/keyframes.messed.json | 15 ++++++--- test/cases/keyframes.vendor.json | 15 ++++++--- test/cases/media.json | 54 ++++++++++++++++++++----------- test/cases/media.messed.json | 42 ++++++++++++++++-------- test/cases/messed-up.json | 24 +++++++++----- test/cases/namespace.json | 6 ++-- test/cases/no-semi.json | 9 ++++-- test/cases/paged-media.json | 18 +++++++---- test/cases/props.json | 12 ++++--- test/cases/quoted.json | 6 ++-- test/cases/rule.json | 6 ++-- test/cases/rules.json | 12 ++++--- test/cases/supports.json | 18 +++++++---- test/cases/wtf.json | 9 ++++-- test/css-parse.js | 2 +- 26 files changed, 286 insertions(+), 142 deletions(-) diff --git a/Readme.md b/Readme.md index 1c05b32..30f5579 100644 --- a/Readme.md +++ b/Readme.md @@ -104,6 +104,9 @@ parse tree with `.position` enabled: } ``` +If you also pass in `source: 'path/to/original.css'`, that will be set +on `node.position.source`. + ## Performance Parsed 15,000 lines of CSS (2mb) in 40ms on my macbook air. diff --git a/index.js b/index.js index 944865b..789a695 100644 --- a/index.js +++ b/index.js @@ -31,7 +31,8 @@ module.exports = function(css, options){ return function(node){ node.position = { start: start, - end: { line: lineno, column: column } + end: { line: lineno, column: column }, + source: options.source }; whitespace(); diff --git a/test/cases/charset.json b/test/cases/charset.json index f7d72ab..7f8eafa 100644 --- a/test/cases/charset.json +++ b/test/cases/charset.json @@ -13,7 +13,8 @@ "end": { "line": 1, "column": 18 - } + }, + "source": "charset.css" } }, { @@ -27,7 +28,8 @@ "end": { "line": 1, "column": 82 - } + }, + "source": "charset.css" } }, { @@ -41,7 +43,8 @@ "end": { "line": 2, "column": 24 - } + }, + "source": "charset.css" } }, { @@ -55,7 +58,8 @@ "end": { "line": 2, "column": 122 - } + }, + "source": "charset.css" } } ] diff --git a/test/cases/colon-space.json b/test/cases/colon-space.json index c8fe10d..607ad36 100644 --- a/test/cases/colon-space.json +++ b/test/cases/colon-space.json @@ -20,7 +20,8 @@ "end": { "line": 2, "column": 19 - } + }, + "source": "colon-space.css" } }, { @@ -35,7 +36,8 @@ "end": { "line": 3, "column": 16 - } + }, + "source": "colon-space.css" } } ], @@ -47,7 +49,8 @@ "end": { "line": 4, "column": 2 - } + }, + "source": "colon-space.css" } } ] diff --git a/test/cases/comment.json b/test/cases/comment.json index 5459552..ba281b6 100644 --- a/test/cases/comment.json +++ b/test/cases/comment.json @@ -13,7 +13,8 @@ "end": { "line": 1, "column": 8 - } + }, + "source": "comment.css" } }, { @@ -33,7 +34,8 @@ "end": { "line": 3, "column": 15 - } + }, + "source": "comment.css" } }, { @@ -47,7 +49,8 @@ "end": { "line": 4, "column": 10 - } + }, + "source": "comment.css" } }, { @@ -61,7 +64,8 @@ "end": { "line": 5, "column": 7 - } + }, + "source": "comment.css" } }, { @@ -76,7 +80,8 @@ "end": { "line": 5, "column": 17 - } + }, + "source": "comment.css" } }, { @@ -90,7 +95,8 @@ "end": { "line": 6, "column": 10 - } + }, + "source": "comment.css" } } ], @@ -102,7 +108,8 @@ "end": { "line": 7, "column": 2 - } + }, + "source": "comment.css" } }, { @@ -116,7 +123,8 @@ "end": { "line": 7, "column": 10 - } + }, + "source": "comment.css" } }, { @@ -130,7 +138,8 @@ "end": { "line": 9, "column": 8 - } + }, + "source": "comment.css" } } ] diff --git a/test/cases/comment.url.json b/test/cases/comment.url.json index 12c6f46..eb00189 100644 --- a/test/cases/comment.url.json +++ b/test/cases/comment.url.json @@ -13,7 +13,8 @@ "end": { "line": 1, "column": 34 - } + }, + "source": "comment.url.css" } }, { @@ -27,7 +28,8 @@ "end": { "line": 2, "column": 5 - } + }, + "source": "comment.url.css" } }, { @@ -47,7 +49,8 @@ "end": { "line": 4, "column": 12 - } + }, + "source": "comment.url.css" } }, { @@ -61,7 +64,8 @@ "end": { "line": 5, "column": 18 - } + }, + "source": "comment.url.css" } }, { @@ -76,7 +80,8 @@ "end": { "line": 6, "column": 11 - } + }, + "source": "comment.url.css" } }, { @@ -90,7 +95,8 @@ "end": { "line": 6, "column": 46 - } + }, + "source": "comment.url.css" } } ], @@ -102,7 +108,8 @@ "end": { "line": 7, "column": 2 - } + }, + "source": "comment.url.css" } } ] diff --git a/test/cases/document.json b/test/cases/document.json index 55f6de1..916e0dc 100644 --- a/test/cases/document.json +++ b/test/cases/document.json @@ -18,7 +18,8 @@ "end": { "line": 2, "column": 17 - } + }, + "source": "document.css" } }, { @@ -38,7 +39,8 @@ "end": { "line": 4, "column": 20 - } + }, + "source": "document.css" } }, { @@ -53,7 +55,8 @@ "end": { "line": 6, "column": 3 - } + }, + "source": "document.css" } } ], @@ -65,7 +68,8 @@ "end": { "line": 6, "column": 4 - } + }, + "source": "document.css" } } ], @@ -77,7 +81,8 @@ "end": { "line": 7, "column": 2 - } + }, + "source": "document.css" } } ] diff --git a/test/cases/import.json b/test/cases/import.json index eb520b6..ce1f2ac 100644 --- a/test/cases/import.json +++ b/test/cases/import.json @@ -13,7 +13,8 @@ "end": { "line": 2, "column": 36 - } + }, + "source": "import.css" } }, { @@ -27,7 +28,8 @@ "end": { "line": 3, "column": 42 - } + }, + "source": "import.css" } }, { @@ -41,7 +43,8 @@ "end": { "line": 4, "column": 22 - } + }, + "source": "import.css" } }, { @@ -55,7 +58,8 @@ "end": { "line": 5, "column": 41 - } + }, + "source": "import.css" } }, { @@ -69,7 +73,8 @@ "end": { "line": 6, "column": 65 - } + }, + "source": "import.css" } } ] diff --git a/test/cases/import.messed.json b/test/cases/import.messed.json index 5c8a07c..78139d7 100644 --- a/test/cases/import.messed.json +++ b/test/cases/import.messed.json @@ -13,7 +13,8 @@ "end": { "line": 2, "column": 39 - } + }, + "source": "import.messed.css" } }, { @@ -27,7 +28,8 @@ "end": { "line": 3, "column": 44 - } + }, + "source": "import.messed.css" } }, { @@ -41,7 +43,8 @@ "end": { "line": 4, "column": 28 - } + }, + "source": "import.messed.css" } }, { @@ -55,7 +58,8 @@ "end": { "line": 5, "column": 45 - } + }, + "source": "import.messed.css" } }, { @@ -69,7 +73,8 @@ "end": { "line": 7, "column": 67 - } + }, + "source": "import.messed.css" } } ] diff --git a/test/cases/keyframes.complex.json b/test/cases/keyframes.complex.json index b6035ca..379c421 100644 --- a/test/cases/keyframes.complex.json +++ b/test/cases/keyframes.complex.json @@ -24,7 +24,8 @@ "end": { "line": 2, "column": 14 - } + }, + "source": "keyframes.complex.css" } }, { @@ -39,7 +40,8 @@ "end": { "line": 2, "column": 24 - } + }, + "source": "keyframes.complex.css" } } ], @@ -51,7 +53,8 @@ "end": { "line": 2, "column": 25 - } + }, + "source": "keyframes.complex.css" } }, { @@ -72,7 +75,8 @@ "end": { "line": 3, "column": 22 - } + }, + "source": "keyframes.complex.css" } } ], @@ -84,7 +88,8 @@ "end": { "line": 3, "column": 23 - } + }, + "source": "keyframes.complex.css" } }, { @@ -107,7 +112,8 @@ "end": { "line": 6, "column": 26 - } + }, + "source": "keyframes.complex.css" } } ], @@ -119,7 +125,8 @@ "end": { "line": 6, "column": 27 - } + }, + "source": "keyframes.complex.css" } }, { @@ -140,7 +147,8 @@ "end": { "line": 7, "column": 20 - } + }, + "source": "keyframes.complex.css" } }, { @@ -155,7 +163,8 @@ "end": { "line": 7, "column": 33 - } + }, + "source": "keyframes.complex.css" } } ], @@ -167,7 +176,8 @@ "end": { "line": 7, "column": 34 - } + }, + "source": "keyframes.complex.css" } } ], @@ -179,7 +189,8 @@ "end": { "line": 8, "column": 2 - } + }, + "source": "keyframes.complex.css" } } ] diff --git a/test/cases/keyframes.json b/test/cases/keyframes.json index 0694ce0..0ef0637 100644 --- a/test/cases/keyframes.json +++ b/test/cases/keyframes.json @@ -17,7 +17,8 @@ "end": { "line": 2, "column": 19 - } + }, + "source": "keyframes.css" } }, { @@ -37,7 +38,8 @@ "end": { "line": 4, "column": 22 - } + }, + "source": "keyframes.css" } }, { @@ -52,7 +54,8 @@ "end": { "line": 5, "column": 15 - } + }, + "source": "keyframes.css" } } ], @@ -64,7 +67,8 @@ "end": { "line": 6, "column": 4 - } + }, + "source": "keyframes.css" } }, { @@ -78,7 +82,8 @@ "end": { "line": 8, "column": 17 - } + }, + "source": "keyframes.css" } }, { @@ -98,7 +103,8 @@ "end": { "line": 10, "column": 20 - } + }, + "source": "keyframes.css" } }, { @@ -113,7 +119,8 @@ "end": { "line": 11, "column": 15 - } + }, + "source": "keyframes.css" } } ], @@ -125,7 +132,8 @@ "end": { "line": 12, "column": 4 - } + }, + "source": "keyframes.css" } } ], @@ -137,7 +145,8 @@ "end": { "line": 13, "column": 2 - } + }, + "source": "keyframes.css" } } ] diff --git a/test/cases/keyframes.messed.json b/test/cases/keyframes.messed.json index b322137..9c92591 100644 --- a/test/cases/keyframes.messed.json +++ b/test/cases/keyframes.messed.json @@ -24,7 +24,8 @@ "end": { "line": 2, "column": 14 - } + }, + "source": "keyframes.messed.css" } } ], @@ -36,7 +37,8 @@ "end": { "line": 3, "column": 7 - } + }, + "source": "keyframes.messed.css" } }, { @@ -57,7 +59,8 @@ "end": { "line": 6, "column": 16 - } + }, + "source": "keyframes.messed.css" } } ], @@ -69,7 +72,8 @@ "end": { "line": 6, "column": 18 - } + }, + "source": "keyframes.messed.css" } } ], @@ -81,7 +85,8 @@ "end": { "line": 6, "column": 19 - } + }, + "source": "keyframes.messed.css" } } ] diff --git a/test/cases/keyframes.vendor.json b/test/cases/keyframes.vendor.json index 66a0783..a9b948b 100644 --- a/test/cases/keyframes.vendor.json +++ b/test/cases/keyframes.vendor.json @@ -25,7 +25,8 @@ "end": { "line": 2, "column": 21 - } + }, + "source": "keyframes.vendor.json" } } ], @@ -37,7 +38,8 @@ "end": { "line": 2, "column": 22 - } + }, + "source": "keyframes.vendor.json" } }, { @@ -58,7 +60,8 @@ "end": { "line": 3, "column": 19 - } + }, + "source": "keyframes.vendor.json" } } ], @@ -70,7 +73,8 @@ "end": { "line": 3, "column": 20 - } + }, + "source": "keyframes.vendor.json" } } ], @@ -82,7 +86,8 @@ "end": { "line": 4, "column": 2 - } + }, + "source": "keyframes.vendor.json" } } ] diff --git a/test/cases/media.json b/test/cases/media.json index 9d9ae30..8dabf65 100644 --- a/test/cases/media.json +++ b/test/cases/media.json @@ -17,7 +17,8 @@ "end": { "line": 2, "column": 19 - } + }, + "source": "media.css" } }, { @@ -37,7 +38,8 @@ "end": { "line": 4, "column": 22 - } + }, + "source": "media.css" } }, { @@ -52,7 +54,8 @@ "end": { "line": 5, "column": 24 - } + }, + "source": "media.css" } }, { @@ -67,7 +70,8 @@ "end": { "line": 6, "column": 16 - } + }, + "source": "media.css" } } ], @@ -79,7 +83,8 @@ "end": { "line": 7, "column": 4 - } + }, + "source": "media.css" } }, { @@ -93,7 +98,8 @@ "end": { "line": 9, "column": 19 - } + }, + "source": "media.css" } }, { @@ -113,7 +119,8 @@ "end": { "line": 11, "column": 22 - } + }, + "source": "media.css" } }, { @@ -128,7 +135,8 @@ "end": { "line": 12, "column": 20 - } + }, + "source": "media.css" } }, { @@ -143,7 +151,8 @@ "end": { "line": 13, "column": 19 - } + }, + "source": "media.css" } } ], @@ -155,7 +164,8 @@ "end": { "line": 14, "column": 4 - } + }, + "source": "media.css" } } ], @@ -167,7 +177,8 @@ "end": { "line": 15, "column": 2 - } + }, + "source": "media.css" } }, { @@ -192,7 +203,8 @@ "end": { "line": 19, "column": 21 - } + }, + "source": "media.css" } }, { @@ -207,7 +219,8 @@ "end": { "line": 20, "column": 16 - } + }, + "source": "media.css" } } ], @@ -219,7 +232,8 @@ "end": { "line": 21, "column": 4 - } + }, + "source": "media.css" } }, { @@ -240,7 +254,8 @@ "end": { "line": 23, "column": 17 - } + }, + "source": "media.css" } }, { @@ -255,7 +270,8 @@ "end": { "line": 24, "column": 29 - } + }, + "source": "media.css" } } ], @@ -267,7 +283,8 @@ "end": { "line": 25, "column": 4 - } + }, + "source": "media.css" } } ], @@ -279,7 +296,8 @@ "end": { "line": 26, "column": 2 - } + }, + "source": "media.css" } } ] diff --git a/test/cases/media.messed.json b/test/cases/media.messed.json index 3deaeb2..42757a6 100644 --- a/test/cases/media.messed.json +++ b/test/cases/media.messed.json @@ -24,7 +24,8 @@ "end": { "line": 4, "column": 20 - } + }, + "source": "media.messed.css" } }, { @@ -39,7 +40,8 @@ "end": { "line": 5, "column": 15 - } + }, + "source": "media.messed.css" } } ], @@ -51,7 +53,8 @@ "end": { "line": 6, "column": 4 - } + }, + "source": "media.messed.css" } }, { @@ -72,7 +75,8 @@ "end": { "line": 10, "column": 20 - } + }, + "source": "media.messed.css" } }, { @@ -87,7 +91,8 @@ "end": { "line": 11, "column": 19 - } + }, + "source": "media.messed.css" } } ], @@ -99,7 +104,8 @@ "end": { "line": 14, "column": 2 - } + }, + "source": "media.messed.css" } } ], @@ -111,7 +117,8 @@ "end": { "line": 15, "column": 4 - } + }, + "source": "media.messed.css" } }, { @@ -136,7 +143,8 @@ "end": { "line": 20, "column": 31 - } + }, + "source": "media.messed.css" } }, { @@ -151,7 +159,8 @@ "end": { "line": 21, "column": 26 - } + }, + "source": "media.messed.css" } } ], @@ -163,7 +172,8 @@ "end": { "line": 22, "column": 16 - } + }, + "source": "media.messed.css" } }, { @@ -184,7 +194,8 @@ "end": { "line": 24, "column": 27 - } + }, + "source": "media.messed.css" } }, { @@ -199,7 +210,8 @@ "end": { "line": 25, "column": 39 - } + }, + "source": "media.messed.css" } } ], @@ -211,7 +223,8 @@ "end": { "line": 26, "column": 16 - } + }, + "source": "media.messed.css" } } ], @@ -223,7 +236,8 @@ "end": { "line": 27, "column": 2 - } + }, + "source": "media.messed.css" } } ] diff --git a/test/cases/messed-up.json b/test/cases/messed-up.json index 098a80d..6fa5739 100644 --- a/test/cases/messed-up.json +++ b/test/cases/messed-up.json @@ -20,7 +20,8 @@ "end": { "line": 3, "column": 9 - } + }, + "source": "messed-up.css" } } ], @@ -32,7 +33,8 @@ "end": { "line": 3, "column": 10 - } + }, + "source": "messed-up.css" } }, { @@ -53,7 +55,8 @@ "end": { "line": 5, "column": 16 - } + }, + "source": "messed-up.css" } }, { @@ -68,7 +71,8 @@ "end": { "line": 5, "column": 24 - } + }, + "source": "messed-up.css" } } ], @@ -80,7 +84,8 @@ "end": { "line": 5, "column": 25 - } + }, + "source": "messed-up.css" } }, { @@ -101,7 +106,8 @@ "end": { "line": 11, "column": 6 - } + }, + "source": "messed-up.css" } }, { @@ -116,7 +122,8 @@ "end": { "line": 15, "column": 6 - } + }, + "source": "messed-up.css" } } ], @@ -128,7 +135,8 @@ "end": { "line": 15, "column": 7 - } + }, + "source": "messed-up.css" } } ] diff --git a/test/cases/namespace.json b/test/cases/namespace.json index 49565b1..f6f4a12 100644 --- a/test/cases/namespace.json +++ b/test/cases/namespace.json @@ -13,7 +13,8 @@ "end": { "line": 1, "column": 43 - } + }, + "source": "namespace.css" } }, { @@ -27,7 +28,8 @@ "end": { "line": 2, "column": 45 - } + }, + "source": "namespace.css" } } ] diff --git a/test/cases/no-semi.json b/test/cases/no-semi.json index dd7c80f..5d313ea 100644 --- a/test/cases/no-semi.json +++ b/test/cases/no-semi.json @@ -20,7 +20,8 @@ "end": { "line": 3, "column": 13 - } + }, + "source": "no-semi.css" } }, { @@ -35,7 +36,8 @@ "end": { "line": 5, "column": 1 - } + }, + "source": "no-semi.css" } } ], @@ -47,7 +49,8 @@ "end": { "line": 5, "column": 2 - } + }, + "source": "no-semi.css" } } ] diff --git a/test/cases/paged-media.json b/test/cases/paged-media.json index 6272900..77effee 100644 --- a/test/cases/paged-media.json +++ b/test/cases/paged-media.json @@ -13,7 +13,8 @@ "end": { "line": 1, "column": 16 - } + }, + "source": "paged-media.css" } }, { @@ -34,7 +35,8 @@ "end": { "line": 3, "column": 19 - } + }, + "source": "paged-media.css" } }, { @@ -49,7 +51,8 @@ "end": { "line": 4, "column": 15 - } + }, + "source": "paged-media.css" } } ], @@ -61,7 +64,8 @@ "end": { "line": 5, "column": 2 - } + }, + "source": "paged-media.css" } }, { @@ -80,7 +84,8 @@ "end": { "line": 8, "column": 18 - } + }, + "source": "paged-media.css" } } ], @@ -92,7 +97,8 @@ "end": { "line": 9, "column": 2 - } + }, + "source": "paged-media.css" } } ] diff --git a/test/cases/props.json b/test/cases/props.json index 0c355b5..a0fcaab 100644 --- a/test/cases/props.json +++ b/test/cases/props.json @@ -20,7 +20,8 @@ "end": { "line": 3, "column": 13 - } + }, + "source": "props.css" } }, { @@ -35,7 +36,8 @@ "end": { "line": 4, "column": 32 - } + }, + "source": "props.css" } }, { @@ -50,7 +52,8 @@ "end": { "line": 5, "column": 19 - } + }, + "source": "props.css" } } ], @@ -62,7 +65,8 @@ "end": { "line": 6, "column": 2 - } + }, + "source": "props.css" } } ] diff --git a/test/cases/quoted.json b/test/cases/quoted.json index 770b858..7092353 100644 --- a/test/cases/quoted.json +++ b/test/cases/quoted.json @@ -20,7 +20,8 @@ "end": { "line": 2, "column": 55 - } + }, + "source": "quoted.css" } } ], @@ -32,7 +33,8 @@ "end": { "line": 3, "column": 2 - } + }, + "source": "quoted.css" } } ] diff --git a/test/cases/rule.json b/test/cases/rule.json index 9892baf..0af5c6f 100644 --- a/test/cases/rule.json +++ b/test/cases/rule.json @@ -20,7 +20,8 @@ "end": { "line": 2, "column": 13 - } + }, + "source": "rule.css" } } ], @@ -32,7 +33,8 @@ "end": { "line": 3, "column": 2 - } + }, + "source": "rule.css" } } ] diff --git a/test/cases/rules.json b/test/cases/rules.json index a5d651f..9fda096 100644 --- a/test/cases/rules.json +++ b/test/cases/rules.json @@ -20,7 +20,8 @@ "end": { "line": 2, "column": 15 - } + }, + "source": "rules.css" } } ], @@ -32,7 +33,8 @@ "end": { "line": 3, "column": 2 - } + }, + "source": "rules.css" } }, { @@ -53,7 +55,8 @@ "end": { "line": 5, "column": 15 - } + }, + "source": "rules.css" } } ], @@ -65,7 +68,8 @@ "end": { "line": 6, "column": 2 - } + }, + "source": "rules.css" } } ] diff --git a/test/cases/supports.json b/test/cases/supports.json index 67cb88c..065a7ce 100644 --- a/test/cases/supports.json +++ b/test/cases/supports.json @@ -17,7 +17,8 @@ "end": { "line": 2, "column": 19 - } + }, + "source": "supports.css" } }, { @@ -37,7 +38,8 @@ "end": { "line": 4, "column": 22 - } + }, + "source": "supports.css" } }, { @@ -52,7 +54,8 @@ "end": { "line": 5, "column": 17 - } + }, + "source": "supports.css" } }, { @@ -67,7 +70,8 @@ "end": { "line": 6, "column": 18 - } + }, + "source": "supports.css" } } ], @@ -79,7 +83,8 @@ "end": { "line": 7, "column": 4 - } + }, + "source": "supports.css" } } ], @@ -91,7 +96,8 @@ "end": { "line": 8, "column": 2 - } + }, + "source": "supports.css" } } ] diff --git a/test/cases/wtf.json b/test/cases/wtf.json index e2d3cb5..61ac1d5 100644 --- a/test/cases/wtf.json +++ b/test/cases/wtf.json @@ -20,7 +20,8 @@ "end": { "line": 2, "column": 22 - } + }, + "source": "wtf.css" } }, { @@ -35,7 +36,8 @@ "end": { "line": 3, "column": 22 - } + }, + "source": "wtf.css" } } ], @@ -47,7 +49,8 @@ "end": { "line": 4, "column": 2 - } + }, + "source": "wtf.css" } } ] diff --git a/test/css-parse.js b/test/css-parse.js index c6e6127..87497c5 100644 --- a/test/css-parse.js +++ b/test/css-parse.js @@ -16,7 +16,7 @@ describe('parse(str)', function(){ it('should parse ' + file, function(){ var css = read(path.join('test', 'cases', file + '.css'), 'utf8'); var json = read(path.join('test', 'cases', file + '.json'), 'utf8'); - var ret = parse(css, { position: true }); + var ret = parse(css, { position: true, source: file + '.css' }); ret = JSON.stringify(ret, null, 2); ret.should.equal(json); })