From 9828730ad8c6c4861fd337023d3a07e158a5d84a Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Wed, 20 Sep 2017 22:14:10 +1000 Subject: [PATCH 1/8] [jest-docblock]: add docblock.print() --- packages/jest-docblock/README.md | 8 +- .../jest-docblock/src/__tests__/index.test.js | 76 +++++++++++++++++++ packages/jest-docblock/src/index.js | 48 ++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 41f021a912c2..26d7009d992d 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -30,6 +30,7 @@ Pragmas can also take arguments: `jest-docblock` can: * extract the docblock from some code as a string * parse a docblock string's pragmas into an object +* print an object and some comments back to a string ## Installation ```sh @@ -56,13 +57,15 @@ const code = ` } `; -const { extract, parse } = require("jest-docblock"); +const { extract, parse, print } = require("jest-docblock"); const docblock = extract(code); console.log(docblock); // "/**\n * Everything is awesome!\n * \n * @everything is:awesome\n * @flow\n */" const pragmas = parse(docblock); console.log(pragmas); // { everything: "is:awesome", flow: "" } + +console.log(print(pragmas), "hi!") // /**\n * hi!\n *\n * @everything is:awesome\n * @flow */; ``` ## API Documentation @@ -72,3 +75,6 @@ Extracts a docblock from some file contents. Returns the docblock contained in ` ### `parse(docblock: string): {[key: string]: string}` Parses the pragmas in a docblock string into an object whose keys are the pragma tags and whose values are the arguments to those pragmas. + +### `print(object: {[key: string]: string}, comments?: string): string` +Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. \ No newline at end of file diff --git a/packages/jest-docblock/src/__tests__/index.test.js b/packages/jest-docblock/src/__tests__/index.test.js index ba58b1aed701..73e51ddc3cbc 100644 --- a/packages/jest-docblock/src/__tests__/index.test.js +++ b/packages/jest-docblock/src/__tests__/index.test.js @@ -213,4 +213,80 @@ describe('docblock', () => { providesModule: 'apple/banana', }); }); + + it('prints docblocks with no keys as empty string', () => { + const object = {}; + expect(docblock.print(object)).toEqual(''); + }); + + it('prints docblocks with one key on one line', () => { + const object = {flow: ''}; + expect(docblock.print(object)).toEqual('/** @flow */'); + }); + + it('prints docblocks with multiple keys on multiple lines', () => { + const object = { + flow: '', + format: '', + }; + expect(docblock.print(object)).toEqual( + '/**' + os.EOL + ' * @flow' + os.EOL + ' * @format' + os.EOL + ' */', + ); + }); + + it('prints docblocks with values', () => { + const object = { + flow: 'foo', + providesModule: 'x/y/z', + }; + expect(docblock.print(object)).toEqual( + '/**' + + os.EOL + + ' * @flow foo' + + os.EOL + + ' * @providesModule x/y/z' + + os.EOL + + ' */', + ); + }); + + it('prints docblocks with comments', () => { + const object = {flow: 'foo'}; + const comments = 'hello'; + expect(docblock.print(object, comments)).toEqual( + '/**' + + os.EOL + + ' * hello' + + os.EOL + + ' *' + + os.EOL + + ' * @flow foo' + + os.EOL + + ' */', + ); + }); + + it('prints docblocks with comments and no keys', () => { + const object = {}; + const comments = 'Copyright 2004-present Facebook. All Rights Reserved.'; + expect(docblock.print(object, comments)).toEqual( + '/**' + os.EOL + ' * ' + comments + os.EOL + ' */', + ); + }); + + it('prints docblocks with multiline comments', () => { + const object = {}; + const comments = 'hello' + os.EOL + 'world'; + expect(docblock.print(object, comments)).toEqual( + '/**' + os.EOL + ' * hello' + os.EOL + ' * world' + os.EOL + ' */', + ); + }); + + it('prints docblocks that are parseable', () => { + const object = {a: 'b', c: ''}; + const comments = 'hello world!'; + const formatted = docblock.print(object, comments); + const parsed = docblock.parse(formatted); + expect(parsed).toEqual(object); + }); }); diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index 18e0a8d49f6b..0f4cbefd015c 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -8,6 +8,8 @@ * @flow */ +const os = require('os'); + const commentEndRe = /\*\/$/; const commentStartRe = /^\/\*\*/; const docblockRe = /^\s*(\/\*\*?(.|\r?\n)*?\*\/)/; @@ -47,5 +49,51 @@ function parse(docblock: string): {[key: string]: string} { return result; } +function print(object: {[key: string]: string} = {}, comments = ''): string { + const head = '/**'; + const start = ' *'; + const tail = ' */'; + + const keys = Object.keys(object); + const line = os.EOL; + + const printedObject = keys + .reduce( + (acc, key) => + acc.concat(start, ' ', printKeyValue(key, object[key]), line), + [], + ) + .join(''); + + if (!comments) { + if (keys.length === 0) { + return ''; + } + if (keys.length === 1) { + return `${head} ${printKeyValue(keys[0], object[keys[0]])}${tail}`; + } + } + + const printedComments = + comments + .split(os.EOL) + .map(textLine => `${start} ${textLine}`) + .join(os.EOL) + os.EOL; + + return ( + head + + line + + (comments ? printedComments : '') + + (comments && keys.length ? start + line : '') + + printedObject + + tail + ); +} + +function printKeyValue(key, value) { + return `@${key} ${value}`.trim(); +} + exports.extract = extract; exports.parse = parse; +exports.print = print; From 17d8f0fc5b89ece92bfaa8fe2ccb9849dfa934e2 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Wed, 20 Sep 2017 22:41:58 +1000 Subject: [PATCH 2/8] Add missing flow type, clean up --- packages/jest-docblock/src/index.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index 0f4cbefd015c..22635fbb9fe2 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -49,7 +49,10 @@ function parse(docblock: string): {[key: string]: string} { return result; } -function print(object: {[key: string]: string} = {}, comments = ''): string { +function print( + object: {[key: string]: string} = {}, + comments: string = '', +): string { const head = '/**'; const start = ' *'; const tail = ' */'; @@ -58,11 +61,7 @@ function print(object: {[key: string]: string} = {}, comments = ''): string { const line = os.EOL; const printedObject = keys - .reduce( - (acc, key) => - acc.concat(start, ' ', printKeyValue(key, object[key]), line), - [], - ) + .map(key => start + ' ' + printKeyValue(key, object[key]) + line) .join(''); if (!comments) { From 130628f6cc98c71870767566951548e50220b083 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Wed, 20 Sep 2017 22:43:42 +1000 Subject: [PATCH 3/8] Fix docs typo --- packages/jest-docblock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 26d7009d992d..7dfca75585a5 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -65,7 +65,7 @@ console.log(docblock); // "/**\n * Everything is awesome!\n * \n * @everything i const pragmas = parse(docblock); console.log(pragmas); // { everything: "is:awesome", flow: "" } -console.log(print(pragmas), "hi!") // /**\n * hi!\n *\n * @everything is:awesome\n * @flow */; +console.log(print(pragmas), "hi!") // /**\n * hi!\n *\n * @everything is:awesome\n * @flow\n */; ``` ## API Documentation From 66fdd4a78c80ab9e8e6eb4cdd8c9c54021eb69a5 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Wed, 20 Sep 2017 23:31:31 +1000 Subject: [PATCH 4/8] Fix doc typo --- packages/jest-docblock/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 7dfca75585a5..35f3b9d0b5a3 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -65,7 +65,7 @@ console.log(docblock); // "/**\n * Everything is awesome!\n * \n * @everything i const pragmas = parse(docblock); console.log(pragmas); // { everything: "is:awesome", flow: "" } -console.log(print(pragmas), "hi!") // /**\n * hi!\n *\n * @everything is:awesome\n * @flow\n */; +console.log(print(pragmas, "hi!")) // /**\n * hi!\n *\n * @everything is:awesome\n * @flow\n */; ``` ## API Documentation @@ -77,4 +77,4 @@ Extracts a docblock from some file contents. Returns the docblock contained in ` Parses the pragmas in a docblock string into an object whose keys are the pragma tags and whose values are the arguments to those pragmas. ### `print(object: {[key: string]: string}, comments?: string): string` -Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. \ No newline at end of file +Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. From c0b6a97edb5b5446a0a8602d8c9cb41b18a7785b Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Thu, 21 Sep 2017 11:10:56 +1000 Subject: [PATCH 5/8] [WIP] add docblock.parseWithComments() --- packages/jest-docblock/README.md | 5 +- .../jest-docblock/src/__tests__/index.test.js | 51 +++++++++++++++++++ packages/jest-docblock/src/index.js | 20 +++++--- 3 files changed, 67 insertions(+), 9 deletions(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 35f3b9d0b5a3..4d72b4fc2eaf 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -76,5 +76,8 @@ Extracts a docblock from some file contents. Returns the docblock contained in ` ### `parse(docblock: string): {[key: string]: string}` Parses the pragmas in a docblock string into an object whose keys are the pragma tags and whose values are the arguments to those pragmas. +### `parseWithComments(docblock: string): { comments: string, pragmas: {[key: string]: string} }` +Similar to `parse` except this method also returns the comments from the docblock. Useful when used with `print()`. + ### `print(object: {[key: string]: string}, comments?: string): string` -Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. +Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. \ No newline at end of file diff --git a/packages/jest-docblock/src/__tests__/index.test.js b/packages/jest-docblock/src/__tests__/index.test.js index 73e51ddc3cbc..e0466759429a 100644 --- a/packages/jest-docblock/src/__tests__/index.test.js +++ b/packages/jest-docblock/src/__tests__/index.test.js @@ -214,6 +214,57 @@ describe('docblock', () => { }); }); + it('extracts comments from docblock', () => { + const code = + '/**' + + os.EOL + + ' * hello world' + + os.EOL + + ' * @flow yes' + + os.EOL + + ' */'; + expect(docblock.parseWithComments(code)).toEqual({ + comments: 'hello world', + pragmas: {flow: 'yes'}, + }); + }); + + it('extracts multiline comments from docblock', () => { + const code = + '/**' + + os.EOL + + ' * hello' + + os.EOL + + ' * world' + + os.EOL + + ' * @flow yes' + + os.EOL + + ' */'; + expect(docblock.parseWithComments(code)).toEqual({ + comments: 'hello\nworld', + pragmas: {flow: 'yes'}, + }); + }); + + it('extracts comments from beginning and end of docblock', () => { + const code = + '/**' + + os.EOL + + ' * hello' + + os.EOL + + ' * @flow yes' + + os.EOL + + ' * ' + + os.EOL + + ' * world' + + os.EOL + + ' */'; + expect(docblock.parseWithComments(code)).toEqual({ + comments: 'hello\n\nworld', + pragmas: {flow: 'yes'}, + }); + }); + it('prints docblocks with no keys as empty string', () => { const object = {}; expect(docblock.print(object)).toEqual(''); diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index 22635fbb9fe2..91f8e9dba63e 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -18,14 +18,21 @@ const ltrimRe = /^\s*/; const multilineRe = /(?:^|\r?\n) *(@[^\r\n]*?) *\r?\n *([^@\r\n\s][^@\r\n]+?) *\r?\n/g; const propertyRe = /(?:^|\r?\n) *@(\S+) *([^\r\n]*)/g; const stringStartRe = /(\r?\n|^) *\*/g; +const lineStartRe = /(?:\r?\n|^) */g; const wsRe = /[\t ]+/g; -function extract(contents: string): string { +export function extract(contents: string): string { const match = contents.match(docblockRe); return match ? match[0].replace(ltrimRe, '') || '' : ''; } -function parse(docblock: string): {[key: string]: string} { +export function parse(docblock: string): {[key: string]: string} { + return parseWithComments(docblock).pragmas; +} + +export function parseWithComments( + docblock: string, +): {comments: string, pragmas: {[key: string]: string}} { docblock = docblock .replace(commentStartRe, '') .replace(commentEndRe, '') @@ -42,14 +49,15 @@ function parse(docblock: string): {[key: string]: string} { docblock = docblock.trim(); const result = Object.create(null); + const comments = docblock.replace(propertyRe, '').replace(lineStartRe, '\n'); let match; while ((match = propertyRe.exec(docblock))) { result[match[1]] = match[2]; } - return result; + return {comments: comments.trim(), pragmas: result}; } -function print( +export function print( object: {[key: string]: string} = {}, comments: string = '', ): string { @@ -92,7 +100,3 @@ function print( function printKeyValue(key, value) { return `@${key} ${value}`.trim(); } - -exports.extract = extract; -exports.parse = parse; -exports.print = print; From 854afa66dccfc5f60ac1713b12769b19b76489ae Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Thu, 21 Sep 2017 21:51:18 +1000 Subject: [PATCH 6/8] Detect newline character, consolidate API --- packages/jest-docblock/README.md | 9 +- packages/jest-docblock/package.json | 5 +- .../jest-docblock/src/__tests__/index.test.js | 101 +++++++++++++----- packages/jest-docblock/src/index.js | 34 +++--- yarn.lock | 4 + 5 files changed, 110 insertions(+), 43 deletions(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 4d72b4fc2eaf..465bb3d2704d 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -57,7 +57,7 @@ const code = ` } `; -const { extract, parse, print } = require("jest-docblock"); +const { extract, parse, parseWithComments, print } = require("jest-docblock"); const docblock = extract(code); console.log(docblock); // "/**\n * Everything is awesome!\n * \n * @everything is:awesome\n * @flow\n */" @@ -65,7 +65,10 @@ console.log(docblock); // "/**\n * Everything is awesome!\n * \n * @everything i const pragmas = parse(docblock); console.log(pragmas); // { everything: "is:awesome", flow: "" } -console.log(print(pragmas, "hi!")) // /**\n * hi!\n *\n * @everything is:awesome\n * @flow\n */; +const parsed = parseWithComments(docblock); +console.log(parsed); // { comments: "Everything is awesome!", pragmas: { everything: "is:awesome", flow: "" } } + +console.log(print({pragmas, comments: "hi!"})) // /**\n * hi!\n *\n * @everything is:awesome\n * @flow\n */; ``` ## API Documentation @@ -79,5 +82,5 @@ Parses the pragmas in a docblock string into an object whose keys are the pragma ### `parseWithComments(docblock: string): { comments: string, pragmas: {[key: string]: string} }` Similar to `parse` except this method also returns the comments from the docblock. Useful when used with `print()`. -### `print(object: {[key: string]: string}, comments?: string): string` +### `print({ comments: string, pragmas: {[key: string]: string} }): string` Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. \ No newline at end of file diff --git a/packages/jest-docblock/package.json b/packages/jest-docblock/package.json index ccc2c39f7d93..04221a82d1e0 100644 --- a/packages/jest-docblock/package.json +++ b/packages/jest-docblock/package.json @@ -6,5 +6,8 @@ "url": "https://github.com/facebook/jest.git" }, "license": "BSD-3-Clause", - "main": "build/index.js" + "main": "build/index.js", + "dependencies": { + "detect-newline": "^2.1.0" + } } diff --git a/packages/jest-docblock/src/__tests__/index.test.js b/packages/jest-docblock/src/__tests__/index.test.js index e0466759429a..4ff2a42715d5 100644 --- a/packages/jest-docblock/src/__tests__/index.test.js +++ b/packages/jest-docblock/src/__tests__/index.test.js @@ -11,8 +11,8 @@ 'use strict'; -const os = require('os'); -const docblock = require('../'); +import os from 'os'; +import * as docblock from '..'; describe('docblock', () => { it('extracts valid docblock with line comment', () => { @@ -241,7 +241,7 @@ describe('docblock', () => { os.EOL + ' */'; expect(docblock.parseWithComments(code)).toEqual({ - comments: 'hello\nworld', + comments: 'hello' + os.EOL + 'world', pragmas: {flow: 'yes'}, }); }); @@ -260,37 +260,53 @@ describe('docblock', () => { os.EOL + ' */'; expect(docblock.parseWithComments(code)).toEqual({ - comments: 'hello\n\nworld', + comments: 'hello' + os.EOL + os.EOL + 'world', pragmas: {flow: 'yes'}, }); }); - it('prints docblocks with no keys as empty string', () => { - const object = {}; - expect(docblock.print(object)).toEqual(''); + it('extracts docblock comments as CRLF when docblock contains CRLF', () => { + const code = '/**\r\n * foo\r\n * bar\r\n*/'; + expect(docblock.parseWithComments(code)).toEqual({ + comments: 'foo\r\nbar', + pragmas: {}, + }); + }); + + it('extracts docblock comments as LF when docblock contains LF', () => { + const code = '/**\n * foo\n * bar\n*/'; + expect(docblock.parseWithComments(code)).toEqual({ + comments: 'foo\nbar', + pragmas: {}, + }); }); - it('prints docblocks with one key on one line', () => { - const object = {flow: ''}; - expect(docblock.print(object)).toEqual('/** @flow */'); + it('prints docblocks with no pragmas as empty string', () => { + const pragmas = {}; + expect(docblock.print({pragmas})).toEqual(''); }); - it('prints docblocks with multiple keys on multiple lines', () => { - const object = { + it('prints docblocks with one pragma on one line', () => { + const pragmas = {flow: ''}; + expect(docblock.print({pragmas})).toEqual('/** @flow */'); + }); + + it('prints docblocks with multiple pragmas on multiple lines', () => { + const pragmas = { flow: '', format: '', }; - expect(docblock.print(object)).toEqual( + expect(docblock.print({pragmas})).toEqual( '/**' + os.EOL + ' * @flow' + os.EOL + ' * @format' + os.EOL + ' */', ); }); - it('prints docblocks with values', () => { - const object = { + it('prints docblocks with pragmas', () => { + const pragmas = { flow: 'foo', providesModule: 'x/y/z', }; - expect(docblock.print(object)).toEqual( + expect(docblock.print({pragmas})).toEqual( '/**' + os.EOL + ' * @flow foo' + @@ -302,9 +318,9 @@ describe('docblock', () => { }); it('prints docblocks with comments', () => { - const object = {flow: 'foo'}; + const pragmas = {flow: 'foo'}; const comments = 'hello'; - expect(docblock.print(object, comments)).toEqual( + expect(docblock.print({comments, pragmas})).toEqual( '/**' + os.EOL + ' * hello' + @@ -318,26 +334,61 @@ describe('docblock', () => { }); it('prints docblocks with comments and no keys', () => { - const object = {}; + const pragmas = {}; const comments = 'Copyright 2004-present Facebook. All Rights Reserved.'; - expect(docblock.print(object, comments)).toEqual( + expect(docblock.print({comments, pragmas})).toEqual( '/**' + os.EOL + ' * ' + comments + os.EOL + ' */', ); }); it('prints docblocks with multiline comments', () => { - const object = {}; + const pragmas = {}; const comments = 'hello' + os.EOL + 'world'; - expect(docblock.print(object, comments)).toEqual( + expect(docblock.print({comments, pragmas})).toEqual( '/**' + os.EOL + ' * hello' + os.EOL + ' * world' + os.EOL + ' */', ); }); it('prints docblocks that are parseable', () => { - const object = {a: 'b', c: ''}; + const pragmas = {a: 'b', c: ''}; const comments = 'hello world!'; - const formatted = docblock.print(object, comments); + const formatted = docblock.print({comments, pragmas}); const parsed = docblock.parse(formatted); - expect(parsed).toEqual(object); + expect(parsed).toEqual(pragmas); + }); + + it('can augment existing docblocks with comments', () => { + const before = + '/**' + os.EOL + ' * Legalese' + os.EOL + ' * @flow' + os.EOL + ' */'; + const parsed = docblock.parseWithComments(before); + parsed.pragmas.format = ''; + const after = docblock.print(parsed); + expect(after).toEqual( + '/**' + + os.EOL + + ' * Legalese' + + os.EOL + + ' *' + + os.EOL + + ' * @flow' + + os.EOL + + ' * @format' + + os.EOL + + ' */', + ); + }); + + it('prints docblocks using CRLF if comments contains CRLF', () => { + const pragmas = {}; + const comments = 'hello\r\nworld'; + const formatted = docblock.print({comments, pragmas}); + expect(formatted).toEqual('/**\r\n * hello\r\n * world\r\n */'); + }); + + it('prints docblocks using LF if comments contains LF', () => { + const pragmas = {}; + const comments = 'hello\nworld'; + const formatted = docblock.print({comments, pragmas}); + expect(formatted).toEqual('/**\n * hello\n * world\n */'); }); }); diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index 91f8e9dba63e..0e92f427cb5c 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -8,7 +8,8 @@ * @flow */ -const os = require('os'); +import detectNewline from 'detect-newline'; +import {EOL} from 'os'; const commentEndRe = /\*\/$/; const commentStartRe = /^\/\*\*/; @@ -18,7 +19,7 @@ const ltrimRe = /^\s*/; const multilineRe = /(?:^|\r?\n) *(@[^\r\n]*?) *\r?\n *([^@\r\n\s][^@\r\n]+?) *\r?\n/g; const propertyRe = /(?:^|\r?\n) *@(\S+) *([^\r\n]*)/g; const stringStartRe = /(\r?\n|^) *\*/g; -const lineStartRe = /(?:\r?\n|^) */g; +const lineStartRe = /(\r?\n|^) */g; const wsRe = /[\t ]+/g; export function extract(contents: string): string { @@ -33,6 +34,8 @@ export function parse(docblock: string): {[key: string]: string} { export function parseWithComments( docblock: string, ): {comments: string, pragmas: {[key: string]: string}} { + const line = detectNewline(docblock) || EOL; + docblock = docblock .replace(commentStartRe, '') .replace(commentEndRe, '') @@ -44,12 +47,12 @@ export function parseWithComments( let prev = ''; while (prev !== docblock) { prev = docblock; - docblock = docblock.replace(multilineRe, '\n$1 $2\n'); + docblock = docblock.replace(multilineRe, `${line}$1 $2${line}`); } docblock = docblock.trim(); const result = Object.create(null); - const comments = docblock.replace(propertyRe, '').replace(lineStartRe, '\n'); + const comments = docblock.replace(propertyRe, '').replace(lineStartRe, line); let match; while ((match = propertyRe.exec(docblock))) { result[match[1]] = match[2]; @@ -57,19 +60,22 @@ export function parseWithComments( return {comments: comments.trim(), pragmas: result}; } -export function print( - object: {[key: string]: string} = {}, - comments: string = '', -): string { +export function print({ + comments = '', + pragmas = {}, +}: { + comments: string, + pragmas: {[key: string]: string}, +}): string { + const line = detectNewline(comments) || EOL; const head = '/**'; const start = ' *'; const tail = ' */'; - const keys = Object.keys(object); - const line = os.EOL; + const keys = Object.keys(pragmas); const printedObject = keys - .map(key => start + ' ' + printKeyValue(key, object[key]) + line) + .map(key => start + ' ' + printKeyValue(key, pragmas[key]) + line) .join(''); if (!comments) { @@ -77,15 +83,15 @@ export function print( return ''; } if (keys.length === 1) { - return `${head} ${printKeyValue(keys[0], object[keys[0]])}${tail}`; + return `${head} ${printKeyValue(keys[0], pragmas[keys[0]])}${tail}`; } } const printedComments = comments - .split(os.EOL) + .split(line) .map(textLine => `${start} ${textLine}`) - .join(os.EOL) + os.EOL; + .join(line) + line; return ( head + diff --git a/yarn.lock b/yarn.lock index e3aee5cc88cd..360a7f0d8c90 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1971,6 +1971,10 @@ detect-indent@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" +detect-newline@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" + detective@^4.0.0: version "4.5.0" resolved "https://registry.yarnpkg.com/detective/-/detective-4.5.0.tgz#6e5a8c6b26e6c7a254b1c6b6d7490d98ec91edd1" From dc34f5ddbf8c0f40a8fc9a14829f3410577ee4bd Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Thu, 21 Sep 2017 22:21:01 +1000 Subject: [PATCH 7/8] Fixup types --- packages/jest-docblock/README.md | 2 +- packages/jest-docblock/src/__tests__/index.test.js | 6 +++--- packages/jest-docblock/src/index.js | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/jest-docblock/README.md b/packages/jest-docblock/README.md index 465bb3d2704d..85a740b8e6aa 100644 --- a/packages/jest-docblock/README.md +++ b/packages/jest-docblock/README.md @@ -82,5 +82,5 @@ Parses the pragmas in a docblock string into an object whose keys are the pragma ### `parseWithComments(docblock: string): { comments: string, pragmas: {[key: string]: string} }` Similar to `parse` except this method also returns the comments from the docblock. Useful when used with `print()`. -### `print({ comments: string, pragmas: {[key: string]: string} }): string` +### `print({ comments?: string, pragmas?: {[key: string]: string} }): string` Prints an object of key-value pairs back into a docblock. If `comments` are provided, they will be positioned on the top of the docblock. \ No newline at end of file diff --git a/packages/jest-docblock/src/__tests__/index.test.js b/packages/jest-docblock/src/__tests__/index.test.js index 4ff2a42715d5..ce248386a8ce 100644 --- a/packages/jest-docblock/src/__tests__/index.test.js +++ b/packages/jest-docblock/src/__tests__/index.test.js @@ -360,9 +360,9 @@ describe('docblock', () => { it('can augment existing docblocks with comments', () => { const before = '/**' + os.EOL + ' * Legalese' + os.EOL + ' * @flow' + os.EOL + ' */'; - const parsed = docblock.parseWithComments(before); - parsed.pragmas.format = ''; - const after = docblock.print(parsed); + const {comments, pragmas} = docblock.parseWithComments(before); + pragmas.format = ''; + const after = docblock.print({comments, pragmas}); expect(after).toEqual( '/**' + os.EOL + diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index 0e92f427cb5c..e5ee76751349 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -64,8 +64,8 @@ export function print({ comments = '', pragmas = {}, }: { - comments: string, - pragmas: {[key: string]: string}, + comments?: string, + pragmas?: {[key: string]: string}, }): string { const line = detectNewline(comments) || EOL; const head = '/**'; @@ -106,3 +106,5 @@ export function print({ function printKeyValue(key, value) { return `@${key} ${value}`.trim(); } + +export default {extract, parse, parseWithComments, print}; From a13f950da9414f3c541a6970e5b6a25051b0cae1 Mon Sep 17 00:00:00 2001 From: Lucas Azzola Date: Fri, 22 Sep 2017 20:54:23 +1000 Subject: [PATCH 8/8] Remove default export from jest-docblock BREAKING CHANGE: Changes jest-docblock to an ES module without a default export, requires `import * as docblock from 'jest-docbloc'` --- packages/jest-docblock/src/index.js | 2 -- packages/jest-haste-map/src/worker.js | 2 +- packages/jest-runner/src/run_test.js | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/jest-docblock/src/index.js b/packages/jest-docblock/src/index.js index e5ee76751349..6e43729909a6 100644 --- a/packages/jest-docblock/src/index.js +++ b/packages/jest-docblock/src/index.js @@ -106,5 +106,3 @@ export function print({ function printKeyValue(key, value) { return `@${key} ${value}`.trim(); } - -export default {extract, parse, parseWithComments, print}; diff --git a/packages/jest-haste-map/src/worker.js b/packages/jest-haste-map/src/worker.js index 451f2ee36eaa..67c457451213 100644 --- a/packages/jest-haste-map/src/worker.js +++ b/packages/jest-haste-map/src/worker.js @@ -12,7 +12,7 @@ import type {SerializableError} from 'types/TestResult'; import type {HasteImpl, WorkerMessage, WorkerCallback} from './types'; import path from 'path'; -import docblock from 'jest-docblock'; +import * as docblock from 'jest-docblock'; import fs from 'graceful-fs'; import H from './constants'; import extractRequires from './lib/extract_requires'; diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index ed5b35f52fe3..a0ad0d84821d 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -25,7 +25,7 @@ import { } from 'jest-util'; import jasmine2 from 'jest-jasmine2'; import {getTestEnvironment} from 'jest-config'; -import docblock from 'jest-docblock'; +import * as docblock from 'jest-docblock'; // The default jest-runner is required because it is the default test runner // and required implicitly through the `testRunner` ProjectConfig option.