Skip to content

Commit 08aed4a

Browse files
authored
feat(array): Array#flatを追加 (asciidwango#890)
* feat(array): Array#flatを追加 * fix(doctest): support doctest:ecmascript directive * fix(CONTRIBUTING): doctest:ecmascriptを追加 * fix * fix * fix
1 parent 35d1add commit 08aed4a

File tree

6 files changed

+72
-9
lines changed

6 files changed

+72
-9
lines changed

CONTRIBUTING.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ DoctestでPromiseやAsync Functionを使った非同期のテストも書けま
178178

179179
Note: `vm`モジュールの制約からタイムアウト指定の時間が正しく指定させていることが前提となっています。
180180

181+
182+
#### DoctestのECMAScriptバージョン
183+
184+
DoctestはNode.jsで実行されます。
185+
実行するNode.jsがECMAScriptの最新のバージョンをサポートしていない場合があります。
186+
そのため、コードのECMAScriptバージョンを指定することで、そのDoctestをスキップできます。
187+
188+
例) DoctestがECMAScript 2019であることを表記する
189+
190+
<!-- doctest:ecmascript: 2019 -->
191+
```js
192+
[1,[2], [3]].flat();
193+
```
194+
195+
DoctestでサポートしてないECMAScriptバージョンのテストは実行されません。
196+
181197
#### Doctestの無視
182198

183199
CodeBlockの手前に`<!-- doctest:disable -->`というHTMLコメントがある場合はDoctestをしません。

source/basic/array/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,34 @@ const newArray = array.concat("新しい要素");
426426
console.log(newArray); // => ["A", "B", "C", "新しい要素"]
427427
```
428428

429+
## [ES2019] 配列をフラット化 {#flat}
430+
431+
`Array#flat`メソッドを使うことで、多次元配列をフラットな配列に変換できます。
432+
引数を指定しなかった場合は1段階のみのフラット化ですが、引数にわたす数値でフラット化する深さを指定できます。
433+
配列をすべてフラット化する場合には、無限を意味する`Infinity`を値として渡すことで実現できます。
434+
435+
{{book.console}}
436+
<!-- doctest:ecmascript: 2019 -->
437+
```js
438+
const array = [[["A"], "B"], "C"];
439+
// 引数なしは 1 を指定した場合と同じ
440+
console.log(array.flat()); // => [["A"], "B", "C"]
441+
console.log(array.flat(1)); // => [["A"], "B", "C"]
442+
console.log(array.flat(2)); // => ["A", "B", "C"]
443+
// 全てをフラット化するには Inifinity を渡す
444+
console.log(array.flat(Infinity)); // => ["A", "B", "C"]
445+
```
446+
447+
また、`Array#flat`メソッドは必ず新しい配列を作成して返すメソッドです。
448+
そのため、これ以上フラット化できない配列をフラット化しても、同じ要素をもつ新しい配列を返します。
449+
450+
{{book.console}}
451+
<!-- doctest:ecmascript: 2019 -->
452+
```js
453+
const array = ["A", "B", "C"];
454+
console.log(array.flat()); // => ["A", "B", "C"]
455+
```
456+
429457
## 配列から要素を削除 {#delete-element}
430458

431459
### `Array#splice` {#splice}

source/basic/date/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ console.log(invalid.toString()); // => "Invalid Date"
141141
`getMonth`メソッドや`setMonth`メソッドのように月を数値で扱うメソッドは、0から11の数値で指定することに注意しましょう。ある`Date`のインスタンスの時刻が何月かを表示するには、`getMonth`メソッドの戻り値に1を足す必要があります。
142142

143143
{{book.console}}
144+
<!-- doctest:ecmascript: 2017 -->
144145
```js
145146
// YYYY/MM/DD形式の文字列に変換する関数
146147
function formatDate(date) {

source/basic/object/README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ console.log(obj[symbolKey2]); // => "2"
555555
それぞれ、オブジェクトのキー、値、キーと値の組み合わせを配列にして返します。
556556

557557
{{book.console}}
558+
<!-- doctest:ecmascript: 2017 -->
558559
```js
559560
const obj = {
560561
"one": 1,
@@ -563,9 +564,9 @@ const obj = {
563564
};
564565
// `Object.keys`はキーの列挙した配列を返す
565566
console.log(Object.keys(obj)); // => ["one", "two", "three"]
566-
// `Object.values`(ES2017)は値を列挙した配列を返す
567+
// `Object.values`は値を列挙した配列を返す
567568
console.log(Object.values(obj)); // => [1, 2, 3]
568-
// `Object.entries`(ES2017)は[キー, 値]の配列を返す
569+
// `Object.entries`は[キー, 値]の配列を返す
569570
console.log(Object.entries(obj)); // => [["one", 1], ["two", 2], ["three", 3]]
570571
```
571572

test/lib/DocTestController.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
const DISABLE_PATTERN = /doctest:\s*?disable/;
55
const ASYNC_TIME_PATTERN = /doctest:\w*?async:(\d+)/;
66
const ERROR_TYPE_PATTERN = /doctest:\s*([\w\s]*?Error)/;
7+
const ES_VERSION = /doctest:ecmascript:\s*?([\d]+)/;
78

89
/**
910
* CodeBlockの手前に該当するHTMLコメントはdoctestの制御コードとして扱える
@@ -83,6 +84,22 @@ class DocTestController {
8384
return timeoutMillSecAsString;
8485
}
8586

87+
88+
get ecmascriptVersion() {
89+
const version = this.comments.find(comment => {
90+
return ES_VERSION.test(comment);
91+
});
92+
if (!version) {
93+
return;
94+
}
95+
const match = version.match(ES_VERSION);
96+
const versionString = match && match[1];
97+
if (versionString === undefined) {
98+
throw new Error(`AsyncDocTest: ecmascript formatec: ${version}`);
99+
}
100+
return versionString;
101+
}
102+
86103
/**
87104
* Return true, if the `error` is expected error name
88105
* If not defined expected error, return true.

test/markdown-doc-test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const getComments = (parentNode, codeNode) => {
3030
* .travis.ymlのサポートしているNode.jsバージョンに合わせる
3131
* @type {string[]}
3232
*/
33-
const ESVersions = ["ES2017"];
33+
const ESVersions = ["2017", "2018", "2019"];
3434
/**
3535
* Markdownファイルの CodeBlock に対してdoctestを行う
3636
* CodeBlockは必ず実行できるとは限らないので、
@@ -42,15 +42,15 @@ const ESVersions = ["ES2017"];
4242
*
4343
* その他詳細は CONTRIBUTING.md を読む
4444
**/
45-
describe("doctest:md", function() {
45+
describe("doctest:md", function () {
4646
const files = globby.sync([
4747
`${sourceDir}/**/*.md`,
4848
`!${sourceDir}/**/node_modules{,/**}`,
4949
`!**/OUTLINE.md`
5050
]);
5151
files.forEach(filePath => {
5252
const normalizeFilePath = filePath.replace(sourceDir, "");
53-
describe(`${normalizeFilePath}`, function() {
53+
describe(`${normalizeFilePath}`, function () {
5454
const content = fs.readFileSync(filePath, "utf-8");
5555
const markdownAST = attachParents(remark.parse(content));
5656
const codeBlocks = [].concat(
@@ -60,16 +60,16 @@ describe("doctest:md", function() {
6060
// try to eval
6161
codeBlocks.forEach((codeBlock, index) => {
6262
const codeValue = codeBlock.value;
63-
const isIgnoredCode = ESVersions.some(version => {
64-
return codeValue.includes(version);
65-
});
6663
const comments = getComments(codeBlock.parent, codeBlock);
6764
const docTestController = new DocTestController(comments);
65+
const isIgnoredCode = ESVersions.some(version => {
66+
return codeValue.includes(version) || docTestController.ecmascriptVersion === version;
67+
});
6868
if (docTestController.isDisabled) {
6969
return;
7070
}
7171
const testCaseName = codeValue.slice(0, 32).replace(/[\r\n]/g, "_");
72-
it(testCaseName, function(_done) {
72+
it(testCaseName, function (_done) {
7373
let isCalled = false;
7474
const done = (error) => {
7575
if (isCalled) {

0 commit comments

Comments
 (0)