From 3dbe7c2e4392719852aec390101532bcd578dcb9 Mon Sep 17 00:00:00 2001 From: ng-zorro-bot <33472860+ng-zorro-bot@users.noreply.github.com> Date: Wed, 19 Jun 2019 14:29:27 +0800 Subject: [PATCH 01/23] chore: sync ant-design v3.19.6 (#3602) --- components/card/style/index.less | 2 +- components/date-picker/style/Picker.less | 4 ++++ components/date-picker/style/RangePicker.less | 1 - components/input/style/mixin.less | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/components/card/style/index.less b/components/card/style/index.less index b23e8fc3ea..a198bdd37a 100644 --- a/components/card/style/index.less +++ b/components/card/style/index.less @@ -109,7 +109,7 @@ padding-bottom: 0; } - &-contain-tabs &-extra { + &-contain-tabs > &-head &-extra { padding-bottom: 0; } diff --git a/components/date-picker/style/Picker.less b/components/date-picker/style/Picker.less index c0fd7d269e..0d3c36e3af 100644 --- a/components/date-picker/style/Picker.less +++ b/components/date-picker/style/Picker.less @@ -43,6 +43,10 @@ &-input { outline: none; + + &.@{ant-prefix}-input { + line-height: @line-height-base; + } } &-input.@{ant-prefix}-input-sm { diff --git a/components/date-picker/style/RangePicker.less b/components/date-picker/style/RangePicker.less index 9027cab589..b8acbe2511 100644 --- a/components/date-picker/style/RangePicker.less +++ b/components/date-picker/style/RangePicker.less @@ -7,7 +7,6 @@ background-color: transparent; border: 0; outline: 0; - vertical-align: top; .placeholder(); &[disabled] { diff --git a/components/input/style/mixin.less b/components/input/style/mixin.less index 0bc2b8f0c6..b5d22ed13b 100644 --- a/components/input/style/mixin.less +++ b/components/input/style/mixin.less @@ -82,6 +82,7 @@ min-height: @input-height-base; vertical-align: bottom; transition: all 0.3s, height 0s; + line-height: @line-height-base; } // Size From c85743d520b04a3c3abe0f67a9805d1c5eefb523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=96=87=E8=94=BA?= Date: Wed, 19 Jun 2019 19:56:18 +0800 Subject: [PATCH 02/23] fix(module:table): fix sortChange with dynamic columns (#3603) (#3605) close #3603 --- components/table/nz-thead.component.ts | 4 ++-- components/table/nz-thead.spec.ts | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/components/table/nz-thead.component.ts b/components/table/nz-thead.component.ts index 198d8001e7..9e549eccaf 100644 --- a/components/table/nz-thead.component.ts +++ b/components/table/nz-thead.component.ts @@ -26,7 +26,7 @@ import { ViewEncapsulation } from '@angular/core'; import { merge, Subject } from 'rxjs'; -import { flatMap, startWith, takeUntil } from 'rxjs/operators'; +import { startWith, switchMap, takeUntil } from 'rxjs/operators'; import { InputBoolean } from 'ng-zorro-antd/core'; @@ -62,7 +62,7 @@ export class NzTheadComponent implements AfterContentInit, OnDestroy, AfterViewI this.listOfNzThComponent.changes .pipe( startWith(true), - flatMap(() => + switchMap(() => merge<{ key: string; value: string }>(...this.listOfNzThComponent.map(th => th.nzSortChangeWithKey)) ), takeUntil(this.destroy$) diff --git a/components/table/nz-thead.spec.ts b/components/table/nz-thead.spec.ts index 202bc87496..f8e53c3856 100644 --- a/components/table/nz-thead.spec.ts +++ b/components/table/nz-thead.spec.ts @@ -54,6 +54,27 @@ describe('nz-thead', () => { expect(upButtons[1].querySelector('.ant-table-column-sorter-down').classList).toContain('on'); expect(testComponent.sortChange).toHaveBeenCalledTimes(2); }); + + // Test for #3603 + it('should support dynamic headers', () => { + testComponent.singleSort = true; + fixture.detectChanges(); + expect(testComponent.sortChange).toHaveBeenCalledTimes(0); + let upButtons = table.nativeElement.querySelectorAll('.ant-table-column-sorters'); + upButtons[2].click(); + fixture.detectChanges(); + expect(testComponent.sortChange).toHaveBeenCalledTimes(1); + upButtons[3].click(); + fixture.detectChanges(); + expect(testComponent.sortChange).toHaveBeenCalledTimes(2); + + testComponent.columns = testComponent.columns.slice(0, 1); + fixture.detectChanges(); + upButtons = table.nativeElement.querySelectorAll('.ant-table-column-sorters'); + expect(upButtons.length).toBe(3); + upButtons[2].click(); + expect(testComponent.sortChange).toHaveBeenCalledTimes(3); + }); }); }); @@ -64,6 +85,7 @@ describe('nz-thead', () => { + ` @@ -71,4 +93,5 @@ describe('nz-thead', () => { export class NzTheadTestNzTableComponent { singleSort = false; sortChange = jasmine.createSpy('sort change'); + columns = ['third', 'fourth']; } From 9522658918e90ca2f01b4ebca565a280cc424354 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Wed, 19 Jun 2019 21:15:47 +0800 Subject: [PATCH 03/23] chore: sync with antd 3.19 (#3590) * chore: sync with antd 3.19 * test(module:page-header): fix test --- .../page-header/nz-page-header.component.html | 8 +++++--- components/page-header/nz-page-header.component.ts | 13 ++++++++++++- components/page-header/nz-page-header.spec.ts | 6 +++--- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/components/page-header/nz-page-header.component.html b/components/page-header/nz-page-header.component.html index 0556d96660..055fb04948 100644 --- a/components/page-header/nz-page-header.component.html +++ b/components/page-header/nz-page-header.component.html @@ -1,8 +1,10 @@ -
- - +
+
+ + +
diff --git a/components/page-header/nz-page-header.component.ts b/components/page-header/nz-page-header.component.ts index a168c6b6b5..ed7150df0e 100644 --- a/components/page-header/nz-page-header.component.ts +++ b/components/page-header/nz-page-header.component.ts @@ -32,7 +32,18 @@ import { NzPageHeaderFooterDirective } from './nz-page-header-cells'; host: { class: 'ant-page-header', '[class.ant-page-header-has-footer]': 'nzPageHeaderFooter' - } + }, + styles: [ + ` + .ant-page-header-back-button { + border: 0px; + background: transparent; + padding: 0px; + line-height: inherit; + display: inline-block; + } + ` + ] }) export class NzPageHeaderComponent implements OnInit, OnChanges { isTemplateRefBackIcon = false; diff --git a/components/page-header/nz-page-header.spec.ts b/components/page-header/nz-page-header.spec.ts index e57dbd21fd..fccd1e64be 100644 --- a/components/page-header/nz-page-header.spec.ts +++ b/components/page-header/nz-page-header.spec.ts @@ -65,14 +65,14 @@ describe('NzPageHeaderComponent', () => { const fixture = TestBed.createComponent(NzDemoPageHeaderBasicComponent); const pageHeader = fixture.debugElement.query(By.directive(NzPageHeaderComponent)); fixture.detectChanges(); - expect(pageHeader.nativeElement.querySelector('.ant-page-header-back-icon > i.anticon-arrow-left')).toBeTruthy(); + expect(pageHeader.nativeElement.querySelector('.ant-page-header-back i.anticon-arrow-left')).toBeTruthy(); }); it('should does not have an default back icon', () => { const fixture = TestBed.createComponent(NzDemoPageHeaderContentComponent); const pageHeader = fixture.debugElement.query(By.directive(NzPageHeaderComponent)); fixture.detectChanges(); - expect(pageHeader.nativeElement.querySelector('.ant-page-header-back-icon')).toBeFalsy(); + expect(pageHeader.nativeElement.querySelector('.ant-page-header-back')).toBeFalsy(); }); it('should nzBack work', () => { @@ -82,7 +82,7 @@ describe('NzPageHeaderComponent', () => { spyOn(context, 'onBack'); fixture.detectChanges(); expect(context.onBack).not.toHaveBeenCalled(); - const back = pageHeader.nativeElement.querySelector('.ant-page-header-back-icon'); + const back = pageHeader.nativeElement.querySelector('.ant-page-header-back'); (back as HTMLElement).click(); fixture.detectChanges(); expect(context.onBack).toHaveBeenCalled(); From 1b17110821f15870e2cec4d6ae331ed91eef87a2 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 20 Jun 2019 16:49:18 +0800 Subject: [PATCH 04/23] chore: refactor commit hook (#3610) * chore: refactor commit hook * chore(packaging): clean dependencie * chore(packaging): clean dev dependencie --- commitlint.config.js | 60 +++++++++++++++++++++ package.json | 4 +- scripts/git/commit-message.json | 24 --------- scripts/git/commit-msg.js | 21 -------- scripts/git/validate-commit-message.js | 73 -------------------------- 5 files changed, 63 insertions(+), 119 deletions(-) create mode 100644 commitlint.config.js delete mode 100644 scripts/git/commit-message.json delete mode 100755 scripts/git/commit-msg.js delete mode 100644 scripts/git/validate-commit-message.js diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000000..e5762bf628 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,60 @@ +'use strict'; +const message = process.env['HUSKY_GIT_PARAMS']; +const fs = require('fs'); + +const types = [ + 'build', + "chore", + 'ci', + 'docs', + 'feat', + 'fix', + 'perf', + 'refactor', + "release", + 'revert', + 'style', + 'test' +]; + +const scopes = [ + "showcase", + "packaging", + "changelog", + "schematics", + "module:*" +]; + +function parseMessage(message) { + const PATTERN = /^(\w+)(?:\(([^)]+)\))?\: (.+)$/; + const match = PATTERN.exec(message); + if (!match) { + return null; + } + return { + type: match[1] || null, + scope: match[2] || null, + } +} + +function getScopesRule() { + const messages = fs.readFileSync(message, {encoding: 'utf-8'}); + const parsed = parseMessage(messages.split('\n')[0]); + if (!parsed) { + return [2, 'always', scopes] + } + const { scope, type } = parsed; + if (scope && !scopes.includes(scope) && type !== 'release' && !/module:.+/.test(scope)) { + return [2, 'always', scopes] + } else { + return [2, 'always', []] + } +} + +module.exports = { + extends: ['@commitlint/config-angular'], + rules: { + 'type-enum': [2, 'always', types], + 'scope-enum': getScopesRule + } +}; diff --git a/package.json b/package.json index cc1ac75123..0d1d012556 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,8 @@ "@angular/pwa": "^0.800.1", "@angular/router": "~8.0.0", "@angular/service-worker": "~8.0.0", + "@commitlint/cli": "^8.0.0", + "@commitlint/config-angular": "^8.0.0", "@nguniversal/module-map-ngfactory-loader": "^7.1.1", "@schematics/angular": "~8.0.1", "@stackblitz/sdk": "^1.1.1", @@ -123,7 +125,7 @@ }, "husky": { "hooks": { - "commit-msg": "node ./scripts/git/commit-msg.js -E HUSKY_GIT_PARAMS", + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", "pre-commit": "lint-staged" } } diff --git a/scripts/git/commit-message.json b/scripts/git/commit-message.json deleted file mode 100644 index 3f9c6885b8..0000000000 --- a/scripts/git/commit-message.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "maxLength": 100, - "types": [ - "build", - "ci", - "docs", - "feat", - "fix", - "perf", - "refactor", - "release", - "style", - "test", - "chore", - "revert" - ], - "scopes": [ - "showcase", - "packaging", - "changelog", - "schematics", - "module:*" - ] -} diff --git a/scripts/git/commit-msg.js b/scripts/git/commit-msg.js deleted file mode 100755 index 1c8079e8e9..0000000000 --- a/scripts/git/commit-msg.js +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env node - -// from https://github.com/angular/angular/blob/master/scripts/git/commit-msg.js - -'use strict'; - -const fs = require('fs'); -const checkMsg = require('./validate-commit-message'); -const msgFile = process.env['HUSKY_GIT_PARAMS']; - -let isValid = true; -if (msgFile || true) { - const commitMsg = fs.readFileSync(msgFile, {encoding: 'utf-8'}); - const firstLine = commitMsg.split('\n')[0]; - isValid = checkMsg(firstLine); - if (!isValid) { - console.error('\x1b[36mCheck CONTRIBUTING.md at the root of the repo for more information.(请查看根目录下的 CONTRIBUTING.md 获取更多信息)\x1b[0m\n'); - } -} - -process.exit(isValid ? 0 : 1); diff --git a/scripts/git/validate-commit-message.js b/scripts/git/validate-commit-message.js deleted file mode 100644 index 26dfd200ad..0000000000 --- a/scripts/git/validate-commit-message.js +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env node - -// from https://github.com/angular/angular/blob/master/tools/validate-commit-message/validate-commit-message.js - -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const configPath = path.resolve(__dirname, './commit-message.json'); -const config = JSON.parse(fs.readFileSync(configPath, 'utf8')); -const PATTERN = /^(\w+)(?:\(([^)]+)\))?\: (.+)$/; -const FIXUP_SQUASH = /^(fixup|squash)\! /i; -const REVERT = /^revert:? /i; - -module.exports = function (commitSubject) { - - const subject = commitSubject.replace(FIXUP_SQUASH, ''); - - if (subject.match(REVERT)) { - return true; - } - - if (subject.length > config['maxLength']) { - error(`The commit message is longer than ${config['maxLength']} characters`, commitSubject); - error(`commit 信息不能超过 ${config['maxLength']} 字符`, commitSubject, 'zh'); - return false; - } - - const match = PATTERN.exec(subject); - if (!match) { - error(`The commit message does not match the format of '(): ' OR ': '`, commitSubject); - error(`这条 commit 信息格式不正确 '(): ' 或 ': `, commitSubject, 'zh'); - return false; - } - - const type = match[1]; - - if (type.toLowerCase() === 'wip') { - error(`wip are not allowed in a commit, you can change this PR title`, commitSubject); - error(`wip 不允许出现在 commit 中,你可以在 PR 中修改它的标题`, commitSubject, 'zh'); - return false; - } - - if (config['types'].indexOf(type) === -1) { - error( - `${type} is not an allowed type.\n => TYPES: ${config['types'].join(', ')}`, commitSubject); - error( - `${type} 是不允许的 type.\n => TYPES: ${config['types'].join(', ')}`, commitSubject, 'zh'); - return false; - } - - const scope = match[2]; - - if (scope && !config['scopes'].includes(scope) && type !== 'release' && !/module:.+/.test(scope)) { - error( - `"${scope}" is not an allowed scope.\n => SCOPES: ${config['scopes'].join(', ')}`, commitSubject); - error( - `"${scope}" 是不允许的 scope.\n => SCOPES: ${config['scopes'].join(', ')}`, commitSubject, 'zh'); - return false; - } - - return true; -}; - -function error(errorMessage, commitMessage, lang) { - if (lang === 'zh') { - console.error(`\x1b[33m无效的 COMMIT 信息: "${commitMessage}"\x1b[0m\n\x1b[31m => 错误: ${errorMessage}\x1b[0m\n`); - } else { - console.error(`\x1b[33mINVALID COMMIT MSG: "${commitMessage}"\x1b[0m\n\x1b[31m => ERROR: ${errorMessage}\x1b[0m\n`); - } -} - -module.exports.config = config; From 2ff9b4d109f800d94a5103a34216207186389725 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 20 Jun 2019 16:53:35 +0800 Subject: [PATCH 05/23] chore: refactor commit hook (#3610) * chore: refactor commit hook * chore(packaging): clean dependencie * chore(packaging): clean dev dependencie From 2c03fb724ad26a9591482ab567c6c02198821824 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 20 Jun 2019 17:36:18 +0800 Subject: [PATCH 06/23] chore: refactor commit hook (#3610) * chore: refactor commit hook * chore(packaging): clean dependencie * chore(packaging): clean dev dependencie From 1d8b08bf53e3bec626f61b0f96b3059e8f8affb9 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Tue, 11 Jun 2019 18:47:28 +0800 Subject: [PATCH 07/23] build: refactor scripts ref #2474 --- build-config.js | 13 ++ components/core/responsive/index.ts | 8 + components/core/responsive/public-api.ts | 8 + gulpfile.js | 18 ++ package.json | 51 ++-- scripts/build-config.ts | 27 +++ scripts/build/compile-styles.js | 84 ------- scripts/build/compile-styles.ts | 87 +++++++ scripts/build/migration-styles.js | 12 - scripts/build/migration-styles.ts | 16 ++ scripts/build/replace-publish.sh | 3 - scripts/gulp/gulpfile.ts | 14 ++ scripts/gulp/tasks/clean.ts | 6 + scripts/gulp/tasks/default.ts | 6 + scripts/gulp/tasks/library.ts | 32 +++ scripts/gulp/tasks/release.ts | 0 scripts/gulp/tasks/schematic.ts | 48 ++++ scripts/gulp/tasks/site.ts | 107 +++++++++ scripts/gulp/tasks/universal.ts | 34 +++ scripts/gulp/tsconfig.json | 25 ++ scripts/gulp/util/task-helpers.ts | 70 ++++++ scripts/prerender/prerender.ts | 23 +- scripts/prerender/sitemap.ts | 7 +- scripts/publish/publish.js | 161 ------------- scripts/release/parse-version.ts | 62 +++++ scripts/release/release.ts | 185 +++++++++++++++ scripts/release/tsconfig.json | 6 + scripts/schematics/copy-resources.js | 22 -- scripts/schematics/copy-resources.ts | 25 ++ ...{demo2schematics.js => demo2schematics.ts} | 80 +++---- scripts/schematics/set-theme.js | 13 -- scripts/schematics/set-theme.ts | 16 ++ scripts/schematics/set-version.js | 11 - scripts/schematics/set-version.ts | 13 ++ scripts/site/generate-site.js | 218 +++++++++--------- scripts/site/generateColorLess.js | 6 +- 36 files changed, 1014 insertions(+), 503 deletions(-) create mode 100644 build-config.js create mode 100644 gulpfile.js create mode 100644 scripts/build-config.ts delete mode 100644 scripts/build/compile-styles.js create mode 100644 scripts/build/compile-styles.ts delete mode 100644 scripts/build/migration-styles.js create mode 100644 scripts/build/migration-styles.ts delete mode 100755 scripts/build/replace-publish.sh create mode 100644 scripts/gulp/gulpfile.ts create mode 100644 scripts/gulp/tasks/clean.ts create mode 100644 scripts/gulp/tasks/default.ts create mode 100644 scripts/gulp/tasks/library.ts create mode 100644 scripts/gulp/tasks/release.ts create mode 100644 scripts/gulp/tasks/schematic.ts create mode 100644 scripts/gulp/tasks/site.ts create mode 100644 scripts/gulp/tasks/universal.ts create mode 100644 scripts/gulp/tsconfig.json create mode 100644 scripts/gulp/util/task-helpers.ts delete mode 100644 scripts/publish/publish.js create mode 100644 scripts/release/parse-version.ts create mode 100644 scripts/release/release.ts create mode 100644 scripts/release/tsconfig.json delete mode 100644 scripts/schematics/copy-resources.js create mode 100644 scripts/schematics/copy-resources.ts rename scripts/schematics/{demo2schematics.js => demo2schematics.ts} (75%) delete mode 100644 scripts/schematics/set-theme.js create mode 100644 scripts/schematics/set-theme.ts delete mode 100644 scripts/schematics/set-version.js create mode 100644 scripts/schematics/set-version.ts diff --git a/build-config.js b/build-config.js new file mode 100644 index 0000000000..917eca5eba --- /dev/null +++ b/build-config.js @@ -0,0 +1,13 @@ +const {join} = require('path'); + +const packageJson = require('./package.json'); +const buildVersion = packageJson.version; + +module.exports = { + projectVersion: buildVersion, + projectDir: __dirname, + componentsDir: join(__dirname, 'components'), + scriptsDir: join(__dirname, 'scripts'), + outputDir: join(__dirname, 'dist'), + publishDir: join(__dirname, 'publish'), +}; \ No newline at end of file diff --git a/components/core/responsive/index.ts b/components/core/responsive/index.ts index 7e1a213e3e..f17e95188c 100644 --- a/components/core/responsive/index.ts +++ b/components/core/responsive/index.ts @@ -1 +1,9 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + export * from './public-api'; diff --git a/components/core/responsive/public-api.ts b/components/core/responsive/public-api.ts index 0c19caa1de..8a75b13ce1 100644 --- a/components/core/responsive/public-api.ts +++ b/components/core/responsive/public-api.ts @@ -1 +1,9 @@ +/** + * @license + * Copyright Alibaba.com All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE + */ + export * from './break-point'; diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000000..017a5e0c66 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,18 @@ +const path = require('path'); + +const projectDir = __dirname; +const tsconfigPath = path.join(projectDir, 'scripts/gulp/tsconfig.json'); +const tsconfig = require(tsconfigPath); + +if (projectDir.includes(' ')) { + console.error('Error: Cannot run the build tasks if the project is ' + + 'located in a directory with spaces in between. Please rename your project directory.'); + process.exit(1); +} + +// Register TS compilation. +require('ts-node').register({ + project: tsconfigPath +}); + +require('./scripts/gulp/gulpfile'); \ No newline at end of file diff --git a/package.json b/package.json index 0d1d012556..bacf9bfbdd 100644 --- a/package.json +++ b/package.json @@ -7,38 +7,21 @@ "node": ">=12.1.0" }, "scripts": { - "build-iframe": "node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --project=ng-zorro-antd-iframe --prod --base-href ./", - "build-site": "node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --prod", - "build-site-server": "node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng run ng-zorro-antd-doc:server:production", - "build:client-and-server-bundles": "npm run build-site && npm run build-site-server", - "build:docs": "npm run build:client-and-server-bundles && npm run build:prerender && npm run build-iframe && npm run helper", - "build:prerender": "npm run compile:prerender && npm run generate:prerender", - "compile:prerender": "tsc -p scripts/prerender/tsconfig.json", - "generate:prerender": "cd dist && node prerender && node sitemap", + "start": "gulp start:site", + "test": "ng test --watch=false --code-coverage", + "build": "gulp build:release", + "build:library": "gulp build:library", + "doc": "gulp build:overview-site", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --pkg components/package.json && node ./scripts/site/replace-scope-prefix.js", - "doc": "npm run site:init && npm run build-site", - "format:check": "prettier --config ./.prettierrc --list-different \"component/**/*{.ts}\"", - "generate": "ng build ng-zorro-antd-lib", - "helper": "bash ./scripts/release-helper.sh", - "integration-cli": "npm run generate && cd integration/angular-cli && npm run integration", - "integration-rollup": "npm run generate && cd integration/rollup && npm run integration", - "integration-webpack": "npm run generate && cd integration/webpack && npm run integration", - "integration": "npm run generate && bash ./integration-test.sh", - "lint": "tslint -c tslint.json 'components/**/!(demo|testing)/!(polyfills).ts' --fix", - "migration-styles": "node ./scripts/build/migration-styles.js", + "format": "prettier --config ./.prettierrc --list-different \"component/**/*{.ts}\"", + "stage-release": "ts-node --project scripts/release/tsconfig.json scripts/release/release.ts", "ng": "ng", - "postgenerate": "node scripts/build/compile-styles.js && cp README.md publish/README.md && npm run migration-styles && npm run schematic:generate", - "pre-release": "npm run site:init && bash ./scripts/build/replace-publish.sh && npm run generate && npm run build:docs", - "release": "node ./scripts/publish/publish.js", - "schematic:build": "node ./scripts/schematics/set-theme.js && node ./scripts/schematics/set-version.js && npm run schematic:tsc && node ./scripts/schematics/copy-resources", - "schematic:demo": "node ./scripts/schematics/demo2schematics", - "schematic:generate": "npm run schematic:demo && npm run schematic:build && rm -rf schematics/demo", - "schematic:tsc": "tsc -p schematics/tsconfig.json", - "site:init": "node ./scripts/site/generate-site init && node ./scripts/site/generateColorLess", - "site:start": "npm run site:init && ng serve --port 0 --open", - "site": "node ./scripts/site/generate-site", - "start": "ng serve --port 0", - "test": "ng test --watch=false --code-coverage" + "gulp": "gulp", + "lint": "tslint -c tslint.json 'components/**/!(demo|testing)/!(polyfills).ts' --fix", + "integration-cli": "npm run build:library && cd integration/angular-cli && npm run integration", + "integration-rollup": "npm run build:library && cd integration/rollup && npm run integration", + "integration-webpack": "npm run build:library && cd integration/webpack && npm run integration", + "integration": "npm run build:library && bash ./integration-test.sh" }, "dependencies": { "@angular/cdk": "~8.0.0", @@ -70,8 +53,10 @@ "@schematics/angular": "~8.0.1", "@stackblitz/sdk": "^1.1.1", "@types/fs-extra": "^5.0.4", + "@types/gulp": "^4.0.6", "@types/jasmine": "~2.8.8", "@types/jasminewd2": "~2.0.3", + "@types/less": "^3.0.0", "antd-theme-generator": "^1.0.7", "chalk": "^2.4.1", "classlist.js": "^1.1.20150312", @@ -81,6 +66,8 @@ "conventional-changelog-cli": "^2.0.1", "core-js": "^2.5.4", "fs-extra": "^6.0.1", + "gulp": "^4.0.2", + "gulp-clean": "^0.4.0", "husky": "^1.0.1", "jasmine-core": "~2.99.1", "karma": "~3.0.0", @@ -103,8 +90,10 @@ "readline-sync": "^1.4.9", "remark": "^8.0.0", "rxjs": "~6.5.2", + "resolve-bin": "^0.4.0", + "run-sequence": "^2.2.1", "sitemap": "^2.1.0", - "ts-node": "~7.0.0", + "ts-node": "^7.0.1", "tsickle": ">=0.34.0", "tslib": "^1.9.0", "tslint": "~5.11.0", diff --git a/scripts/build-config.ts b/scripts/build-config.ts new file mode 100644 index 0000000000..a6586bf4dc --- /dev/null +++ b/scripts/build-config.ts @@ -0,0 +1,27 @@ +import { existsSync } from 'fs'; +import { dirname, join, resolve } from 'path'; + +export interface BuildConfig { + projectVersion: string; + projectDir: string; + componentsDir: string; + scriptsDir: string; + outputDir: string; + publishDir: string; +} + +const BUILD_CONFIG_FILENAME = 'build-config.js'; + +export function findBuildConfig(): string { + let currentDir = process.cwd(); + + while (!existsSync(resolve(currentDir, BUILD_CONFIG_FILENAME))) { + currentDir = dirname(currentDir); + } + + return join(currentDir, BUILD_CONFIG_FILENAME); +} + +const buildConfigPath = findBuildConfig(); + +export const buildConfig = require(buildConfigPath) as BuildConfig; diff --git a/scripts/build/compile-styles.js b/scripts/build/compile-styles.js deleted file mode 100644 index 090a9794ad..0000000000 --- a/scripts/build/compile-styles.js +++ /dev/null @@ -1,84 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); -const less = require('less'); -const LessPluginCleanCSS = require('less-plugin-clean-css'); -const NpmImportPlugin = require('less-plugin-npm-import'); - -function compileLess(content, savePath, min, sub, rootPath) { - return new Promise((resolve, reject) => { - const plugins = []; - const lessOptions = { plugins: plugins, javascriptEnabled: true }; - - if (min) { - plugins.push(new LessPluginCleanCSS({ advanced: true })); - } - - if (sub) { - lessOptions.paths = [path.dirname(rootPath)]; - lessOptions.filename = rootPath; - plugins.push( - new NpmImportPlugin({ - prefix: '~' - }) - ); - } - - return less - .render(content, lessOptions) - .then(({ css }) => { - fs.writeFileSync(savePath, css); - resolve(); - }) - .catch(err => reject(err)); - }); -} - -const sourcePath = path.resolve(__dirname, '../../components'); -const targetPath = path.resolve(__dirname, '../../publish'); -const componentFolders = fs.readdirSync(targetPath); - -componentFolders.forEach(dir => { - if (fs.existsSync(`${sourcePath}/${dir}/style/index.less`)) { - // Copy style files for each component. - fs.copySync(`${sourcePath}/${dir}/style`, `${targetPath}/${dir}/style`); - - // Compile less files to CSS and delete the `entry.less` file. - const buildFilePath = `${sourcePath}/${dir}/style/entry.less`; - if (fs.existsSync(buildFilePath)) { - compileLess( - fs.readFileSync(buildFilePath, { encoding: 'utf8' }), - path.join(targetPath, dir, 'style', `index.css`), - false, - true, - buildFilePath - ).catch(e => console.log(e)); - compileLess( - fs.readFileSync(buildFilePath, { encoding: 'utf8' }), - path.join(targetPath, dir, 'style', `index.min.css`), - true, - true, - buildFilePath - ).catch(e => console.log(e)); - } - } -}); - -// Copy concentrated less files. -fs.copySync(path.resolve(sourcePath, 'style'), path.resolve(targetPath, 'style')); -fs.writeFileSync(`${targetPath}/components.less`, fs.readFileSync(`${sourcePath}/components.less`)); -fs.writeFileSync(`${targetPath}/ng-zorro-antd.less`, fs.readFileSync(`${sourcePath}/ng-zorro-antd.less`)); - -// Compile concentrated less file to CSS file. -const lessContent = `@import "${path.posix.join(targetPath, 'ng-zorro-antd.less')}";`; -compileLess(lessContent, path.join(targetPath, 'ng-zorro-antd.css'), false).catch(e => console.log(e)); -compileLess(lessContent, path.join(targetPath, 'ng-zorro-antd.min.css'), true).catch(e => console.log(e)); - -// Compile css file that doesn't have component-specific styles. -const cssIndexPath = path.join(sourcePath, 'style', 'entry.less'); -const cssIndex = fs.readFileSync(cssIndexPath, { encoding: 'utf8' }); -compileLess(cssIndex, path.join(targetPath, 'style', 'index.css'), false, true, cssIndexPath).catch(e => - console.log(e) -); -compileLess(cssIndex, path.join(targetPath, 'style', 'index.min.css'), true, true, cssIndexPath).catch(e => - console.log(e) -); diff --git a/scripts/build/compile-styles.ts b/scripts/build/compile-styles.ts new file mode 100644 index 0000000000..eb8669f030 --- /dev/null +++ b/scripts/build/compile-styles.ts @@ -0,0 +1,87 @@ +import * as fs from 'fs-extra'; +import * as less from 'less'; +import * as path from 'path'; +import { buildConfig } from '../build-config'; + +const LessPluginCleanCSS = require('less-plugin-clean-css'); +const NpmImportPlugin = require('less-plugin-npm-import'); + +function compileLess(content: string, savePath: string, min: boolean, sub?: boolean, rootPath?: string): Promise { + return new Promise((resolve, reject) => { + // tslint:disable-next-line:no-any + const plugins: any[] = []; + const lessOptions: Less.Options = { plugins: plugins, javascriptEnabled: true }; + + if (min) { + plugins.push(new LessPluginCleanCSS({ advanced: true })); + } + + if (sub) { + lessOptions.paths = [path.dirname(rootPath as string)]; + lessOptions.filename = rootPath; + plugins.push( + new NpmImportPlugin({ + prefix: '~' + }) + ); + } + + return less + .render(content, lessOptions) + .then(({ css }) => { + fs.writeFileSync(savePath, css); + resolve(); + }) + .catch(err => reject(err)); + }); +} + +const sourcePath = buildConfig.componentsDir; +const targetPath = buildConfig.publishDir; + +export function compile(): Promise { + const componentFolders = fs.readdirSync(targetPath); + const promiseList = []; + componentFolders.forEach((dir: string) => { + if (fs.existsSync(`${sourcePath}/${dir}/style/index.less`)) { + // Copy style files for each component. + fs.copySync(`${sourcePath}/${dir}/style`, `${targetPath}/${dir}/style`); + + // Compile less files to CSS and delete the `entry.less` file. + const buildFilePath = `${sourcePath}/${dir}/style/entry.less`; + if (fs.existsSync(buildFilePath)) { + promiseList.push(compileLess( + fs.readFileSync(buildFilePath, { encoding: 'utf8' }), + path.join(targetPath, dir, 'style', `index.css`), + false, + true, + buildFilePath + )); + promiseList.push(compileLess( + fs.readFileSync(buildFilePath, { encoding: 'utf8' }), + path.join(targetPath, dir, 'style', `index.min.css`), + true, + true, + buildFilePath + )); + } + } + }); + +// Copy concentrated less files. + fs.copySync(path.resolve(sourcePath, 'style'), path.resolve(targetPath, 'style')); + fs.writeFileSync(`${targetPath}/components.less`, fs.readFileSync(`${sourcePath}/components.less`)); + fs.writeFileSync(`${targetPath}/ng-zorro-antd.less`, fs.readFileSync(`${sourcePath}/ng-zorro-antd.less`)); + +// Compile concentrated less file to CSS file. + const lessContent = `@import "${path.posix.join(targetPath, 'ng-zorro-antd.less')}";`; + promiseList.push(compileLess(lessContent, path.join(targetPath, 'ng-zorro-antd.css'), false)); + promiseList.push(compileLess(lessContent, path.join(targetPath, 'ng-zorro-antd.min.css'), true)); + +// Compile css file that doesn't have component-specific styles. + const cssIndexPath = path.join(sourcePath, 'style', 'entry.less'); + const cssIndex = fs.readFileSync(cssIndexPath, { encoding: 'utf8' }); + promiseList.push(compileLess(cssIndex, path.join(targetPath, 'style', 'index.css'), false, true, cssIndexPath)); + promiseList.push(compileLess(cssIndex, path.join(targetPath, 'style', 'index.min.css'), true, true, cssIndexPath)); + return Promise.all(promiseList).catch(e => console.log(e)) +} diff --git a/scripts/build/migration-styles.js b/scripts/build/migration-styles.js deleted file mode 100644 index 321d2b20b3..0000000000 --- a/scripts/build/migration-styles.js +++ /dev/null @@ -1,12 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const sourcePath = path.resolve(__dirname, `../../publish`); -const targetPath = path.resolve(__dirname, `../../publish/src`); - -fs.mkdirsSync(targetPath); -fs.copySync(path.resolve(sourcePath, `style`), path.resolve(targetPath, `style`)); -fs.copySync(path.resolve(sourcePath, `ng-zorro-antd.css`), path.resolve(targetPath, `ng-zorro-antd.css`)); -fs.copySync(path.resolve(sourcePath, `ng-zorro-antd.min.css`), path.resolve(targetPath, `ng-zorro-antd.min.css`)); -fs.outputFileSync(path.resolve(targetPath, `ng-zorro-antd.less`), `@import "../style/entry.less"; -@import "../components.less";`); diff --git a/scripts/build/migration-styles.ts b/scripts/build/migration-styles.ts new file mode 100644 index 0000000000..755b4ef5ca --- /dev/null +++ b/scripts/build/migration-styles.ts @@ -0,0 +1,16 @@ +import * as fs from 'fs-extra'; +import * as path from 'path'; + +import { buildConfig } from '../build-config'; + +const sourcePath = buildConfig.publishDir; +const targetPath = path.join(buildConfig.publishDir, `src`); + +export function copyStylesToSrc(): void { + fs.mkdirsSync(targetPath); + fs.copySync(path.resolve(sourcePath, `style`), path.resolve(targetPath, `style`)); + fs.copySync(path.resolve(sourcePath, `ng-zorro-antd.css`), path.resolve(targetPath, `ng-zorro-antd.css`)); + fs.copySync(path.resolve(sourcePath, `ng-zorro-antd.min.css`), path.resolve(targetPath, `ng-zorro-antd.min.css`)); + fs.outputFileSync(path.resolve(targetPath, `ng-zorro-antd.less`), `@import "../style/entry.less"; +@import "../components.less";`); +} diff --git a/scripts/build/replace-publish.sh b/scripts/build/replace-publish.sh deleted file mode 100755 index 54ed94726c..0000000000 --- a/scripts/build/replace-publish.sh +++ /dev/null @@ -1,3 +0,0 @@ -sed 's/components\/ng-zorro-antd.module.ts/publish/g -s/components/publish/g' site/tsconfig.app.json > site/tsconfig.app.json_back -mv site/tsconfig.app.json_back site/tsconfig.app.json diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts new file mode 100644 index 0000000000..e61b80157a --- /dev/null +++ b/scripts/gulp/gulpfile.ts @@ -0,0 +1,14 @@ +// tslint:disable:no-import-side-effect +import { series, task } from 'gulp'; +import './tasks/clean'; +import './tasks/default'; +import './tasks/schematic'; +import './tasks/universal'; + +import './tasks/library'; +import './tasks/site'; + +task('build:release', series( + 'build:library', + 'build:release-site' +)); diff --git a/scripts/gulp/tasks/clean.ts b/scripts/gulp/tasks/clean.ts new file mode 100644 index 0000000000..a67f55a5ee --- /dev/null +++ b/scripts/gulp/tasks/clean.ts @@ -0,0 +1,6 @@ +import { task } from 'gulp'; +import { buildConfig } from '../../build-config'; +import { cleanTask } from '../util/task-helpers'; + +/** Deletes the dist/ publish/ directory. */ +task('clean', cleanTask([buildConfig.outputDir, buildConfig.publishDir])); diff --git a/scripts/gulp/tasks/default.ts b/scripts/gulp/tasks/default.ts new file mode 100644 index 0000000000..1e9bf90ae3 --- /dev/null +++ b/scripts/gulp/tasks/default.ts @@ -0,0 +1,6 @@ +import { task } from 'gulp'; + +task('default', done => { + console.log(1); + done(); +}); diff --git a/scripts/gulp/tasks/library.ts b/scripts/gulp/tasks/library.ts new file mode 100644 index 0000000000..5353a40760 --- /dev/null +++ b/scripts/gulp/tasks/library.ts @@ -0,0 +1,32 @@ +import { dest, parallel, series, src, task } from 'gulp'; +import { join } from 'path'; +import { buildConfig } from '../../build-config'; +import { compile as compileLess } from '../../build/compile-styles'; +import { copyStylesToSrc } from '../../build/migration-styles'; +import { execNodeTask } from '../util/task-helpers'; + +/** Run `ng build ng-zorro-antd-lib` */ +task('library:build-zorro', execNodeTask( + '@angular/cli', + 'ng', + [ 'build', 'ng-zorro-antd-lib' ] +)); + +// Compile less to the public directory. +task('library:compile-less', done => { + compileLess().then(() => { + copyStylesToSrc(); + done(); + }); +}); + +// Copies README.md file to the public directory. +task('library:copy-resources', () => { + return src(join(buildConfig.projectDir, 'README.md')) + .pipe(dest(join(buildConfig.publishDir))) +}); + +task('build:library', series( + 'library:build-zorro', + parallel('library:compile-less', 'library:copy-resources', 'build:schematics') +)); diff --git a/scripts/gulp/tasks/release.ts b/scripts/gulp/tasks/release.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/gulp/tasks/schematic.ts b/scripts/gulp/tasks/schematic.ts new file mode 100644 index 0000000000..f306cd9567 --- /dev/null +++ b/scripts/gulp/tasks/schematic.ts @@ -0,0 +1,48 @@ +import { series, task } from 'gulp'; +import { join } from "path"; +import { buildConfig } from '../../build-config'; + +import { copyResources } from '../../schematics/copy-resources'; +import { generate as demo2schematics } from '../../schematics/demo2schematics'; +import { setTheme } from '../../schematics/set-theme'; +import { setVersion } from '../../schematics/set-version'; +import { cleanTask, execNodeTask } from '../util/task-helpers'; + +const schematicsDir = join(buildConfig.projectDir, 'schematics'); +const tsconfigFile = join(schematicsDir, 'tsconfig.json'); +const cleanGlob = [ + join(schematicsDir, 'demo'), + join(schematicsDir, 'utils/+(create-custom-theme|version-names).ts') +]; + +/** Generate the schematics in the schematics directory */ +task('generate:schematics', done => { + demo2schematics(); + setTheme(); + setVersion(); + done() +}); + +/** Build the schematics in the publish directory. */ +task('tsc:schematics', execNodeTask( + 'typescript', + 'tsc', + [ '-p', tsconfigFile ] +)); + +/** Copies all resources files to the publish directory. */ +task('schematics:copy-resources', done => { + copyResources(); + done(); +}); + +/** Deletes the schematics/ directory and utils/(create-custom-theme|version-names).ts. files */ +task('clean:schematics', cleanTask(cleanGlob)); + +/** Task that run the generate script and builds the schematics in the publish directory. */ +task('build:schematics', series( + 'generate:schematics', + 'tsc:schematics', + 'schematics:copy-resources', + 'clean:schematics' +)); diff --git a/scripts/gulp/tasks/site.ts b/scripts/gulp/tasks/site.ts new file mode 100644 index 0000000000..ebfaefb566 --- /dev/null +++ b/scripts/gulp/tasks/site.ts @@ -0,0 +1,107 @@ +import { parallel, series, task, watch } from 'gulp'; +import * as fs from 'fs-extra'; +import { join } from 'path'; +import { execNodeTask, execTask } from '../util/task-helpers'; + +import { buildConfig } from '../../build-config'; + +const siteGenerate = require('../../site/generate-site'); +const colorGenerate = require('../../site/generateColorLess'); + +const docsGlob = join(buildConfig.componentsDir, `**/doc/*.+(md|txt)`); +const demoGlob = join(buildConfig.componentsDir, `**/demo/*.+(md|ts)`); +const issueHelperScriptFile = join(buildConfig.scriptsDir, 'release-helper.sh'); +const tsconfigFile = join(buildConfig.projectDir, 'site/tsconfig.app.json'); + +/** + * Development app watch task, + * to ensures the demos and docs have changes are rebuild. + */ +task('watch:site', () => { + watch([docsGlob, demoGlob], {delay: 700}) + .on('change', path => { + const execArray = /components\/(.+)\/(doc|demo)/.exec(path); + if (execArray && execArray[1]) { + const component = execArray[1]; + console.log(`Reload '${component}'`); + siteGenerate(component); + } + }) +}); + +/** Parse demos and docs to site directory. */ +task('init:site', done => { + siteGenerate('init'); + colorGenerate().then(() => { + done(); + }); +}); + +/** Run `ng serve --port 0` */ +task('serve:site', execNodeTask( + '@angular/cli', + 'ng', + [ 'serve', '--port', '0' ] +)); + +/** Run `ng build --prod --project=ng-zorro-antd-doc` */ +task('build:site-doc', execNodeTask( + '@angular/cli', + 'ng', + [ 'build', '--project=ng-zorro-antd-doc', '--prod' ] +)); + +/** Run `ng build --prod --base-href ./ --project=ng-zorro-antd-iframe` */ +task('build:site-iframe', execNodeTask( + '@angular/cli', + 'ng', + [ 'build', '--project=ng-zorro-antd-iframe', '--prod', '--base-href=./' ] +)); + +/** Replace the library paths to publish/ directory */ +task('site:replace-path', () => { + // tslint:disable-next-line:no-any + const tsconfig: any = fs.readJSONSync(tsconfigFile); + tsconfig.compilerOptions.paths['ng-zorro-antd'] = ['../publish']; + tsconfig.compilerOptions.paths['ng-zorro-antd/*'] = ['../publish/*'] + return fs.writeJSON(tsconfigFile, tsconfig); +}); + +/** Run release-helper.sh + * Clone issue-helper builds from github and copy to the output directory. + */ +task('build:site-issue-helper', execTask( + 'bash', + [issueHelperScriptFile] +)); + +/** Build all site projects to the output directory. */ +task('build:site', series( + 'build:site-doc', + 'build:site-iframe', + 'build:site-issue-helper' +)); + +/** Init site directory, and start watch and ng-serve */ +task('start:site', series( + 'init:site', + parallel('watch:site', 'serve:site') +)); + +/** Task that use source code to build ng-zorro-antd-doc project, + * output not included issue-helper/iframe and prerender. + */ +task('build:overview-site', series( + 'init:site', + 'build:site-doc' +)); + +/** Task that use publish code to build ng-zorro-antd-doc project, + * output included issue-helper/iframe and prerender. + */ +task('build:release-site', series( + 'init:site', + 'site:replace-path', + 'build:site', + 'prerender' +)); diff --git a/scripts/gulp/tasks/universal.ts b/scripts/gulp/tasks/universal.ts new file mode 100644 index 0000000000..1be5cc06f8 --- /dev/null +++ b/scripts/gulp/tasks/universal.ts @@ -0,0 +1,34 @@ +import { parallel, series, task } from 'gulp'; +import { join } from 'path'; +import { buildConfig } from '../../build-config'; +import { execNodeTask, execTask } from '../util/task-helpers'; + +const tsconfigFile = join(buildConfig.scriptsDir, 'prerender', 'tsconfig.json'); +const prerenderScript = join(buildConfig.outputDir, 'prerender', 'prerender.js'); +const sitemapScript = join(buildConfig.outputDir, 'prerender', 'sitemap.js'); + +/** Build the universal app in the output directory. */ +task('universal:build-app', execNodeTask( + '@angular/cli', + 'ng', + [ 'run', 'ng-zorro-antd-doc:server:production' ] +)); + +/** Build the prerender script in the output directory. */ +task('universal:build-prerender-ts', execNodeTask( + 'typescript', + 'tsc', + [ '-p', tsconfigFile ] +)); + +/** Run prerender script on the output directory, to render static html. */ +task(':run:prerender', execTask('node', [prerenderScript])); + +/** Run sitemap script on the output directory, to create sitemap.xml */ +task(':run:sitemap', execTask('node', [sitemapScript])); + +/** Parallel run sitemap and prerender scripts */ +task('run:prerender', parallel(':run:prerender', ':run:sitemap')); + +/** Task that builds the universal-app and runs the prerender and sitemap script. */ +task('prerender', series('universal:build-app', 'universal:build-prerender-ts', 'run:prerender')); diff --git a/scripts/gulp/tsconfig.json b/scripts/gulp/tsconfig.json new file mode 100644 index 0000000000..4a8f714559 --- /dev/null +++ b/scripts/gulp/tsconfig.json @@ -0,0 +1,25 @@ + +{ + "compilerOptions": { + "experimentalDecorators": true, + "noUnusedParameters": true, + "noUnusedLocals": true, + "lib": ["es2015", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "outDir": "../../dist", + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "noEmitOnError": true, + "noImplicitAny": true, + "target": "es5", + "types": [ + "node" + ], + "baseUrl": "." + }, + "files": [ + "gulpfile.ts" + ] +} \ No newline at end of file diff --git a/scripts/gulp/util/task-helpers.ts b/scripts/gulp/util/task-helpers.ts new file mode 100644 index 0000000000..4fee08be34 --- /dev/null +++ b/scripts/gulp/util/task-helpers.ts @@ -0,0 +1,70 @@ +import * as child_process from 'child_process'; +import * as gulp from 'gulp'; +const gulpClean = require('gulp-clean'); +const resolveBin = require('resolve-bin'); + +/** Options that can be passed to execTask or execNodeTask. */ +export interface ExecTaskOptions { + // Whether STDOUT and STDERR messages should be printed. + silent?: boolean; + // Whether STDOUT messages should be printed. + silentStdout?: boolean; + // If an error happens, this will replace the standard error. + errMessage?: string; + // Environment variables being passed to the child process. + // tslint:disable-next-line:no-any + env?: any; + // Whether the task should fail if the process writes to STDERR. + failOnStderr?: boolean; +} + +export function cleanTask(glob: string | string[]) { + return () => gulp.src(glob, { read: false, allowEmpty: true }).pipe(gulpClean(null)); +} + +export function execTask(binPath: string, args: string[], options: ExecTaskOptions = {}) { + return (done: (err?: string) => void) => { + const env = {...process.env, ...options.env}; + const childProcess = child_process.spawn(binPath, args, {env}); + const stderrData: string[] = []; + + if (!options.silentStdout && !options.silent) { + childProcess.stdout.on('data', (data: string) => process.stdout.write(data)); + } + + if (!options.silent || options.failOnStderr) { + childProcess.stderr.on('data', (data: string) => { + options.failOnStderr ? stderrData.push(data) : process.stderr.write(data); + }); + } + + childProcess.on('close', (code: number) => { + if (options.failOnStderr && stderrData.length) { + done(stderrData.join('\n')); + } else { + // tslint:disable-next-line:triple-equals + code != 0 ? done(options.errMessage || `Process failed with code ${code}`) : done(); + } + }); + }; +} + +export function execNodeTask(packageName: string, executable: string | string[], args?: string[], + options: ExecTaskOptions = {}) { + if (!args) { + args = executable as string[]; + executable = ''; + } + + // tslint:disable-next-line:no-any + return (done: (err: any) => void) => { + // tslint:disable-next-line:no-any + resolveBin(packageName, { executable: executable }, (err: any, binPath: string) => { + if (err) { + done(err); + } else { + execTask('node', ['--max_old_space_size=5120', binPath].concat(args!), options)(done); + } + }); + }; +} \ No newline at end of file diff --git a/scripts/prerender/prerender.ts b/scripts/prerender/prerender.ts index cf1135152e..98ce9a78b5 100644 --- a/scripts/prerender/prerender.ts +++ b/scripts/prerender/prerender.ts @@ -1,10 +1,19 @@ +// tslint:disable:no-import-side-effect + // Load zone.js for the server. +import { enableProdMode } from '@angular/core'; import { ensureDirSync, readFileSync, writeFileSync } from 'fs-extra'; import { join } from 'path'; import 'reflect-metadata'; import 'zone.js/dist/zone-node'; -import { enableProdMode } from '@angular/core'; +// Import module map for lazy loading +import { renderModuleFactory } from '@angular/platform-server'; +import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; +import { ROUTES } from './static.paths'; + +import { buildConfig } from '../build-config'; + // Faster server renders w/ Prod mode (dev mode never needed) enableProdMode(); @@ -12,18 +21,15 @@ enableProdMode(); // tslint:disable-next-line no-string-literal global['Event'] = null; -// Import module map for lazy loading -import { renderModuleFactory } from '@angular/platform-server'; -import { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader'; -import { ROUTES } from './static.paths'; +const serverMainFile = join(buildConfig.outputDir, 'server/main'); // * NOTE :: leave this as require() since this file is built Dynamically from webpack -const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./server/main'); +const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require(serverMainFile); -const BROWSER_FOLDER = join(process.cwd(), '/'); +const BROWSER_FOLDER = buildConfig.outputDir; // Load the index.html file containing referances to your application bundle. -const index = readFileSync(join('./', 'index.html'), 'utf8'); +const index = readFileSync(join(buildConfig.outputDir, 'index.html'), 'utf8'); let previousRender = Promise.resolve(); @@ -35,7 +41,6 @@ ROUTES.forEach(route => { // Make sure the directory structure is there ensureDirSync(fullPath); - // Writes rendered HTML to index.html, replacing the file if it already exists. previousRender = previousRender .then(_ => diff --git a/scripts/prerender/sitemap.ts b/scripts/prerender/sitemap.ts index c994d9909b..8b5ab24099 100644 --- a/scripts/prerender/sitemap.ts +++ b/scripts/prerender/sitemap.ts @@ -1,7 +1,10 @@ -import * as sitemap from 'sitemap'; import { writeFileSync } from 'fs'; +import { join } from 'path'; +import * as sitemap from 'sitemap'; import { ROUTES } from './static.paths'; +import { buildConfig } from '../build-config'; + const urls = Array.from(new Set(ROUTES.filter(r => r !== '/').map(r => r.replace(/\/(zh|en)$/, '')))).map( (r: string) => { return { @@ -19,4 +22,4 @@ const sitemapInstance = sitemap.createSitemap({ urls: [{ url: '/', changefreq: 'weekly', priority: 0.5, lastmodrealtime: true }, ...urls] }); -writeFileSync('sitemap.xml', sitemapInstance.toString()); +writeFileSync(join(buildConfig.outputDir, 'sitemap.xml'), sitemapInstance.toString()); diff --git a/scripts/publish/publish.js b/scripts/publish/publish.js deleted file mode 100644 index f4fcc80191..0000000000 --- a/scripts/publish/publish.js +++ /dev/null @@ -1,161 +0,0 @@ -const chalk = require('chalk'); -const fs = require('fs-extra'); -const read = require('readline-sync'); -const path = require('path'); - -/* Shortcut methods */ -const execSync = require('child_process').execSync; -const versionNameRegex = /^(\d+)\.(\d+)\.(\d+)(?:-(alpha|beta|rc)\.(\d+))?$/; -const print = console.log; -const log = { - info : (msg) => { - print(chalk.bgBlue.black('INFO'), chalk.blue(msg)); - }, - warn : (msg) => { - print(chalk.bgYellow.black('WARN'), chalk.yellow(msg)); - }, - error : (msg) => { - print(chalk.bgRed.black('ERROR'), chalk.red(msg)); - }, - success: (msg) => { - print(chalk.bgGreen.black('SUCCESS'), chalk.green(msg)); - } -}; - -/* The whole process */ - -log.info('Starting publishing process...'); - -let nextVersion; - -fetchOlderVersions(); -changeVersion(); -generatingPublishNote(); -preRelease(); -checkout(); - -// publish(); - -/** - * Publisher should input the new version number. This script would check if the input is valid. - */ -function changeVersion() { - log.info('Updating version number...'); - - const packageJsonPath = path.join(__dirname, '../../components/package.json'); - const appComponentPath = path.join(__dirname, '../site/_site/doc/app/app.component.ts'); - const codeBoxPath = path.join(__dirname, '../site/_site/doc/app/share/nz-codebox/stack-blitz.ts'); - const zorroVersionPath = path.join(__dirname, '../../components/version.ts'); - - const packageJson = fs.readJsonSync(packageJsonPath); - const currentVersion = packageJson.version; - let versionNumberValid = false; - let version; - - function parseVersion(version) { - const matches = version.match(versionNameRegex); - - if (!matches) { - return null; - } - - return { - major : Number(matches[1]), - minor : Number(matches[2]), - patch : Number(matches[3]), - preTag: matches[4], - pre : Number(matches[5]), - } - } - - function checkVersionNumber(cur, next) { - // Must be numbers and dots. - if (!versionNameRegex.test(next)) { - return false; - } - - const curVersion = parseVersion(cur); - const nextVersion = parseVersion(next); - - for (const k of ['major', 'minor', 'patch']) { - if (curVersion[k] < nextVersion[k]) { - return true; - } - - if (curVersion[k] > nextVersion[k]) { - return false; - } - } - - if (curVersion.preTag !== nextVersion.preTag) { - return true; - } - - return curVersion.pre < nextVersion.pre - } - - while (!versionNumberValid) { - version = read.question(chalk.bgYellow.black('Please input the new version:') + ' '); - if (checkVersionNumber(currentVersion, version)) { - versionNumberValid = true; - nextVersion = version; - } else { - log.error(`Your input ${version} is not after the current version ${currentVersion} or is unvalid. Please check it.`); - } - } - - fs.writeJsonSync(packageJsonPath, {...packageJson, version: version}, {spaces: 2}); - fs.writeFileSync(appComponentPath, - fs.readFileSync(appComponentPath, 'utf-8') - .replace(/currentVersion = '.+';/g, `currentVersion = '${version}';`) - ); - fs.writeFileSync(codeBoxPath, - fs.readFileSync(codeBoxPath, 'utf-8').replace(/'ng-zorro-antd'\s*: '.+'/g, `'ng-zorro-antd': '^${version}'`) - ); - fs.writeFileSync(zorroVersionPath, - fs.readFileSync(zorroVersionPath, 'utf-8') - .replace(/Version\('.+'\);/g, `Version('${version}');`) - ); - log.success('Version updated!'); -} - -function fetchOlderVersions() { - log.info('Fetching older versions...'); - execSync('git checkout master'); - execSync('git pull upstream master'); - execSync('git fetch upstream master --prune --tags'); - log.success('Older versions fetched!'); -} - -function generatingPublishNote() { - log.info('Generating changelog...'); - execSync('npm run changelog'); - log.success('Changelog generated!'); - - let completeEditing = false; - - while (!completeEditing) { - const result = read.question(chalk.bgYellow.black('Please manually update docs/changelog. Press [Y] if you are done:') + ' '); - if (result.trim().toLowerCase() === 'y') { - completeEditing = true; - } - } - - log.success('Change log finished!'); -} - -function preRelease() { - log.info('Running pre-release script... Be patient...'); - execSync('npm run pre-release', {stdio: [0, 1, 2]}); - log.info('pre-release completed!'); -} - -function checkout() { - log.info('Checkout and push a new branch for publishing...'); - execSync(`git checkout -b publish-${nextVersion}`); - execSync('git add .'); - execSync(`git commit -m "release(${nextVersion}): release ${nextVersion}"`); - execSync(`git push origin publish-${nextVersion}`); - log.success('Please go to GitHub and make a pull request.'); - log.success('Bye!'); -} diff --git a/scripts/release/parse-version.ts b/scripts/release/parse-version.ts new file mode 100644 index 0000000000..24ef402b4a --- /dev/null +++ b/scripts/release/parse-version.ts @@ -0,0 +1,62 @@ + +export interface Version { + major: number; + minor: number; + patch: number; + preTag: string; + pre: number; +} + +const versionNameRegex = /^(\d+)\.(\d+)\.(\d+)(?:-(alpha|beta|rc)\.(\d+))?$/; + +export function validVerison(version: string): boolean { + return versionNameRegex.test(version) +} + +export function parseVersion(version: string): Version | null { + const matches = version.match(versionNameRegex); + + if (!matches) { + return null; + } + + return { + major : Number(matches[1]), + minor : Number(matches[2]), + patch : Number(matches[3]), + preTag: matches[4], + pre : Number(matches[5]) + } +} + +export function checkVersionNumber(cur: string, next: string): boolean { + // Must be numbers and dots. + if (!validVerison(next)) { + return false; + } + + const curVersion = parseVersion(cur); + const nextVersion = parseVersion(next); + + if (!nextVersion || !curVersion) { + return false + } + + if (curVersion.major !== nextVersion.major) { + return curVersion.major < nextVersion.major; + } + + if (curVersion.minor !== nextVersion.minor) { + return curVersion.minor < nextVersion.minor; + } + + if (curVersion.patch !== nextVersion.patch) { + return curVersion.patch < nextVersion.patch; + } + + if (curVersion.preTag !== nextVersion.preTag) { + return true; + } + + return curVersion.pre < nextVersion.pre +} diff --git a/scripts/release/release.ts b/scripts/release/release.ts new file mode 100644 index 0000000000..ddf54b69d2 --- /dev/null +++ b/scripts/release/release.ts @@ -0,0 +1,185 @@ +import chalk from 'chalk'; +import { execSync, spawnSync } from 'child_process'; +import * as fs from 'fs-extra'; +import * as path from 'path'; +import { buildConfig } from '../build-config'; +import { checkVersionNumber } from './parse-version'; + +const read = require('readline-sync'); + +/* Shortcut methods */ +const print = console.log; +const log = { + info: (msg: string) => print(chalk.bgBlue.black(' INFO\t'), chalk.blue(msg)), + warn: (msg: string) => print(chalk.bgYellow.black(' WARN\t'), chalk.yellow(msg)), + error: (msg: string) => print(chalk.bgRed.black(' ERROR\t'), chalk.red(msg)), + success: (msg: string) => print(chalk.bgGreen.black(' SUCCESS\t'), chalk.green(msg)) +}; + +/* The whole process */ + +let releaseVersion: string; + +run(); + +function run(): void { + if (hasUncommittedChanges()) { + log.error('Current working tree has changes which are not committed. ' + + 'Please make sure your working tree is clean.'); + return; + } + const stages = [ + { + name: 'Fetch upstream', + fun: fetchUpstream + }, + { + name: 'Bump version', + fun: bumpVersion + }, + { + name: 'Update changelog', + fun: updateChangelog + }, + { + name: 'Build release', + fun: buildRelease + }, + { + name: 'Push release', + fun: pushRelease + } + ]; + + let index = read.keyInSelect(stages.map(e => e.name), 'Where do you want to start?'); + if (index === -1) { + return; + } + log.info('Starting publishing process...'); + for (index; index < stages.length; index++) { + stages[index].fun(); + } +} + +/** git has uncommitted changes */ +function hasUncommittedChanges(): boolean { + const output = spawnSync('git', + ['diff-index', '--quiet', 'HEAD'], + { + encoding: 'utf-8' + }); + return output.status !== 0 +} + +function getUpstreamRemoteName(): string | null { + const output = spawnSync('git', + ['remote', 'show'], + { + encoding: 'utf-8' + }); + const names: string[] = output.stdout.split('\n').map((e: string) => e.trim()); + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < names.length; i++) { + const url = getRemoteUrl(names[i]); + if (url.search('github.com/NG-ZORRO/ng-zorro-antd') !== -1) { + return names[i]; + } + } + return null; +} + +function getRemoteUrl(remote: string): string { + const output = spawnSync('git', + ['remote', 'get-url', remote], + { + encoding: 'utf-8' + }); + return output.stdout.trim(); +} + +/** + * Publisher should input the new version number. This script would check if the input is valid. + */ +function bumpVersion(): void { + log.info('Updating version number...'); + + const packageJsonPath = path.join(buildConfig.componentsDir, 'package.json'); + const appComponentPath = path.join(buildConfig.scriptsDir, 'site/_site/doc/app/app.component.ts'); + const codeBoxPath = path.join(buildConfig.scriptsDir, 'site/_site/doc/app/share/nz-codebox/stack-blitz.ts'); + const zorroVersionPath = path.join(buildConfig.componentsDir, 'version.ts'); + + const packageJson = fs.readJsonSync(packageJsonPath); + const currentVersion = packageJson.version; + let versionNumberValid = false; + let version; + + while (!versionNumberValid) { + version = read.question(chalk.bgYellow.black('Please input the new version:') + ' '); + if (checkVersionNumber(currentVersion, version)) { + versionNumberValid = true; + releaseVersion = version; + } else { + log.error(`Your input ${version} is not after the current version ${currentVersion} or is unvalid. Please check it.`); + } + } + + fs.writeJsonSync(packageJsonPath, {...packageJson, version: version}, {spaces: 2}); + fs.writeFileSync(appComponentPath, + fs.readFileSync(appComponentPath, 'utf-8') + .replace(/currentVersion = '.+';/g, `currentVersion = '${version}';`) + ); + fs.writeFileSync(codeBoxPath, + fs.readFileSync(codeBoxPath, 'utf-8').replace(/'ng-zorro-antd'\s*: '.+'/g, `'ng-zorro-antd': '^${version}'`) + ); + fs.writeFileSync(zorroVersionPath, + fs.readFileSync(zorroVersionPath, 'utf-8') + .replace(/Version\('.+'\);/g, `Version('${version}');`) + ); + log.success('Version updated!'); +} + +function fetchUpstream(): void { + log.info('Fetching upstream...'); + const remoteName = getUpstreamRemoteName(); + if (!remoteName) { + log.error('The valid remote name does not exist. View detail https://help.github.com/en/articles/configuring-a-remote-for-a-fork'); + return; + } + execSync('git checkout master'); + execSync(`git pull ${remoteName} master`); + execSync(`git fetch ${remoteName} master --prune --tags`); + log.success('Older versions fetched!'); +} + +function updateChangelog(): void { + log.info('Generating changelog...'); + execSync('npm run changelog'); + log.success('Changelog generated!'); + + let completeEditing = false; + + while (!completeEditing) { + const result = read.question(chalk.bgYellow.black('Please manually update docs/changelog. Press [Y] if you are done:') + ' '); + if (result.trim().toLowerCase() === 'y') { + completeEditing = true; + } + } + + log.success('Change log finished!'); +} + +function buildRelease(): void { + log.info('Running pre-release script... Be patient...'); + execSync('npm run build', {stdio: [0, 1, 2]}); + log.info('pre-release completed!'); +} + +function pushRelease(): void { + log.info('Checkout and push a new branch for publishing...'); + execSync(`git checkout -b publish-${releaseVersion}`); + execSync('git add .'); + execSync(`git commit -m "release(${releaseVersion}): release ${releaseVersion}"`); + execSync(`git push origin publish-${releaseVersion}`); + log.success('Please go to GitHub and make a pull request.'); + log.success('Bye!'); +} diff --git a/scripts/release/tsconfig.json b/scripts/release/tsconfig.json new file mode 100644 index 0000000000..65a1ff1890 --- /dev/null +++ b/scripts/release/tsconfig.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "lib": ["es2016"], + "types": ["node"] + } +} \ No newline at end of file diff --git a/scripts/schematics/copy-resources.js b/scripts/schematics/copy-resources.js deleted file mode 100644 index 0e78cf419b..0000000000 --- a/scripts/schematics/copy-resources.js +++ /dev/null @@ -1,22 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const srcPath = path.resolve(__dirname, `../../schematics`); -const targetPath = path.resolve(__dirname, `../../publish/schematics`); -const copyFilter = (path) => (/files\/__path__/.test(path) || (!/.+\.ts/.test(path))); - - -function mergeDemoCollection() { - const demoCollectionPath = path.resolve(targetPath, `demo/collection.json`); - const targetCollectionPath = path.resolve(targetPath, `collection.json`); - const demoCollectionJson = fs.readJsonSync(demoCollectionPath, { throws: false }) || {schematics: {}}; - const targetCollectionJson = fs.readJsonSync(targetCollectionPath, { throws: false }) || {schematics: {}}; - targetCollectionJson.schematics = Object.assign(targetCollectionJson.schematics, { - ...demoCollectionJson.schematics - }); - fs.outputJsonSync(targetCollectionPath, targetCollectionJson); - fs.removeSync(demoCollectionPath) -} - -fs.copySync(srcPath, targetPath, { filter: copyFilter }); -mergeDemoCollection(); \ No newline at end of file diff --git a/scripts/schematics/copy-resources.ts b/scripts/schematics/copy-resources.ts new file mode 100644 index 0000000000..70752f2524 --- /dev/null +++ b/scripts/schematics/copy-resources.ts @@ -0,0 +1,25 @@ +import * as fs from 'fs-extra'; +import * as path from 'path'; +import { buildConfig } from '../build-config'; + +const srcPath = path.join(buildConfig.projectDir, `schematics`); +const targetPath = path.join(buildConfig.publishDir, `schematics`); +const copyFilter = (p: string) => (/files\/__path__/.test(p) || (!/.+\.ts/.test(p))); + +function mergeDemoCollection(): void { + const demoCollectionPath = path.resolve(targetPath, `demo/collection.json`); + const targetCollectionPath = path.resolve(targetPath, `collection.json`); + const demoCollectionJson = fs.readJsonSync(demoCollectionPath, { throws: false }) || {schematics: {}}; + const targetCollectionJson = fs.readJsonSync(targetCollectionPath, { throws: false }) || {schematics: {}}; + targetCollectionJson.schematics = { + ...targetCollectionJson.schematics, + ...demoCollectionJson.schematics + }; + fs.outputJsonSync(targetCollectionPath, targetCollectionJson); + fs.removeSync(demoCollectionPath) +} + +export function copyResources(): void { + fs.copySync(srcPath, targetPath, { filter: copyFilter }); + mergeDemoCollection(); +} diff --git a/scripts/schematics/demo2schematics.js b/scripts/schematics/demo2schematics.ts similarity index 75% rename from scripts/schematics/demo2schematics.js rename to scripts/schematics/demo2schematics.ts index 12142a1011..8dff2a09ce 100644 --- a/scripts/schematics/demo2schematics.js +++ b/scripts/schematics/demo2schematics.ts @@ -1,10 +1,22 @@ -const fs = require('fs-extra'); -const path = require('path'); +import * as fs from 'fs-extra'; +import * as path from 'path'; +import { buildConfig } from '../build-config'; + const glob = require('glob').sync; -const componentsPath = path.resolve(__dirname, '../../components'); -const demoDirPath = path.resolve(__dirname, '../../schematics/demo'); -const collectionPath = path.resolve(__dirname, '../../schematics/demo/collection.json'); +interface DemoMeta { + fileContent: string, + componentName: string, + demoName: string, + template: string, + styles: string, + selector: string, + className: string +} + +const componentsPath = buildConfig.componentsDir; +const demoDirPath = path.join(buildConfig.projectDir, 'schematics/demo'); +const collectionPath = path.join(demoDirPath, 'collection.json'); const TEST_FILE_CONTENT = `import { fakeAsync, ComponentFixture, TestBed } from '@angular/core/testing'; @@ -31,18 +43,11 @@ describe('<%= classify(name) %>Component', () => { }); `; -/** - * @returns {string[]} - */ -function getComponentPaths() { +function getComponentPaths(): string[] { return glob(path.join(componentsPath, '**/demo/*.ts')) } -/** - * @param {string} filePath - * @returns {{fileContent: string, componentName: string, demoName: string, template: string, styles: string, selector: string, className: string}} - */ -function parse(filePath) { +function parse(filePath: string): DemoMeta { const fileContent = fs.readFileSync(filePath, 'utf-8'); const pathSplitted = filePath.split('components/')[1].split('/'); const componentName = pathSplitted[0] || ''; @@ -62,43 +67,27 @@ function parse(filePath) { } } -/** - * @param {string} fileContent - * @returns {string} - */ -function getTemplate(fileContent) { +function getTemplate(fileContent: string): string { const match = fileContent.match(/template\s*:\s*`([\s\S]*?)`/); return match ? match[1] || '' : ''; } -/** - * @param {string} fileContent - * @returns {string} - */ -function getStyles(fileContent) { +function getStyles(fileContent: string): string { const match = fileContent.match(/styles\s*:\s*\[\s*`([\s\S]*?)`\s*\]/); return match ? match[1] || '' : ''; } -/** - * @param {string} fileContent - * @returns {string} - */ -function getClassName(fileContent) { +function getClassName(fileContent: string): string { const match = fileContent.match(/export\s*class\s*(.+?)\s.*/); return match ? match[1] || '' : ''; } -/** - * @param {string} fileContent - * @returns {string} - */ -function getSelector(fileContent) { +function getSelector(fileContent: string): string { const match = fileContent.match(/selector\s*:\s*'(.+?)'\s*/); return match ? match[1] || '' : ''; } -function replaceTemplate(demoComponent) { +function replaceTemplate(demoComponent: DemoMeta): string { return demoComponent.fileContent .replace(/selector\s*:\s*'(.+?)'\s*/, () => `selector: '<%= selector %>'`) .replace(new RegExp(demoComponent.className), () => `<%= classify(name) %>Component`) @@ -106,10 +95,7 @@ function replaceTemplate(demoComponent) { .replace(/template\s*:\s*`([\s\S]*?)`/, () => `<% if(inlineTemplate) { %>template: \`${demoComponent.template}\`<% } else { %>templateUrl: './<%= dasherize(name) %>.component.html'<% } %>`) } -/** - * @param {{fileContent: string, componentName: string, demoName: string, template: string, styles: string, selector: string, className: string}} demoComponent - */ -function createSchematic(demoComponent) { +function createSchematic(demoComponent: DemoMeta): void { const demoPath = path.resolve(demoDirPath, `./${demoComponent.componentName}-${demoComponent.demoName}`); const filesPath = path.resolve(__dirname, `${demoPath}/files/__path__/__name@dasherize@if-flat__`); const schemaPath = `${demoPath}/schema.json`; @@ -130,27 +116,25 @@ function createSchematic(demoComponent) { fs.outputFileSync(`${filesPath}/__name@dasherize__.component.ts`, replaceTemplate(demoComponent)); const collectionJson = fs.readJsonSync(collectionPath, { throws: false }) || {schematics: {}}; - collectionJson.schematics = Object.assign(collectionJson.schematics, { + collectionJson.schematics = { + ...collectionJson.schematics, [`${demoComponent.componentName}-${demoComponent.demoName}`]: { description: schemaJson.title, factory: `./demo/${demoComponent.componentName}-${demoComponent.demoName}`, schema: `./demo/${demoComponent.componentName}-${demoComponent.demoName}/schema.json` - }, - }); + }}; fs.outputJsonSync(collectionPath, collectionJson, {spaces: ' '}); } -function generate() { +export function generate(): void { const componentPath = getComponentPaths(); - componentPath.forEach(path => { + componentPath.forEach(p => { try { - createSchematic(parse(path)) + createSchematic(parse(p)) } catch (e) { - console.error(`error ${path}`); + console.error(`error ${p}`); console.error(e); } }); console.log(`success(${componentPath.length})`) } - -generate(); diff --git a/scripts/schematics/set-theme.js b/scripts/schematics/set-theme.js deleted file mode 100644 index 3dab70f3cc..0000000000 --- a/scripts/schematics/set-theme.js +++ /dev/null @@ -1,13 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const theme = fs.readFileSync(path.resolve(__dirname, `../site/_site/doc/theme.less`), 'utf8'); -fs.outputFileSync( - path.resolve(__dirname, `../../schematics/utils/create-custom-theme.ts`), -`export function createCustomTheme(): string { - return \`@import "../node_modules/ng-zorro-antd/ng-zorro-antd.less"; -${theme.replace(/`/g, '\\`')} -\`; -} -` -); diff --git a/scripts/schematics/set-theme.ts b/scripts/schematics/set-theme.ts new file mode 100644 index 0000000000..ba5eda975c --- /dev/null +++ b/scripts/schematics/set-theme.ts @@ -0,0 +1,16 @@ +import * as fs from 'fs-extra'; +import * as path from 'path'; +import { buildConfig } from '../build-config'; + +const theme = fs.readFileSync(path.join(buildConfig.scriptsDir, `site/_site/doc/theme.less`), 'utf8'); + +export function setTheme(): void { + fs.outputFileSync( + path.join(buildConfig.projectDir, `schematics/utils/create-custom-theme.ts`), + `export function createCustomTheme(): string { + return \`@import "../node_modules/ng-zorro-antd/ng-zorro-antd.less"; +${theme.replace(/`/g, '\\`')} +\`; +} +`); +} diff --git a/scripts/schematics/set-version.js b/scripts/schematics/set-version.js deleted file mode 100644 index a448321088..0000000000 --- a/scripts/schematics/set-version.js +++ /dev/null @@ -1,11 +0,0 @@ -const fs = require('fs-extra'); -const path = require('path'); - -const packageJson = fs.readJsonSync(path.resolve(__dirname, `../../components/package.json`)); -fs.outputFileSync( - path.resolve(__dirname, `../../schematics/utils/version-names.ts`), - ` -export const zorroVersion = '^${packageJson.version}'; -export const hammerjsVersion = '^2.0.8'; -` -); diff --git a/scripts/schematics/set-version.ts b/scripts/schematics/set-version.ts new file mode 100644 index 0000000000..656de129e1 --- /dev/null +++ b/scripts/schematics/set-version.ts @@ -0,0 +1,13 @@ +import { buildConfig } from '../build-config'; + +const fs = require('fs-extra'); +const path = require('path'); + +export function setVersion(): void { + fs.outputFileSync( + path.join(buildConfig.projectDir, `schematics/utils/version-names.ts`), + ` +export const zorroVersion = '^${buildConfig.projectVersion}'; +export const hammerjsVersion = '^2.0.8'; +`); +} diff --git a/scripts/site/generate-site.js b/scripts/site/generate-site.js index ff660d511f..0120eff4b1 100644 --- a/scripts/site/generate-site.js +++ b/scripts/site/generate-site.js @@ -11,127 +11,133 @@ const generateIframe = require('./utils/generate-iframe'); const capitalizeFirstLetter = require('./utils/capitalize-first-letter'); const camelCase = require('./utils/camelcase'); const getMeta = require('./utils/get-meta'); -const target = process.argv[2]; -const isSyncSpecific = target && (target !== 'init'); +const arg = process.argv[2]; // create site folder const showCasePath = path.resolve(__dirname, '../../site'); -if (!target) { - fs.removeSync(`${showCasePath}/doc`); - fs.copySync(path.resolve(__dirname, '_site/doc'), `${showCasePath}/doc`); -} else if (target === 'init') { - fs.removeSync(`${showCasePath}`); - fs.copySync(path.resolve(__dirname, '_site'), `${showCasePath}`); -} else { - fs.removeSync(`${showCasePath}/doc/app/${target}`); -} -const showCaseTargetPath = `${showCasePath}/doc/app/`; -const iframeTargetPath = `${showCasePath}/iframe/app/`; +function generate(target) { + const isSyncSpecific = target && (target !== 'init'); + if (!target) { + fs.removeSync(`${showCasePath}/doc`); + fs.copySync(path.resolve(__dirname, '_site/doc'), `${showCasePath}/doc`); + } else if (target === 'init') { + fs.removeSync(`${showCasePath}`); + fs.copySync(path.resolve(__dirname, '_site'), `${showCasePath}`); + } else { + fs.removeSync(`${showCasePath}/doc/app/${target}`); + } + const showCaseTargetPath = `${showCasePath}/doc/app/`; + const iframeTargetPath = `${showCasePath}/iframe/app/`; // read components folder -const rootPath = path.resolve(__dirname, '../../components'); -const rootDir = fs.readdirSync(rootPath); -const componentsDocMap = {}; -const componentsMap = {}; -rootDir.forEach(componentName => { - if (isSyncSpecific) { - if (componentName !== target) { + const rootPath = path.resolve(__dirname, '../../components'); + const rootDir = fs.readdirSync(rootPath); + const componentsDocMap = {}; + const componentsMap = {}; + rootDir.forEach(componentName => { + if (isSyncSpecific) { + if (componentName !== target) { + return; + } + } + const componentDirPath = path.join(rootPath, componentName); + if (componentName === 'style' || componentName === 'core' || componentName === 'locale' || componentName === 'i18n') { return; } - } - const componentDirPath = path.join(rootPath, componentName); - if (componentName === 'style' || componentName === 'core' || componentName === 'locale' || componentName === 'i18n') { - return; - } - if (fs.statSync(componentDirPath).isDirectory()) { - // create site/doc/app->${component} folder - const showCaseComponentPath = path.join(showCaseTargetPath, componentName); - fs.mkdirSync(showCaseComponentPath); + if (fs.statSync(componentDirPath).isDirectory()) { + // create site/doc/app->${component} folder + const showCaseComponentPath = path.join(showCaseTargetPath, componentName); + fs.mkdirSync(showCaseComponentPath); - // handle components->${component}->demo folder - const demoDirPath = path.join(componentDirPath, 'demo'); - const demoMap = {}; - if (fs.existsSync(demoDirPath)) { - const demoDir = fs.readdirSync(demoDirPath); - demoDir.forEach(demo => { + // handle components->${component}->demo folder + const demoDirPath = path.join(componentDirPath, 'demo'); + const demoMap = {}; + if (fs.existsSync(demoDirPath)) { + const demoDir = fs.readdirSync(demoDirPath); + demoDir.forEach(demo => { - if (/.md$/.test(demo)) { - const nameKey = nameWithoutSuffixUtil(demo); - const demoMarkDownFile = fs.readFileSync(path.join(demoDirPath, demo)); - demoMap[nameKey] = parseDemoMdUtil(demoMarkDownFile); - demoMap[nameKey]['name'] = `NzDemo${camelCase(capitalizeFirstLetter(componentName))}${camelCase(capitalizeFirstLetter(nameKey))}Component`; - demoMap[nameKey]['enCode'] = generateCodeBox(componentName, demoMap[nameKey]['name'], nameKey, demoMap[nameKey].meta.title['en-US'], demoMap[nameKey].en, demoMap[nameKey].meta.iframe); - demoMap[nameKey]['zhCode'] = generateCodeBox(componentName, demoMap[nameKey]['name'], nameKey, demoMap[nameKey].meta.title['zh-CN'], demoMap[nameKey].zh, demoMap[nameKey].meta.iframe); - } - if (/.ts$/.test(demo)) { - const nameKey = nameWithoutSuffixUtil(demo); - demoMap[nameKey].ts = String(fs.readFileSync(path.join(demoDirPath, demo))); - // copy ts file to site->${component} folder - fs.writeFileSync(path.join(showCaseComponentPath, demo), demoMap[nameKey].ts); - } - }); - } + if (/.md$/.test(demo)) { + const nameKey = nameWithoutSuffixUtil(demo); + const demoMarkDownFile = fs.readFileSync(path.join(demoDirPath, demo)); + demoMap[nameKey] = parseDemoMdUtil(demoMarkDownFile); + demoMap[nameKey]['name'] = `NzDemo${camelCase(capitalizeFirstLetter(componentName))}${camelCase(capitalizeFirstLetter(nameKey))}Component`; + demoMap[nameKey]['enCode'] = generateCodeBox(componentName, demoMap[nameKey]['name'], nameKey, demoMap[nameKey].meta.title['en-US'], demoMap[nameKey].en, demoMap[nameKey].meta.iframe); + demoMap[nameKey]['zhCode'] = generateCodeBox(componentName, demoMap[nameKey]['name'], nameKey, demoMap[nameKey].meta.title['zh-CN'], demoMap[nameKey].zh, demoMap[nameKey].meta.iframe); + } + if (/.ts$/.test(demo)) { + const nameKey = nameWithoutSuffixUtil(demo); + demoMap[nameKey].ts = String(fs.readFileSync(path.join(demoDirPath, demo))); + // copy ts file to site->${component} folder + fs.writeFileSync(path.join(showCaseComponentPath, demo), demoMap[nameKey].ts); + } + }); + } - // handle components->${component}->page folder, parent component of demo page - let pageDemo = ''; - const pageDirPath = path.join(componentDirPath, 'page'); - if (fs.existsSync(pageDirPath)) { - const pageDir = fs.readdirSync(pageDirPath); - let zhLocale = ''; - let enLocale = ''; - pageDemo = {}; - pageDir.forEach(file => { - if (/.ts$/.test(file)) { - pageDemo.raw = String(fs.readFileSync(path.join(pageDirPath, file))); - } - if (/^zh-CN.txt$/.test(file)) { - zhLocale = String(fs.readFileSync(path.join(pageDirPath, file))); - } - if (/^en-US.txt$/.test(file)) { - enLocale = String(fs.readFileSync(path.join(pageDirPath, file))); - } - }); - pageDemo.enCode = pageDemo.raw.replace(/locale;/g, enLocale); - pageDemo.zhCode = pageDemo.raw.replace(/locale;/g, zhLocale); - } + // handle components->${component}->page folder, parent component of demo page + let pageDemo = ''; + const pageDirPath = path.join(componentDirPath, 'page'); + if (fs.existsSync(pageDirPath)) { + const pageDir = fs.readdirSync(pageDirPath); + let zhLocale = ''; + let enLocale = ''; + pageDemo = {}; + pageDir.forEach(file => { + if (/.ts$/.test(file)) { + pageDemo.raw = String(fs.readFileSync(path.join(pageDirPath, file))); + } + if (/^zh-CN.txt$/.test(file)) { + zhLocale = String(fs.readFileSync(path.join(pageDirPath, file))); + } + if (/^en-US.txt$/.test(file)) { + enLocale = String(fs.readFileSync(path.join(pageDirPath, file))); + } + }); + pageDemo.enCode = pageDemo.raw.replace(/locale;/g, enLocale); + pageDemo.zhCode = pageDemo.raw.replace(/locale;/g, zhLocale); + } - // handle components->${component}->doc folder - const result = { - name : componentName, - docZh: parseDocMdUtil(fs.readFileSync(path.join(componentDirPath, 'doc/index.zh-CN.md')), `components/${componentName}/doc/index.zh-CN.md`), - docEn: parseDocMdUtil(fs.readFileSync(path.join(componentDirPath, 'doc/index.en-US.md')), `components/${componentName}/doc/index.en-US.md`), - demoMap, - pageDemo - }; - componentsDocMap[componentName] = { zh: result.docZh.meta, en: result.docEn.meta }; - componentsMap[componentName] = demoMap; - generateDemo(showCaseComponentPath, result); + // handle components->${component}->doc folder + const result = { + name : componentName, + docZh: parseDocMdUtil(fs.readFileSync(path.join(componentDirPath, 'doc/index.zh-CN.md')), `components/${componentName}/doc/index.zh-CN.md`), + docEn: parseDocMdUtil(fs.readFileSync(path.join(componentDirPath, 'doc/index.en-US.md')), `components/${componentName}/doc/index.en-US.md`), + demoMap, + pageDemo + }; + componentsDocMap[componentName] = { zh: result.docZh.meta, en: result.docEn.meta }; + componentsMap[componentName] = demoMap; + generateDemo(showCaseComponentPath, result); - } -}); + } + }); // handle iframe folder -generateIframe(iframeTargetPath, componentsMap); + generateIframe(iframeTargetPath, componentsMap); -if (!isSyncSpecific) { - // read docs folder - const docsPath = path.resolve(__dirname, '../../docs'); - const docsDir = fs.readdirSync(docsPath); - let docsMap = {}; - let docsMeta = {}; - docsDir.forEach(doc => { - const name = nameWithoutSuffixUtil(doc); - docsMap[name] = { - zh: fs.readFileSync(path.join(docsPath, `${name}.zh-CN.md`)), - en: fs.readFileSync(path.join(docsPath, `${name}.en-US.md`)) - }; - docsMeta[name] = { - zh: getMeta(docsMap[name].zh), - en: getMeta(docsMap[name].en) - }; - }); + if (!isSyncSpecific) { + // read docs folder + const docsPath = path.resolve(__dirname, '../../docs'); + const docsDir = fs.readdirSync(docsPath); + let docsMap = {}; + let docsMeta = {}; + docsDir.forEach(doc => { + const name = nameWithoutSuffixUtil(doc); + docsMap[name] = { + zh: fs.readFileSync(path.join(docsPath, `${name}.zh-CN.md`)), + en: fs.readFileSync(path.join(docsPath, `${name}.en-US.md`)) + }; + docsMeta[name] = { + zh: getMeta(docsMap[name].zh), + en: getMeta(docsMap[name].en) + }; + }); - generateDocs(showCaseTargetPath, docsMap); - generateRoutes(showCaseTargetPath, componentsDocMap, docsMeta); + generateDocs(showCaseTargetPath, docsMap); + generateRoutes(showCaseTargetPath, componentsDocMap, docsMeta); + } } +if (require.main === module) { + generate(arg); +} +module.exports = generate; \ No newline at end of file diff --git a/scripts/site/generateColorLess.js b/scripts/site/generateColorLess.js index 33df716470..a4804d0098 100644 --- a/scripts/site/generateColorLess.js +++ b/scripts/site/generateColorLess.js @@ -13,4 +13,8 @@ const options = { outputFilePath: path.join(__dirname, '../../site/doc/assets/color.less'), }; -generateTheme(options); \ No newline at end of file +if (require.main === module) { + generateTheme(options); +} + +module.exports = () => generateTheme(options); \ No newline at end of file From 7402cfc7c6cb0fa7170e78ecccab76d4a5e4ef8c Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 13 Jun 2019 17:41:16 +0800 Subject: [PATCH 08/23] chore: update ci config --- .travis.yml | 4 ++-- package.json | 6 +++--- scripts/gulp/gulpfile.ts | 11 +++++++++++ scripts/gulp/tasks/default.ts | 15 ++++++++++++--- scripts/gulp/tasks/site.ts | 4 ++-- 5 files changed, 30 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1205626c38..e6cf9ec14d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,10 @@ sudo: required dist: trusty language: node_js node_js: - - '10.9.0' + - '12.1.0' env: - - TASK=pre-release + - TASK=build - TASK=test - TASK=lint - TASK=integration-cli diff --git a/package.json b/package.json index bacf9bfbdd..3ca6974fe1 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,11 @@ "node": ">=12.1.0" }, "scripts": { - "start": "gulp start:site", + "start": "gulp start:dev", "test": "ng test --watch=false --code-coverage", "build": "gulp build:release", - "build:library": "gulp build:library", - "doc": "gulp build:overview-site", + "build:lib": "gulp build:library", + "doc": "gulp build:preview", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --pkg components/package.json && node ./scripts/site/replace-scope-prefix.js", "format": "prettier --config ./.prettierrc --list-different \"component/**/*{.ts}\"", "stage-release": "ts-node --project scripts/release/tsconfig.json scripts/release/release.ts", diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts index e61b80157a..52850537b8 100644 --- a/scripts/gulp/gulpfile.ts +++ b/scripts/gulp/gulpfile.ts @@ -9,6 +9,17 @@ import './tasks/library'; import './tasks/site'; task('build:release', series( + 'clean', 'build:library', 'build:release-site' )); + +task('build:preview', series( + 'clean', + 'build:simple-site' +)); + +task('start:dev', series( + 'clean', + 'start:site' +)); diff --git a/scripts/gulp/tasks/default.ts b/scripts/gulp/tasks/default.ts index 1e9bf90ae3..6e29df3e1b 100644 --- a/scripts/gulp/tasks/default.ts +++ b/scripts/gulp/tasks/default.ts @@ -1,6 +1,15 @@ -import { task } from 'gulp'; +import chalk from 'chalk'; +import { parallel, task } from 'gulp'; -task('default', done => { - console.log(1); +task('help', done => { + console.log(); + console.log('Please specify a gulp task you want to run.'); + console.log(chalk.yellow('start:dev '), 'Start development.'); + console.log(chalk.yellow('build:library'), 'Build ng-zorro-antd-lib to publish/ directory.'); + console.log(chalk.yellow('build:preview'), 'Build preview site to dist/ directory.'); + console.log(chalk.yellow('build:release'), 'Build releaseable library to publish/ directory and deployable site to dist/ directory.'); + console.log(); done(); }); + +task('default', parallel('help')); diff --git a/scripts/gulp/tasks/site.ts b/scripts/gulp/tasks/site.ts index ebfaefb566..3c3a09cc2f 100644 --- a/scripts/gulp/tasks/site.ts +++ b/scripts/gulp/tasks/site.ts @@ -1,5 +1,5 @@ -import { parallel, series, task, watch } from 'gulp'; import * as fs from 'fs-extra'; +import { parallel, series, task, watch } from 'gulp'; import { join } from 'path'; import { execNodeTask, execTask } from '../util/task-helpers'; @@ -91,7 +91,7 @@ task('start:site', series( /** Task that use source code to build ng-zorro-antd-doc project, * output not included issue-helper/iframe and prerender. */ -task('build:overview-site', series( +task('build:simple-site', series( 'init:site', 'build:site-doc' )); From 45c052d47cafd184f220c8a9b78a6864cc87f7ec Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 13 Jun 2019 17:46:30 +0800 Subject: [PATCH 09/23] ci: fix integration --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 3ca6974fe1..92e2df808b 100644 --- a/package.json +++ b/package.json @@ -18,10 +18,10 @@ "ng": "ng", "gulp": "gulp", "lint": "tslint -c tslint.json 'components/**/!(demo|testing)/!(polyfills).ts' --fix", - "integration-cli": "npm run build:library && cd integration/angular-cli && npm run integration", - "integration-rollup": "npm run build:library && cd integration/rollup && npm run integration", - "integration-webpack": "npm run build:library && cd integration/webpack && npm run integration", - "integration": "npm run build:library && bash ./integration-test.sh" + "integration-cli": "npm run build:lib && cd integration/angular-cli && npm run integration", + "integration-rollup": "npm run build:lib&& cd integration/rollup && npm run integration", + "integration-webpack": "npm run build:lib && cd integration/webpack && npm run integration", + "integration": "npm run build:lib && bash ./integration-test.sh" }, "dependencies": { "@angular/cdk": "~8.0.0", From a0e354794dbd8fbe13cdc8960f96056e28e3fb05 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 13 Jun 2019 18:30:09 +0800 Subject: [PATCH 10/23] ci: add travis_wait --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e6cf9ec14d..dd2a755f43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_script: - npm install -g karma script: - - npm run $TASK + - travis_wait 30 npm run $TASK - | if [ "$TASK" = "test" ]; then cat ./coverage/lcov.info | ./node_modules/.bin/codecov From 8ab95f84c4b58f6d4538f8d105c92374f82de272 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 13 Jun 2019 18:57:31 +0800 Subject: [PATCH 11/23] ci: fix ci --- .travis.yml | 7 ++++++- scripts/gulp/util/task-helpers.ts | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index dd2a755f43..55580aac7d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,12 @@ before_script: - npm install -g karma script: - - travis_wait 30 npm run $TASK + - | + if [ "$TASK" = "build" ]; then + travis_wait npm run $TASK + else + npm run $TASK + fi - | if [ "$TASK" = "test" ]; then cat ./coverage/lcov.info | ./node_modules/.bin/codecov diff --git a/scripts/gulp/util/task-helpers.ts b/scripts/gulp/util/task-helpers.ts index 4fee08be34..0b8c411e1b 100644 --- a/scripts/gulp/util/task-helpers.ts +++ b/scripts/gulp/util/task-helpers.ts @@ -26,6 +26,11 @@ export function execTask(binPath: string, args: string[], options: ExecTaskOptio return (done: (err?: string) => void) => { const env = {...process.env, ...options.env}; const childProcess = child_process.spawn(binPath, args, {env}); + // https://github.com/angular/angular-cli/issues/10922 + // tslint:disable-next-line:no-any + (childProcess.stdout as any)._handle.setBlocking(true); + // tslint:disable-next-line:no-any + (childProcess.stdout as any)._handle.setBlocking(true); const stderrData: string[] = []; if (!options.silentStdout && !options.silent) { From 1ff279876b85c4088c9b861958f42ce3120cc91c Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 10:34:47 +0800 Subject: [PATCH 12/23] ci: fix ci --- .travis.yml | 7 +--- scripts/gulp/util/task-helpers.ts | 53 ++++++++----------------------- 2 files changed, 14 insertions(+), 46 deletions(-) diff --git a/.travis.yml b/.travis.yml index 55580aac7d..e6cf9ec14d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,12 +30,7 @@ before_script: - npm install -g karma script: - - | - if [ "$TASK" = "build" ]; then - travis_wait npm run $TASK - else - npm run $TASK - fi + - npm run $TASK - | if [ "$TASK" = "test" ]; then cat ./coverage/lcov.info | ./node_modules/.bin/codecov diff --git a/scripts/gulp/util/task-helpers.ts b/scripts/gulp/util/task-helpers.ts index 0b8c411e1b..b88f2a54cb 100644 --- a/scripts/gulp/util/task-helpers.ts +++ b/scripts/gulp/util/task-helpers.ts @@ -3,59 +3,32 @@ import * as gulp from 'gulp'; const gulpClean = require('gulp-clean'); const resolveBin = require('resolve-bin'); -/** Options that can be passed to execTask or execNodeTask. */ -export interface ExecTaskOptions { - // Whether STDOUT and STDERR messages should be printed. - silent?: boolean; - // Whether STDOUT messages should be printed. - silentStdout?: boolean; - // If an error happens, this will replace the standard error. - errMessage?: string; - // Environment variables being passed to the child process. - // tslint:disable-next-line:no-any - env?: any; - // Whether the task should fail if the process writes to STDERR. - failOnStderr?: boolean; -} - export function cleanTask(glob: string | string[]) { return () => gulp.src(glob, { read: false, allowEmpty: true }).pipe(gulpClean(null)); } -export function execTask(binPath: string, args: string[], options: ExecTaskOptions = {}) { +export function execTask(binPath: string, args: string[]) { return (done: (err?: string) => void) => { - const env = {...process.env, ...options.env}; - const childProcess = child_process.spawn(binPath, args, {env}); + const env = {...process.env}; // https://github.com/angular/angular-cli/issues/10922 // tslint:disable-next-line:no-any - (childProcess.stdout as any)._handle.setBlocking(true); + (process.stdout as any)._handle.setBlocking(true); // tslint:disable-next-line:no-any - (childProcess.stdout as any)._handle.setBlocking(true); - const stderrData: string[] = []; - - if (!options.silentStdout && !options.silent) { - childProcess.stdout.on('data', (data: string) => process.stdout.write(data)); - } - - if (!options.silent || options.failOnStderr) { - childProcess.stderr.on('data', (data: string) => { - options.failOnStderr ? stderrData.push(data) : process.stderr.write(data); - }); - } + (process.stdout as any)._handle.setBlocking(true); + const childProcess = child_process.spawn(binPath, args, { + env, + cwd: process.cwd(), + stdio: "inherit" + }); childProcess.on('close', (code: number) => { - if (options.failOnStderr && stderrData.length) { - done(stderrData.join('\n')); - } else { - // tslint:disable-next-line:triple-equals - code != 0 ? done(options.errMessage || `Process failed with code ${code}`) : done(); - } + // tslint:disable-next-line:triple-equals + code != 0 ? done(`Process failed with code ${code}`) : done(); }); }; } -export function execNodeTask(packageName: string, executable: string | string[], args?: string[], - options: ExecTaskOptions = {}) { +export function execNodeTask(packageName: string, executable: string | string[], args?: string[]) { if (!args) { args = executable as string[]; executable = ''; @@ -68,7 +41,7 @@ export function execNodeTask(packageName: string, executable: string | string[], if (err) { done(err); } else { - execTask('node', ['--max_old_space_size=5120', binPath].concat(args!), options)(done); + execTask('node', ['--max_old_space_size=5120', binPath].concat(args!))(done); } }); }; From 3c1f6da46683ccd3aba38bc895392b5d9b4cf083 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 10:57:53 +0800 Subject: [PATCH 13/23] ci: fix ci --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 92e2df808b..78a733eb72 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test": "ng test --watch=false --code-coverage", "build": "gulp build:release", "build:lib": "gulp build:library", - "doc": "gulp build:preview", + "doc": "gulp init:site && node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --prod", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --pkg components/package.json && node ./scripts/site/replace-scope-prefix.js", "format": "prettier --config ./.prettierrc --list-different \"component/**/*{.ts}\"", "stage-release": "ts-node --project scripts/release/tsconfig.json scripts/release/release.ts", From 7427e9108c9044f574b920920dabfa5f5787d1cf Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 11:24:29 +0800 Subject: [PATCH 14/23] ci: fix ci --- package.json | 2 +- scripts/gulp/gulpfile.ts | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 78a733eb72..92e2df808b 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test": "ng test --watch=false --code-coverage", "build": "gulp build:release", "build:lib": "gulp build:library", - "doc": "gulp init:site && node --max_old_space_size=5120 ./node_modules/@angular/cli/bin/ng build --prod", + "doc": "gulp build:preview", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --pkg components/package.json && node ./scripts/site/replace-scope-prefix.js", "format": "prettier --config ./.prettierrc --list-different \"component/**/*{.ts}\"", "stage-release": "ts-node --project scripts/release/tsconfig.json scripts/release/release.ts", diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts index 52850537b8..ee024589ba 100644 --- a/scripts/gulp/gulpfile.ts +++ b/scripts/gulp/gulpfile.ts @@ -16,7 +16,8 @@ task('build:release', series( task('build:preview', series( 'clean', - 'build:simple-site' + 'build:simple-site', + 'build:site-iframe' )); task('start:dev', series( From d24a0b178c663a8348c21522609598f39f813748 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 14:28:13 +0800 Subject: [PATCH 15/23] ci: fix ci --- scripts/gulp/gulpfile.ts | 3 +-- scripts/gulp/tasks/site.ts | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts index ee024589ba..52850537b8 100644 --- a/scripts/gulp/gulpfile.ts +++ b/scripts/gulp/gulpfile.ts @@ -16,8 +16,7 @@ task('build:release', series( task('build:preview', series( 'clean', - 'build:simple-site', - 'build:site-iframe' + 'build:simple-site' )); task('start:dev', series( diff --git a/scripts/gulp/tasks/site.ts b/scripts/gulp/tasks/site.ts index 3c3a09cc2f..902687ab09 100644 --- a/scripts/gulp/tasks/site.ts +++ b/scripts/gulp/tasks/site.ts @@ -63,7 +63,7 @@ task('site:replace-path', () => { // tslint:disable-next-line:no-any const tsconfig: any = fs.readJSONSync(tsconfigFile); tsconfig.compilerOptions.paths['ng-zorro-antd'] = ['../publish']; - tsconfig.compilerOptions.paths['ng-zorro-antd/*'] = ['../publish/*'] + tsconfig.compilerOptions.paths['ng-zorro-antd/*'] = ['../publish/*']; return fs.writeJSON(tsconfigFile, tsconfig); }); From 309695c48cfef58c0a4d5b729a6b01fffecc31ea Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 14:56:09 +0800 Subject: [PATCH 16/23] chore: fix type --- gulpfile.js | 1 - scripts/gulp/util/task-helpers.ts | 10 ++++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/gulpfile.js b/gulpfile.js index 017a5e0c66..0ca9f67609 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -2,7 +2,6 @@ const path = require('path'); const projectDir = __dirname; const tsconfigPath = path.join(projectDir, 'scripts/gulp/tsconfig.json'); -const tsconfig = require(tsconfigPath); if (projectDir.includes(' ')) { console.error('Error: Cannot run the build tasks if the project is ' + diff --git a/scripts/gulp/util/task-helpers.ts b/scripts/gulp/util/task-helpers.ts index b88f2a54cb..daab63d9b4 100644 --- a/scripts/gulp/util/task-helpers.ts +++ b/scripts/gulp/util/task-helpers.ts @@ -3,11 +3,11 @@ import * as gulp from 'gulp'; const gulpClean = require('gulp-clean'); const resolveBin = require('resolve-bin'); -export function cleanTask(glob: string | string[]) { +export function cleanTask(glob: string | string[]): gulp.TaskFunction { return () => gulp.src(glob, { read: false, allowEmpty: true }).pipe(gulpClean(null)); } -export function execTask(binPath: string, args: string[]) { +export function execTask(binPath: string, args: string[]): gulp.TaskFunction { return (done: (err?: string) => void) => { const env = {...process.env}; // https://github.com/angular/angular-cli/issues/10922 @@ -28,9 +28,11 @@ export function execTask(binPath: string, args: string[]) { }; } -export function execNodeTask(packageName: string, executable: string | string[], args?: string[]) { +export function execNodeTask(packageName: string, executable: string | string[], args?: string[]): gulp.TaskFunction { if (!args) { + // tslint:disable-next-line:no-parameter-reassignment args = executable as string[]; + // tslint:disable-next-line:no-parameter-reassignment executable = ''; } @@ -45,4 +47,4 @@ export function execNodeTask(packageName: string, executable: string | string[], } }); }; -} \ No newline at end of file +} From cf3dcac8709ba662cca8d3ddb2b83ffd9ac9602e Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 14 Jun 2019 16:47:23 +0800 Subject: [PATCH 17/23] build: add site release scripts --- .gitignore | 1 + scripts/release/git-client.ts | 34 +++++++++++++++++++++++++++++ scripts/release/release-site.ts | 37 ++++++++++++++++++++++++++++++++ scripts/release/release.ts | 38 +++++++++++++++++++++++---------- 4 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 scripts/release/git-client.ts create mode 100644 scripts/release/release-site.ts diff --git a/.gitignore b/.gitignore index 2e9d0e40ed..531732be78 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ integration/**/*.ngsummary.json schematics/demo schematics/utils/create-custom-theme.ts schematics/utils/version-names.ts +ng-zorro.github.io/ # dependencies node_modules diff --git a/scripts/release/git-client.ts b/scripts/release/git-client.ts new file mode 100644 index 0000000000..fec38173f6 --- /dev/null +++ b/scripts/release/git-client.ts @@ -0,0 +1,34 @@ +import { spawnSync, SpawnSyncReturns } from 'child_process'; + +export class GitClient { + constructor(public projectDir: string, public remoteGitUrl: string) {} + + spawnGitProcess(args: string[], printStderr: boolean = true): SpawnSyncReturns { + return spawnSync('git', args, { + cwd: this.projectDir, + stdio: ['pipe', 'pipe', printStderr ? 'inherit' : 'pipe'], + encoding: 'utf8' + }); + } + + clone(): void { + this.spawnGitProcess(['clone', this.remoteGitUrl, '.', '--depth=1']); + } + + stageAllChanges(): boolean { + return this.spawnGitProcess(['add', '-A']).status === 0; + } + + createNewCommit(message: string): boolean { + return this.spawnGitProcess(['commit', '--no-verify', '-m', message]).status === 0; + } + + checkoutNewBranch(branchName: string): boolean { + return this.spawnGitProcess(['checkout', '-b', branchName]).status === 0; + } + + pushBranchToRemote(branchName: string, remoteName: string = this.remoteGitUrl): boolean { + return this.spawnGitProcess(['push', remoteName, branchName]).status === 0; + } + +} diff --git a/scripts/release/release-site.ts b/scripts/release/release-site.ts new file mode 100644 index 0000000000..c21193644b --- /dev/null +++ b/scripts/release/release-site.ts @@ -0,0 +1,37 @@ +import { copySync, emptyDirSync, removeSync } from 'fs-extra'; +import * as minimatch from 'minimatch'; +import { join } from 'path'; +import { buildConfig } from '../build-config'; +import { GitClient } from './git-client'; + +const docDir = join(buildConfig.projectDir, 'ng-zorro.github.io'); + +export function releaseSite(version: string): boolean { + emptyDirSync(docDir); + const git = new GitClient(docDir, 'https://github.com/NG-ZORRO/ng-zorro.github.io.git'); + const branchName = `release/${version}`; + git.clone(); + git.checkoutNewBranch(branchName); + + copySync(buildConfig.outputDir, docDir, { + overwrite: true, + filter: file => { + const fileGlobs = [ + '.DS_Store', + 'sitemap.js?(.map)', + 'static.paths.js?(.map)', + 'prerender.js?(.map)', + 'server/**/*', + '.idea/**/*', + '.vscode/**/*' + ].map(f => join(buildConfig.outputDir, f)); + return !fileGlobs.some(p => minimatch(file, p)); + } + }); + + git.stageAllChanges(); + git.createNewCommit(`release: ${version}`); + const pushed = git.pushBranchToRemote(branchName); + removeSync(docDir); + return pushed; +} diff --git a/scripts/release/release.ts b/scripts/release/release.ts index ddf54b69d2..e7b1514e32 100644 --- a/scripts/release/release.ts +++ b/scripts/release/release.ts @@ -4,6 +4,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import { buildConfig } from '../build-config'; import { checkVersionNumber } from './parse-version'; +import { releaseSite } from './release-site'; const read = require('readline-sync'); @@ -18,8 +19,6 @@ const log = { /* The whole process */ -let releaseVersion: string; - run(); function run(): void { @@ -46,8 +45,12 @@ function run(): void { fun: buildRelease }, { - name: 'Push release', - fun: pushRelease + name: 'Push library release', + fun: pushLibraryRelease + }, + { + name: 'Push site release', + fun: pushSiteRelease } ]; @@ -103,12 +106,11 @@ function getRemoteUrl(remote: string): string { function bumpVersion(): void { log.info('Updating version number...'); - const packageJsonPath = path.join(buildConfig.componentsDir, 'package.json'); const appComponentPath = path.join(buildConfig.scriptsDir, 'site/_site/doc/app/app.component.ts'); const codeBoxPath = path.join(buildConfig.scriptsDir, 'site/_site/doc/app/share/nz-codebox/stack-blitz.ts'); - const zorroVersionPath = path.join(buildConfig.componentsDir, 'version.ts'); - + const packageJsonPath = path.join(buildConfig.componentsDir, 'package.json'); const packageJson = fs.readJsonSync(packageJsonPath); + const zorroVersionPath = path.join(buildConfig.componentsDir, 'version.ts'); const currentVersion = packageJson.version; let versionNumberValid = false; let version; @@ -117,7 +119,6 @@ function bumpVersion(): void { version = read.question(chalk.bgYellow.black('Please input the new version:') + ' '); if (checkVersionNumber(currentVersion, version)) { versionNumberValid = true; - releaseVersion = version; } else { log.error(`Your input ${version} is not after the current version ${currentVersion} or is unvalid. Please check it.`); } @@ -174,12 +175,27 @@ function buildRelease(): void { log.info('pre-release completed!'); } -function pushRelease(): void { +function pushLibraryRelease(): void { + const releaseVersion = getCurrentVersion(); log.info('Checkout and push a new branch for publishing...'); execSync(`git checkout -b publish-${releaseVersion}`); execSync('git add .'); execSync(`git commit -m "release(${releaseVersion}): release ${releaseVersion}"`); execSync(`git push origin publish-${releaseVersion}`); - log.success('Please go to GitHub and make a pull request.'); - log.success('Bye!'); + log.success('Push library release completed!'); + log.info('Please go to GitHub and make a pull request.'); + +} + +function pushSiteRelease(): void { + log.info('Checkout and push a new branch to ng-zorro.github.io...'); + releaseSite(getCurrentVersion()); + log.success('Push site release completed!'); + log.info('Please go to GitHub and make a pull request.'); +} + +function getCurrentVersion(): string { + const packageJsonPath = path.join(buildConfig.componentsDir, 'package.json'); + const packageJson = fs.readJsonSync(packageJsonPath); + return packageJson.version; } From 438b93504005f174aa28d29d0c90037b3d196b54 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Mon, 17 Jun 2019 14:39:04 +0800 Subject: [PATCH 18/23] build: _ --- scripts/gulp/tasks/unit-test.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/gulp/tasks/unit-test.ts diff --git a/scripts/gulp/tasks/unit-test.ts b/scripts/gulp/tasks/unit-test.ts new file mode 100644 index 0000000000..e69de29bb2 From 356386d88dd33ae29dfc407ba195500df5c16d4e Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Mon, 17 Jun 2019 18:02:40 +0800 Subject: [PATCH 19/23] build: add `test:watch` task --- components/karma.conf.js | 2 ++ components/test.ts | 23 ++++++++++++++++++++--- package.json | 4 +++- scripts/gulp/gulpfile.ts | 1 + scripts/gulp/tasks/unit-test.ts | 13 +++++++++++++ scripts/gulp/util/task-helpers.ts | 9 ++++----- 6 files changed, 43 insertions(+), 9 deletions(-) diff --git a/components/karma.conf.js b/components/karma.conf.js index e70138f456..abb58e693f 100644 --- a/components/karma.conf.js +++ b/components/karma.conf.js @@ -1,6 +1,7 @@ // Karma configuration file, see link for more information // https://karma-runner.github.io/1.0/config/configuration-file.html +const tags = process.env && process.env['NG_TEST_TAGS']; module.exports = function(config) { config.set({ basePath: '', @@ -15,6 +16,7 @@ module.exports = function(config) { require('karma-viewport') ], client: { + args: [tags], clearContext: true // leave Jasmine Spec Runner output visible in browser }, coverageIstanbulReporter: { diff --git a/components/test.ts b/components/test.ts index 16317897b1..7209ac8854 100644 --- a/components/test.ts +++ b/components/test.ts @@ -1,20 +1,37 @@ // This file is required by karma.conf.js and loads recursively all the .spec and framework files +// tslint:disable-next-line:no-import-side-effect import 'zone.js/dist/zone-testing'; + import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + platformBrowserDynamicTesting, + BrowserDynamicTestingModule } from '@angular/platform-browser-dynamic/testing'; +// tslint:disable-next-line:no-any +declare const __karma__: any; +// tslint:disable-next-line:no-any declare const require: any; +const tags = __karma__.config.args[0]; // First, initialize the Angular testing environment. getTestBed().initTestEnvironment( BrowserDynamicTestingModule, platformBrowserDynamicTesting() ); + +let filterRegExp: RegExp; + +if (tags) { + filterRegExp = new RegExp(`(${tags})\\.spec\\.ts$`); +} else { + filterRegExp = /\.spec\.ts$/; +} + // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); +// Filter specify file +const specFiles = context.keys().filter((path: string) => filterRegExp.test(path)); // And load the modules. -context.keys().map(context); +specFiles.map(context); diff --git a/package.json b/package.json index 92e2df808b..d11ed3bfbe 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "scripts": { "start": "gulp start:dev", "test": "ng test --watch=false --code-coverage", + "test:watch": "gulp test:watch --tags $tags", "build": "gulp build:release", "build:lib": "gulp build:library", "doc": "gulp build:preview", @@ -81,6 +82,7 @@ "less-plugin-clean-css": "^1.5.1", "lint-staged": "^8.1.5", "marked": "^0.6.2", + "minimist": "^1.2.0", "ng-packagr": "^5.2.0", "ngx-color": "^2.0.5", "node-prismjs": "^0.1.1", @@ -89,9 +91,9 @@ "protractor": "~5.4.0", "readline-sync": "^1.4.9", "remark": "^8.0.0", - "rxjs": "~6.5.2", "resolve-bin": "^0.4.0", "run-sequence": "^2.2.1", + "rxjs": "~6.5.2", "sitemap": "^2.1.0", "ts-node": "^7.0.1", "tsickle": ">=0.34.0", diff --git a/scripts/gulp/gulpfile.ts b/scripts/gulp/gulpfile.ts index 52850537b8..4efbc99c6d 100644 --- a/scripts/gulp/gulpfile.ts +++ b/scripts/gulp/gulpfile.ts @@ -3,6 +3,7 @@ import { series, task } from 'gulp'; import './tasks/clean'; import './tasks/default'; import './tasks/schematic'; +import './tasks/unit-test'; import './tasks/universal'; import './tasks/library'; diff --git a/scripts/gulp/tasks/unit-test.ts b/scripts/gulp/tasks/unit-test.ts index e69de29bb2..2534296908 100644 --- a/scripts/gulp/tasks/unit-test.ts +++ b/scripts/gulp/tasks/unit-test.ts @@ -0,0 +1,13 @@ +import { task } from 'gulp'; +import { execTask } from '../util/task-helpers'; + +task('test:watch', (done) => { + const argv = require('minimist')(process.argv.slice(2)); + return execTask( + 'ng', + ['test', '--watch=true', '--code-coverage'], + { + 'NG_TEST_TAGS': argv.tags || '' + } + )(done); +}); diff --git a/scripts/gulp/util/task-helpers.ts b/scripts/gulp/util/task-helpers.ts index daab63d9b4..9f10ccb6a3 100644 --- a/scripts/gulp/util/task-helpers.ts +++ b/scripts/gulp/util/task-helpers.ts @@ -7,16 +7,15 @@ export function cleanTask(glob: string | string[]): gulp.TaskFunction { return () => gulp.src(glob, { read: false, allowEmpty: true }).pipe(gulpClean(null)); } -export function execTask(binPath: string, args: string[]): gulp.TaskFunction { +export function execTask(binPath: string, args: string[], env: {} = {}): gulp.TaskFunction { return (done: (err?: string) => void) => { - const env = {...process.env}; // https://github.com/angular/angular-cli/issues/10922 // tslint:disable-next-line:no-any (process.stdout as any)._handle.setBlocking(true); // tslint:disable-next-line:no-any (process.stdout as any)._handle.setBlocking(true); const childProcess = child_process.spawn(binPath, args, { - env, + env: {...process.env, ...env}, cwd: process.cwd(), stdio: "inherit" }); @@ -28,7 +27,7 @@ export function execTask(binPath: string, args: string[]): gulp.TaskFunction { }; } -export function execNodeTask(packageName: string, executable: string | string[], args?: string[]): gulp.TaskFunction { +export function execNodeTask(packageName: string, executable: string | string[], args?: string[], env: {} = {}): gulp.TaskFunction { if (!args) { // tslint:disable-next-line:no-parameter-reassignment args = executable as string[]; @@ -43,7 +42,7 @@ export function execNodeTask(packageName: string, executable: string | string[], if (err) { done(err); } else { - execTask('node', ['--max_old_space_size=5120', binPath].concat(args!))(done); + execTask('node', ['--max_old_space_size=5120', binPath].concat(args!), env)(done); } }); }; From d05ef812d07dd9fc20d011c34eb60e042997b222 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Mon, 17 Jun 2019 18:22:52 +0800 Subject: [PATCH 20/23] build: fix `test:watch` task --- components/test.ts | 5 ++++- scripts/gulp/tasks/unit-test.ts | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/components/test.ts b/components/test.ts index 7209ac8854..ce11f140e2 100644 --- a/components/test.ts +++ b/components/test.ts @@ -32,6 +32,9 @@ if (tags) { // Then we find all the tests. const context = require.context('./', true, /\.spec\.ts$/); // Filter specify file -const specFiles = context.keys().filter((path: string) => filterRegExp.test(path)); +const specFiles = context.keys().filter((path: string) => { + console.log(filterRegExp); + return filterRegExp.test(path); +}); // And load the modules. specFiles.map(context); diff --git a/scripts/gulp/tasks/unit-test.ts b/scripts/gulp/tasks/unit-test.ts index 2534296908..e9ff55730d 100644 --- a/scripts/gulp/tasks/unit-test.ts +++ b/scripts/gulp/tasks/unit-test.ts @@ -3,11 +3,15 @@ import { execTask } from '../util/task-helpers'; task('test:watch', (done) => { const argv = require('minimist')(process.argv.slice(2)); + let tags = ''; + if (argv.tags && typeof argv.tags === 'string') { + tags = argv.tags; + } return execTask( 'ng', ['test', '--watch=true', '--code-coverage'], { - 'NG_TEST_TAGS': argv.tags || '' + 'NG_TEST_TAGS': tags } )(done); }); From eaed4a3c88b8d801d76ada5311aa0c25a36322f3 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Thu, 20 Jun 2019 17:50:49 +0800 Subject: [PATCH 21/23] chore: bump node to 12.1.0 --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index e3cbcda795..6e03ffbaca 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -10.9.0 \ No newline at end of file +12.1.0 \ No newline at end of file From a7bfb76c04f45d3a4143033125360ae19fd8d50a Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 21 Jun 2019 10:14:30 +0800 Subject: [PATCH 22/23] ci: add now.json --- now.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 now.json diff --git a/now.json b/now.json new file mode 100644 index 0000000000..e69de29bb2 From b78670b4275087c9ddaf9406fa15a38f048e48c9 Mon Sep 17 00:00:00 2001 From: Hsuan Lee Date: Fri, 21 Jun 2019 10:26:30 +0800 Subject: [PATCH 23/23] ci: add now.json --- now.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/now.json b/now.json index e69de29bb2..0e0dcd235c 100644 --- a/now.json +++ b/now.json @@ -0,0 +1,3 @@ +{ + +} \ No newline at end of file