From 9137650dba68fbfddddddb5007afdf8c858ad51f Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Sun, 25 Feb 2018 22:55:30 +0100 Subject: [PATCH 01/18] build: update api golden files (#22402) `ts-api-guardion` has been updated to accept new TypeScript syntax PR Close #22402 --- tools/public_api_guard/platform-browser/platform-browser.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/public_api_guard/platform-browser/platform-browser.d.ts b/tools/public_api_guard/platform-browser/platform-browser.d.ts index 5c55225bd9d16..5eaa48d089464 100644 --- a/tools/public_api_guard/platform-browser/platform-browser.d.ts +++ b/tools/public_api_guard/platform-browser/platform-browser.d.ts @@ -60,7 +60,7 @@ export declare class HammerGestureConfig { } /** @experimental */ -export declare function makeStateKey(key: string): StateKey; /** @experimental */ export declare class Meta { From 089769d5c3483d6c07db348f83d0b8a2e92657fb Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Tue, 27 Feb 2018 08:05:09 -0800 Subject: [PATCH 02/18] build: update ts-api-guardian version (#22402) PR Close #22402 --- package.json | 2 +- yarn.lock | 55 +++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 2db951d65045b..ec5ea71ee2cc6 100644 --- a/package.json +++ b/package.json @@ -99,7 +99,7 @@ "source-map": "0.5.7", "source-map-support": "0.4.18", "systemjs": "0.18.10", - "ts-api-guardian": "0.2.2", + "ts-api-guardian": "^0.3.0", "tsickle": "0.26.0", "tslint": "5.7.0", "tslint-eslint-rules": "4.1.1", diff --git a/yarn.lock b/yarn.lock index 8d9ad8f7cef50..11193581a676c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -265,6 +265,12 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" +ansi-styles@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + any-promise@^1.0.0, any-promise@^1.1.0, any-promise@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -978,6 +984,14 @@ chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796" + dependencies: + ansi-styles "^3.2.0" + escape-string-regexp "^1.0.5" + supports-color "^5.2.0" + char-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/char-spinner/-/char-spinner-1.0.1.tgz#e6ea67bd247e107112983b7ab0479ed362800081" @@ -1138,6 +1152,16 @@ coffee-script@1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/coffee-script/-/coffee-script-1.3.3.tgz#150d6b4cb522894369efed6a2101c20bc7f4a4f4" +color-convert@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + colors@0.6.0-1: version "0.6.0-1" resolved "https://registry.yarnpkg.com/colors/-/colors-0.6.0-1.tgz#6dbb68ceb8bc60f2b313dcc5ce1599f06d19e67a" @@ -1920,7 +1944,7 @@ didyoumean@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.1.tgz#e92edfdada6537d484d73c0172fd1eba0c4976ff" -diff@^2.0.2, diff@^2.2.3: +diff@^2.0.2: version "2.2.3" resolved "https://registry.yarnpkg.com/diff/-/diff-2.2.3.tgz#60eafd0d28ee906e4e8ff0a52c1229521033bf99" @@ -1928,6 +1952,10 @@ diff@^3.2.0: version "3.3.1" resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" +diff@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + doctrine@^0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-0.7.2.tgz#7cb860359ba3be90e040b26b729ce4bfa654c523" @@ -3341,6 +3369,10 @@ has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + has-gulplog@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/has-gulplog/-/has-gulplog-0.1.0.tgz#6414c82913697da51590397dafb12f22967811ce" @@ -6816,6 +6848,12 @@ supports-color@^3.1.0: dependencies: has-flag "^1.0.0" +supports-color@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a" + dependencies: + has-flag "^3.0.0" + symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" @@ -7078,14 +7116,13 @@ try-require@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/try-require/-/try-require-1.2.1.tgz#34489a2cac0c09c1cc10ed91ba011594d4333be2" -ts-api-guardian@0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/ts-api-guardian/-/ts-api-guardian-0.2.2.tgz#b23bbb2865d0c4aee161730a74f59a00c4f06c8b" +ts-api-guardian@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/ts-api-guardian/-/ts-api-guardian-0.3.0.tgz#c5fbba9991840328f5ed0c89765a23e707645aa3" dependencies: - chalk "^1.1.3" - diff "^2.2.3" + chalk "^2.3.1" + diff "^3.4.0" minimist "^1.2.0" - typescript "2.0.10" tsickle@0.26.0: version "0.26.0" @@ -7190,10 +7227,6 @@ typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -typescript@2.0.10: - version "2.0.10" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.0.10.tgz#ccdd4ed86fd5550a407101a0814012e1b3fac3dd" - typescript@2.6.x: version "2.6.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.6.2.tgz#3c5b6fd7f6de0914269027f03c0946758f7673a4" From 0ec11e32238cbf757c7321e52c1b9383d75f45f5 Mon Sep 17 00:00:00 2001 From: Kapunahele Wong Date: Mon, 12 Feb 2018 16:34:38 -0500 Subject: [PATCH 03/18] docs: fix dynamic component loader example (#22181) closes #21903 PR Close #22181 --- .../src/app/ad-banner.component.ts | 15 +++++++-------- .../src/app/app.component.ts | 2 +- aio/content/guide/dynamic-component-loader.md | 4 ++-- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts b/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts index 1e59a89204931..63cb0ba0ffdbf 100644 --- a/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts +++ b/aio/content/examples/dynamic-component-loader/src/app/ad-banner.component.ts @@ -1,12 +1,12 @@ // #docregion -import { Component, Input, AfterViewInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core'; +import { Component, Input, OnInit, ViewChild, ComponentFactoryResolver, OnDestroy } from '@angular/core'; import { AdDirective } from './ad.directive'; import { AdItem } from './ad-item'; import { AdComponent } from './ad.component'; @Component({ - selector: 'app-add-banner', + selector: 'app-ad-banner', // #docregion ad-host template: `
@@ -17,16 +17,15 @@ import { AdComponent } from './ad.component'; // #enddocregion ad-host }) // #docregion class -export class AdBannerComponent implements AfterViewInit, OnDestroy { +export class AdBannerComponent implements OnInit, OnDestroy { @Input() ads: AdItem[]; - currentAddIndex: number = -1; + currentAdIndex: number = -1; @ViewChild(AdDirective) adHost: AdDirective; - subscription: any; interval: any; constructor(private componentFactoryResolver: ComponentFactoryResolver) { } - ngAfterViewInit() { + ngOnInit() { this.loadComponent(); this.getAds(); } @@ -36,8 +35,8 @@ export class AdBannerComponent implements AfterViewInit, OnDestroy { } loadComponent() { - this.currentAddIndex = (this.currentAddIndex + 1) % this.ads.length; - let adItem = this.ads[this.currentAddIndex]; + this.currentAdIndex = (this.currentAdIndex + 1) % this.ads.length; + let adItem = this.ads[this.currentAdIndex]; let componentFactory = this.componentFactoryResolver.resolveComponentFactory(adItem.component); diff --git a/aio/content/examples/dynamic-component-loader/src/app/app.component.ts b/aio/content/examples/dynamic-component-loader/src/app/app.component.ts index 40fe96a27638e..1a5fa94dbc4a9 100644 --- a/aio/content/examples/dynamic-component-loader/src/app/app.component.ts +++ b/aio/content/examples/dynamic-component-loader/src/app/app.component.ts @@ -8,7 +8,7 @@ import { AdItem } from './ad-item'; selector: 'app-root', template: `
- +
` }) diff --git a/aio/content/guide/dynamic-component-loader.md b/aio/content/guide/dynamic-component-loader.md index ecd6fe0a246d2..c2e3d777482ae 100644 --- a/aio/content/guide/dynamic-component-loader.md +++ b/aio/content/guide/dynamic-component-loader.md @@ -109,9 +109,9 @@ Take it step by step. First, it picks an ad. The `loadComponent()` method chooses an ad using some math. -First, it sets the `currentAddIndex` by taking whatever it +First, it sets the `currentAdIndex` by taking whatever it currently is plus one, dividing that by the length of the `AdItem` array, and -using the _remainder_ as the new `currentAddIndex` value. Then, it uses that +using the _remainder_ as the new `currentAdIndex` value. Then, it uses that value to select an `adItem` from the array. From 1593bff1b07d17e7e3fdccdf3d55ff7ae2c4020c Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 28 Feb 2018 15:00:20 -0800 Subject: [PATCH 04/18] release: cut the 5.2.7 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec5ea71ee2cc6..3d5d5aea040aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-srcs", - "version": "5.2.6", + "version": "5.2.7", "private": true, "branchPattern": "2.0.*", "description": "Angular - a web framework for modern web apps", From 697d31a38cbe0e7dc420d54f769036df6380bc5d Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 28 Feb 2018 15:01:38 -0800 Subject: [PATCH 05/18] docs: add changelog for 5.2.7 --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e4ead348e7a..3f97026713f91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ + +## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28) + + +### Bug Fixes + +* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235) +* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203) +* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392) +* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390)) +* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175) + + + ## [5.2.6](https://github.com/angular/angular/compare/5.2.5...5.2.6) (2018-02-22) From f8e70fb0c61f2187b75f3abeb3b025f7d8986dc6 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 28 Feb 2018 20:10:14 +0000 Subject: [PATCH 06/18] build(aio): initialise `exampleMap` correctly (#22502) The `exampleMap` needs to hold an hash object for each of the `collectExamples.exampleFolders` paths. Previously these hash objects were only created if there was actually an example file the hash's respective example folder. This could cause crashes during `yarn docs-watch` (and so also `yarn sync-and-serve`) if no examples were read in for a particular run of the doc-gen. PR Close #22502 --- .../examples-package/processors/collect-examples.js | 2 +- .../examples-package/processors/collect-examples.spec.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/aio/tools/transforms/examples-package/processors/collect-examples.js b/aio/tools/transforms/examples-package/processors/collect-examples.js index 5bb6a94c50e6c..ebf66658a9ea0 100644 --- a/aio/tools/transforms/examples-package/processors/collect-examples.js +++ b/aio/tools/transforms/examples-package/processors/collect-examples.js @@ -27,6 +27,7 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD }, $process(docs) { const exampleFolders = this.exampleFolders; + exampleFolders.forEach(folder => exampleMap[folder] = exampleMap[folder] || {}); const regionDocs = []; docs = docs.filter((doc) => { if (doc.docType === 'example-file') { @@ -36,7 +37,6 @@ module.exports = function collectExamples(exampleMap, regionParser, log, createD if (doc.fileInfo.relativePath.indexOf(folder) === 0) { const relativePath = doc.fileInfo.relativePath.substr(folder.length).replace(/^\//, ''); - exampleMap[folder] = exampleMap[folder] || {}; exampleMap[folder][relativePath] = doc; // We treat files that end in `.annotated` specially diff --git a/aio/tools/transforms/examples-package/processors/collect-examples.spec.js b/aio/tools/transforms/examples-package/processors/collect-examples.spec.js index 583c3a102947a..85f10ca02ea2a 100644 --- a/aio/tools/transforms/examples-package/processors/collect-examples.spec.js +++ b/aio/tools/transforms/examples-package/processors/collect-examples.spec.js @@ -25,6 +25,12 @@ describe('collectExampleRegions processor', () => { describe('$process', () => { + it('should initialise the `exampleMap` even if there are no examples to collect', () => { + processor.$process([]); + expect(exampleMap['examples-1']).toEqual(jasmine.any(Object)); + expect(exampleMap['examples-2']).toEqual(jasmine.any(Object)); + }); + it('should identify example files that are in the exampleFolders', () => { const docs = [ createDoc('A', 'examples-1/x/app.js'), createDoc('B', 'examples-1/y/index.html'), From 855e3a65db7ac4671f507a7eb1ec3d9e83354190 Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 28 Feb 2018 14:52:29 +0000 Subject: [PATCH 07/18] build(aio): move link disambiguation from `getLinkInfo` to `getDocFromAlias` (#22494) The disambiguation needs to be done earlier so that the auto-link-code post-processor can benefit from it. PR Close #22494 --- aio/tools/transforms/links-package/index.js | 13 ++++--- .../deprecatedDocsLinkDisambiguator.js | 12 ------ .../disambiguateByDeprecated.js | 3 ++ .../disambiguateByDeprecated.spec.js | 17 +++++++++ .../disambiguators/disambiguateByModule.js | 12 ++++++ .../disambiguateByModule.spec.js | 29 ++++++++++++++ .../links-package/services/getDocFromAlias.js | 38 ++++++++----------- .../services/getDocFromAlias.spec.js | 35 +++++++++-------- .../links-package/services/getLinkInfo.js | 11 ------ .../services/moduleScopeLinkDisambiguator.js | 15 -------- 10 files changed, 100 insertions(+), 85 deletions(-) delete mode 100644 aio/tools/transforms/links-package/services/deprecatedDocsLinkDisambiguator.js create mode 100644 aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.js create mode 100644 aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.spec.js create mode 100644 aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.js create mode 100644 aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.spec.js delete mode 100644 aio/tools/transforms/links-package/services/moduleScopeLinkDisambiguator.js diff --git a/aio/tools/transforms/links-package/index.js b/aio/tools/transforms/links-package/index.js index 1fab11d2ae355..2f6964cfaf3e2 100644 --- a/aio/tools/transforms/links-package/index.js +++ b/aio/tools/transforms/links-package/index.js @@ -8,15 +8,16 @@ module.exports = .factory(require('./services/getAliases')) .factory(require('./services/getDocFromAlias')) .factory(require('./services/getLinkInfo')) - .factory(require('./services/moduleScopeLinkDisambiguator')) - .factory(require('./services/deprecatedDocsLinkDisambiguator')) + .factory(require('./services/disambiguators/disambiguateByDeprecated')) + .factory(require('./services/disambiguators/disambiguateByModule')) .config(function(inlineTagProcessor, linkInlineTagDef) { inlineTagProcessor.inlineTagDefinitions.push(linkInlineTagDef); }) - .config(function( - getLinkInfo, moduleScopeLinkDisambiguator, deprecatedDocsLinkDisambiguator) { - getLinkInfo.disambiguators.push(moduleScopeLinkDisambiguator); - getLinkInfo.disambiguators.push(deprecatedDocsLinkDisambiguator); + .config(function(getDocFromAlias, disambiguateByDeprecated, disambiguateByModule) { + getDocFromAlias.disambiguators = [ + disambiguateByDeprecated, + disambiguateByModule + ]; }); diff --git a/aio/tools/transforms/links-package/services/deprecatedDocsLinkDisambiguator.js b/aio/tools/transforms/links-package/services/deprecatedDocsLinkDisambiguator.js deleted file mode 100644 index 662d3e53e200a..0000000000000 --- a/aio/tools/transforms/links-package/services/deprecatedDocsLinkDisambiguator.js +++ /dev/null @@ -1,12 +0,0 @@ -var _ = require('lodash'); - -module.exports = function deprecatedDocsLinkDisambiguator() { - return function(url, title, currentDoc, docs) { - if (docs.length != 2) return docs; - - var filteredDocs = _.filter( - docs, function(doc) { return !doc.fileInfo.relativePath.match(/\/(\w+)-deprecated\//); }); - - return filteredDocs.length > 0 ? filteredDocs : docs; - }; -}; diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.js new file mode 100644 index 0000000000000..44427c9d40ad2 --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.js @@ -0,0 +1,3 @@ +module.exports = function disambiguateByDeprecated() { + return (alias, originatingDoc, docs) => docs.filter(doc => doc.deprecated === undefined); +}; diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.spec.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.spec.js new file mode 100644 index 0000000000000..edc51aa9dd6b4 --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByDeprecated.spec.js @@ -0,0 +1,17 @@ +const disambiguateByDeprecated = require('./disambiguateByDeprecated')(); +const docs = [ + { id: 'doc1' }, + { id: 'doc2', deprecated: true }, + { id: 'doc3', deprecated: '' }, + { id: 'doc4' }, + { id: 'doc5', deprecated: 'Some text' }, +]; + +describe('disambiguateByDeprecated', () => { + it('should filter out docs whose `deprecated` property is defined', () => { + expect(disambiguateByDeprecated('alias', {}, docs)).toEqual([ + { id: 'doc1' }, + { id: 'doc4' }, + ]); + }); +}); \ No newline at end of file diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.js new file mode 100644 index 0000000000000..8ed131477fa79 --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.js @@ -0,0 +1,12 @@ +module.exports = function disambiguateByModule() { + return (alias, originatingDoc, docs) => { + const originatingModule = originatingDoc && originatingDoc.moduleDoc; + if (originatingModule) { + const filteredDocs = docs.filter(doc => doc.moduleDoc === originatingModule); + if (filteredDocs.length > 0) { + return filteredDocs; + } + } + return docs; + }; +}; diff --git a/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.spec.js b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.spec.js new file mode 100644 index 0000000000000..f80e24ae859f9 --- /dev/null +++ b/aio/tools/transforms/links-package/services/disambiguators/disambiguateByModule.spec.js @@ -0,0 +1,29 @@ +const disambiguateByModule = require('./disambiguateByModule')(); +const moduleA = { name: 'a' }; +const moduleB = { name: 'b' }; +const docs = [ + { id: 'doc1', moduleDoc: moduleA }, + { id: 'doc2', moduleDoc: moduleA }, + { id: 'doc3', moduleDoc: moduleB }, +]; + +describe('disambiguateByModule', () => { + it('should return all docs if the originating doc has no moduleDoc', () => { + expect(disambiguateByModule('alias', { }, docs)).toEqual(docs); + }); + + it('should return all docs if no docs match the originating doc moduleDoc', () => { + expect(disambiguateByModule('alias', { moduleDoc: { name: 'c' } }, docs)).toEqual(docs); + }); + + it('should return only docs that match the moduleDoc of the originating doc', () => { + expect(disambiguateByModule('alias', { moduleDoc: moduleA }, docs)).toEqual([ + { id: 'doc1', moduleDoc: moduleA }, + { id: 'doc2', moduleDoc: moduleA }, + ]); + + expect(disambiguateByModule('alias', { moduleDoc: moduleB }, docs)).toEqual([ + { id: 'doc3', moduleDoc: moduleB }, + ]); + }); +}); \ No newline at end of file diff --git a/aio/tools/transforms/links-package/services/getDocFromAlias.js b/aio/tools/transforms/links-package/services/getDocFromAlias.js index 8860198c3cdb2..3cb8173669c6f 100644 --- a/aio/tools/transforms/links-package/services/getDocFromAlias.js +++ b/aio/tools/transforms/links-package/services/getDocFromAlias.js @@ -1,31 +1,23 @@ -var _ = require('lodash'); - /** * @dgService getDocFromAlias * @description Get an array of docs that match this alias, relative to the originating doc. + * + * @property {Array<(alias: string, originatingDoc: Doc, ambiguousDocs: Doc[]) => Doc[]>} disambiguators + * a collection of functions that attempt to resolve ambiguous links. Each disambiguator returns + * a new collection of docs with unwanted ambiguous docs removed (see links-package/service/disambiguators + * for examples). */ module.exports = function getDocFromAlias(aliasMap) { - return function getDocFromAlias(alias, originatingDoc) { - var docs = aliasMap.getDocs(alias); - - // If there is more than one item with this name then try to filter them by the originatingDoc's - // area - if (docs.length > 1 && originatingDoc && originatingDoc.area) { - docs = _.filter(docs, function(doc) { return doc.area === originatingDoc.area; }); - } - - // If filtering by area left us with none then let's start again - if (docs.length === 0) { - docs = aliasMap.getDocs(alias); - } - - // If there is more than one item with this name then try to filter them by the originatingDoc's - // module - if (docs.length > 1 && originatingDoc && originatingDoc.module) { - docs = _.filter(docs, function(doc) { return doc.module === originatingDoc.module; }); - } + getDocFromAlias.disambiguators = []; + return getDocFromAlias; - return docs; - }; + function getDocFromAlias(alias, originatingDoc) { + return getDocFromAlias.disambiguators.reduce( + // Run the disambiguators while there is more than 1 doc found + (docs, disambiguater) => docs.length > 1 ? disambiguater(alias, originatingDoc, docs) : docs, + // Start with the docs that match the alias + aliasMap.getDocs(alias) + ); + } }; diff --git a/aio/tools/transforms/links-package/services/getDocFromAlias.spec.js b/aio/tools/transforms/links-package/services/getDocFromAlias.spec.js index c5b24a47f296d..989ff43ab64cb 100644 --- a/aio/tools/transforms/links-package/services/getDocFromAlias.spec.js +++ b/aio/tools/transforms/links-package/services/getDocFromAlias.spec.js @@ -3,15 +3,15 @@ var Dgeni = require('dgeni'); var getDocFromAlias, aliasMap; -describe('getDocFromAlias', function() { - beforeEach(function() { +describe('getDocFromAlias', () => { + beforeEach(() => { var dgeni = new Dgeni([testPackage('links-package', true)]); var injector = dgeni.configureInjector(); aliasMap = injector.get('aliasMap'); getDocFromAlias = injector.get('getDocFromAlias'); }); - it('should return an array of docs that match the alias', function() { + it('should return an array of docs that match the alias', () => { var doc1 = {aliases: ['a', 'b', 'c']}; var doc2 = {aliases: ['a', 'b']}; var doc3 = {aliases: ['a']}; @@ -24,25 +24,24 @@ describe('getDocFromAlias', function() { expect(getDocFromAlias('c')).toEqual([doc1]); }); - it('should return docs that match the alias and originating doc\'s area', function() { - var doc1 = {aliases: ['a'], area: 'api'}; - var doc2 = {aliases: ['a'], area: 'api'}; - var doc3 = {aliases: ['a'], area: 'other'}; - aliasMap.addDoc(doc1); - aliasMap.addDoc(doc2); - aliasMap.addDoc(doc3); - - expect(getDocFromAlias('a', {area: 'api'})).toEqual([doc1, doc2]); - }); + it('should filter ambiguous docs by calling each disambiguator', () => { + getDocFromAlias.disambiguators = [ + (alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('X') !== -1), // only if X appears in name + (alias, originatingDoc, docs) => docs.filter(doc => doc.name.indexOf('Y') !== -1) // only if Y appears in name + ]; - it('should return docs that match the alias and originating doc\'s area and module', function() { - var doc1 = {aliases: ['a'], area: 'api', module: 'ng'}; - var doc2 = {aliases: ['a'], area: 'api', module: 'ngMock'}; - var doc3 = {aliases: ['a'], area: 'other', module: 'ng'}; + var doc1 = {name: 'X', aliases: ['a', 'b', 'c']}; + var doc2 = {name: 'Y', aliases: ['a', 'b']}; + var doc3 = {name: 'XY', aliases: ['a', 'c']}; aliasMap.addDoc(doc1); aliasMap.addDoc(doc2); aliasMap.addDoc(doc3); - expect(getDocFromAlias('a', {area: 'api', module: 'ng'})).toEqual([doc1]); + // doc1 and doc2 get removed as they don't both have X and Y in name + expect(getDocFromAlias('a')).toEqual([doc3]); + // doc2 gets removed as it has no X; then we have only one doc left so second disambiguator never runs + expect(getDocFromAlias('b')).toEqual([doc1]); + // doc1 gets removed as it has no Y; then we have only one doc left (which would anyway pass 2nd disambiguator) + expect(getDocFromAlias('c')).toEqual([doc3]); }); }); \ No newline at end of file diff --git a/aio/tools/transforms/links-package/services/getLinkInfo.js b/aio/tools/transforms/links-package/services/getLinkInfo.js index fd6b57dab05da..7b9eb61237a3b 100644 --- a/aio/tools/transforms/links-package/services/getLinkInfo.js +++ b/aio/tools/transforms/links-package/services/getLinkInfo.js @@ -10,14 +10,9 @@ var path = require('canonical-path'); * @return {Object} The link information * * @property {boolean} relativeLinks Whether we expect the links to be relative to the originating doc - * @property {array 1) { linkInfo.valid = false; linkInfo.errorType = 'ambiguous'; @@ -80,5 +70,4 @@ module.exports = function getLinkInfo(getDocFromAlias, encodeCodeBlock, log) { return linkInfo; } - }; diff --git a/aio/tools/transforms/links-package/services/moduleScopeLinkDisambiguator.js b/aio/tools/transforms/links-package/services/moduleScopeLinkDisambiguator.js deleted file mode 100644 index 08435b96eef88..0000000000000 --- a/aio/tools/transforms/links-package/services/moduleScopeLinkDisambiguator.js +++ /dev/null @@ -1,15 +0,0 @@ -var _ = require('lodash'); - -module.exports = function moduleScopeLinkDisambiguator() { - return function(url, title, currentDoc, docs) { - if (docs.length > 1) { - // filter out target docs that are not in the same module as the source doc - var filteredDocs = - _.filter(docs, function(doc) { return doc.moduleDoc === currentDoc.moduleDoc; }); - // if all target docs are in a different module then just return the full collection of - // ambiguous docs - return filteredDocs.length > 0 ? filteredDocs : docs; - } - return docs; - }; -}; From 27962f89495010b464c8e18800183e22c744af9b Mon Sep 17 00:00:00 2001 From: Pete Bacon Darwin Date: Wed, 28 Feb 2018 14:52:53 +0000 Subject: [PATCH 08/18] build(aio): improve accuracy of code auto-linking (#22494) The new version of `dgeni-packages/typescript` no longer strips out "namespaces" from types, which was part of the problem of not autolinking correctly to `HttpEventType.Response`. Another part of the problem was that we did not include `.` characters when matching potential code blocks for auto-linking, which precluded properties of enums from being linked. Finally, members we not being given a `path` property, which is needed to effectively autolink to them. This is now set in the `simplifyMemberAnchors` processor. Closes #21375 PR Close #22494 --- aio/package.json | 2 +- .../transforms/angular-api-package/index.js | 2 +- .../processors/simplifyMemberAnchors.js | 14 ++-- .../processors/simplifyMemberAnchors.spec.js | 72 +++++++++++++++++++ .../post-processors/auto-link-code.js | 2 +- .../post-processors/auto-link-code.spec.js | 9 ++- aio/yarn.lock | 6 +- 7 files changed, 96 insertions(+), 11 deletions(-) create mode 100644 aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.spec.js diff --git a/aio/package.json b/aio/package.json index e7f1a02e78188..a9d0d17e50f51 100644 --- a/aio/package.json +++ b/aio/package.json @@ -107,7 +107,7 @@ "cross-spawn": "^5.1.0", "css-selector-parser": "^1.3.0", "dgeni": "^0.4.7", - "dgeni-packages": "^0.24.0", + "dgeni-packages": "^0.25.0", "entities": "^1.1.1", "eslint": "^3.19.0", "eslint-plugin-jasmine": "^2.2.0", diff --git a/aio/tools/transforms/angular-api-package/index.js b/aio/tools/transforms/angular-api-package/index.js index 26a6e6e220faa..0c5b2365ac7ac 100644 --- a/aio/tools/transforms/angular-api-package/index.js +++ b/aio/tools/transforms/angular-api-package/index.js @@ -131,6 +131,6 @@ module.exports = new Package('angular-api', [basePackage, typeScriptPackage]) ]); convertToJsonProcessor.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT); postProcessHtml.docTypes = convertToJsonProcessor.docTypes.concat(DOCS_TO_CONVERT); - autoLinkCode.docTypes = DOCS_TO_CONVERT; + autoLinkCode.docTypes = DOCS_TO_CONVERT.concat(['member']); autoLinkCode.codeElements = ['code', 'code-example', 'code-pane']; }); diff --git a/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.js b/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.js index 2519d22870bb8..f36a8d480940e 100644 --- a/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.js +++ b/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.js @@ -5,15 +5,21 @@ */ module.exports = function simplifyMemberAnchors() { return { - $runAfter: ['extra-docs-added'], - $runBefore: ['computing-paths'], + $runAfter: ['paths-computed'], + $runBefore: ['rendering-docs'], $process: function(docs) { return docs.forEach(doc => { if (doc.members) { - doc.members.forEach(member => member.anchor = computeAnchor(member)); + doc.members.forEach(member => { + member.anchor = computeAnchor(member); + member.path = doc.path + '#' + member.anchor; + }); } if (doc.statics) { - doc.statics.forEach(member => member.anchor = computeAnchor(member)); + doc.statics.forEach(member => { + member.anchor = computeAnchor(member); + member.path = doc.path + '#' + member.anchor; + }); } }); } diff --git a/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.spec.js b/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.spec.js new file mode 100644 index 0000000000000..b857af196d7dd --- /dev/null +++ b/aio/tools/transforms/angular-api-package/processors/simplifyMemberAnchors.spec.js @@ -0,0 +1,72 @@ +const testPackage = require('../../helpers/test-package'); +const processorFactory = require('./simplifyMemberAnchors'); +const Dgeni = require('dgeni'); + +describe('simplifyMemberAnchors processor', () => { + + it('should be available on the injector', () => { + const dgeni = new Dgeni([testPackage('angular-api-package')]); + const injector = dgeni.configureInjector(); + const processor = injector.get('simplifyMemberAnchors'); + expect(processor.$process).toBeDefined(); + expect(processor.$runAfter).toEqual(['paths-computed']); + expect(processor.$runBefore).toEqual(['rendering-docs']); + }); + + describe('$process', () => { + describe('docs without members', () => { + it('should ignore the docs', () => { + const processor = processorFactory(); + const docs = [ + { id: 'some-doc' }, + { id: 'some-other' } + ]; + processor.$process(docs); + expect(docs).toEqual([ + { id: 'some-doc' }, + { id: 'some-other' } + ]); + }); + }); + + describe('docs with members', () => { + it('should compute an anchor for each instance member', () => { + const processor = processorFactory(); + const docs = [ + { id: 'some-doc', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] } + ]; + processor.$process(docs); + expect(docs[0].members.map(member => member.anchor)).toEqual(['foo', 'new', 'call']); + }); + + it('should compute a path for each instance member', () => { + const processor = processorFactory(); + const docs = [ + { id: 'some-doc', path: 'a/b/c', members: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] } + ]; + processor.$process(docs); + expect(docs[0].members.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']); + }); + }); + + describe('docs with static members', () => { + it('should compute an anchor for each static member', () => { + const processor = processorFactory(); + const docs = [ + { id: 'some-doc', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] } + ]; + processor.$process(docs); + expect(docs[0].statics.map(member => member.anchor)).toEqual(['foo', 'new', 'call']); + }); + + it('should compute a path for each static member', () => { + const processor = processorFactory(); + const docs = [ + { id: 'some-doc', path: 'a/b/c', statics: [ { name: 'foo' }, { name: 'new' }, { name: '' } ] } + ]; + processor.$process(docs); + expect(docs[0].statics.map(member => member.path)).toEqual(['a/b/c#foo', 'a/b/c#new', 'a/b/c#call']); + }); + }); + }); +}); diff --git a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js index baf114aaaa9e5..fae9ba475ebb9 100644 --- a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js +++ b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.js @@ -45,7 +45,7 @@ module.exports = function autoLinkCode(getDocFromAlias) { parent.children.splice(index, 1, createLinkNode(docs[0], node.value)); } else { // Parse the text for words that we can convert to links - const nodes = textContent(node).split(/([A-Za-z0-9_-]+)/) + const nodes = textContent(node).split(/([A-Za-z0-9_.-]+)/) .filter(word => word.length) .map((word, index, words) => { // remove docs that fail the custom filter tests diff --git a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.spec.js b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.spec.js index c37b2165dfd1f..f300487aed3f8 100644 --- a/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.spec.js +++ b/aio/tools/transforms/angular-base-package/post-processors/auto-link-code.spec.js @@ -9,7 +9,7 @@ describe('autoLinkCode post-processor', () => { const dgeni = new Dgeni([testPackage]); const injector = dgeni.configureInjector(); autoLinkCode = injector.get('autoLinkCode'); - autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const']; + autoLinkCode.docTypes = ['class', 'pipe', 'function', 'const', 'member']; aliasMap = injector.get('aliasMap'); processor = injector.get('postProcessHtml'); processor.docTypes = ['test-doc']; @@ -31,6 +31,13 @@ describe('autoLinkCode post-processor', () => { expect(doc.renderedContent).toEqual('foo.MyClass'); }); + it('should match code items within a block of code that contain a dot in their identifier', () => { + aliasMap.addDoc({ docType: 'member', id: 'MyEnum.Value', aliases: ['Value', 'MyEnum.Value'], path: 'a/b/myenum' }); + const doc = { docType: 'test-doc', renderedContent: 'someFn(): MyEnum.Value' }; + processor.$process([doc]); + expect(doc.renderedContent).toEqual('someFn(): MyEnum.Value'); + }); + it('should ignore code items that do not match a link to an API doc', () => { aliasMap.addDoc({ docType: 'guide', id: 'MyClass', aliases: ['MyClass'], path: 'a/b/myclass' }); const doc = { docType: 'test-doc', renderedContent: 'MyClass' }; diff --git a/aio/yarn.lock b/aio/yarn.lock index 4acead46b1a75..7545c27601b92 100644 --- a/aio/yarn.lock +++ b/aio/yarn.lock @@ -2312,9 +2312,9 @@ devtools-timeline-model@1.1.6: chrome-devtools-frontend "1.0.401423" resolve "1.1.7" -dgeni-packages@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.24.0.tgz#2f995f78fecd6a9ded72d7bdccbbc4c46360c1ea" +dgeni-packages@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/dgeni-packages/-/dgeni-packages-0.25.0.tgz#380f0b569ae36d82959252604b729e85e0cd7d4a" dependencies: canonical-path "0.0.2" catharsis "^0.8.1" From fe0d53f3a975d6a19860351bb9551623fe0db55a Mon Sep 17 00:00:00 2001 From: Rado Kirov Date: Wed, 28 Feb 2018 22:52:31 -0800 Subject: [PATCH 09/18] build: Add support for bazelOptions.maxCacheSizeMb in ngc-wrapped. (#22511) PR Close #22511 --- packages/bazel/src/ngc-wrapped/index.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/bazel/src/ngc-wrapped/index.ts b/packages/bazel/src/ngc-wrapped/index.ts index 2c066ef22f55b..99b3e1ef12264 100644 --- a/packages/bazel/src/ngc-wrapped/index.ts +++ b/packages/bazel/src/ngc-wrapped/index.ts @@ -95,6 +95,13 @@ export function compile({allowNonHermeticReads, allDepsCompiledWithBazel = true, }): {diagnostics: ng.Diagnostics, program: ng.Program} { let fileLoader: FileLoader; + if (bazelOpts.maxCacheSizeMb !== undefined) { + const maxCacheSizeBytes = bazelOpts.maxCacheSizeMb * (1 << 20); + fileCache.setMaxCacheSize(maxCacheSizeBytes); + } else { + fileCache.resetMaxCacheSize(); + } + if (inputs) { fileLoader = new CachedFileLoader(fileCache, allowNonHermeticReads); // Resolve the inputs to absolute paths to match TypeScript internals From ff7e2e3f1e2f71979cc4b4ab742c90126643afba Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Thu, 1 Mar 2018 07:15:30 -0800 Subject: [PATCH 10/18] ci: speed up lint job on CircleCI (#22526) When I enabled bazel remote caching, I also switched to running buildifier and skylint from the package.json script, which builds them from head. With remote caching, we do get cache hits for these, but looking up the action inputs actually takes quite a bit of time since we have to first fetch the remote repository, then do loading and analysis, then read the inputs to determine the cache key. It's more important to keep the lint job fast, so I'm reverting that part of the change for now. We can experiment with building them from head in a less critical repo. PR Close #22526 --- .circleci/config.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 975038713617f..dcc04f93e19b7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -41,14 +41,14 @@ jobs: steps: - checkout: <<: *post_checkout - # See remote cache documentation in /docs/BAZEL.md - - run: .circleci/setup_cache.sh - - run: sudo cp .circleci/bazel.rc /etc/bazel.bazelrc - - *setup-bazel-remote-cache - - run: 'yarn buildifier -mode=check || - (echo -e "\nBUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)' - - run: 'yarn skylint || + # Check BUILD.bazel formatting before we have a node_modules directory + # Then we don't need any exclude pattern to avoid checking those files + - run: 'buildifier -mode=check $(find . -type f \( -name BUILD.bazel -or -name BUILD \)) || + (echo "BUILD files not formatted. Please run ''yarn buildifier''" ; exit 1)' + # Run the skylark linter to check our Bazel rules + - run: 'find . -type f -name "*.bzl" | + xargs java -jar /usr/local/bin/Skylint_deploy.jar || (echo -e "\n.bzl files have lint errors. Please run ''yarn skylint''"; exit 1)' - restore_cache: From a3f7e3015324a811d02918481f6320aad906fcb9 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Fri, 2 Mar 2018 10:10:59 -0800 Subject: [PATCH 11/18] build: update to latest bazel rules (#22558) PR Close #22558 --- WORKSPACE | 18 ++++++----------- integration/bazel/WORKSPACE | 20 ++++++------------- packages/bazel/src/esm5.bzl | 2 +- packages/bazel/src/ngc-wrapped/BUILD.bazel | 2 +- packages/service-worker/worker/src/driver.ts | 8 ++++---- .../service-worker/worker/test/happy_spec.ts | 2 +- 6 files changed, 19 insertions(+), 33 deletions(-) diff --git a/WORKSPACE b/WORKSPACE index 96200b63a0fb7..c37ca88168133 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -1,14 +1,10 @@ workspace(name = "angular") -# Using a pre-release snapshot to pick up a commit that makes all nodejs_binary -# programs produce source-mapped stack traces. -RULES_NODEJS_VERSION = "926349cea4cd360afcd5647ccdd09d2d2fb471aa" - http_archive( name = "build_bazel_rules_nodejs", - url = "https://github.com/bazelbuild/rules_nodejs/archive/%s.zip" % RULES_NODEJS_VERSION, - strip_prefix = "rules_nodejs-%s" % RULES_NODEJS_VERSION, - sha256 = "5ba3c8c209078c2e3f0c6aa4abd01a1a561f92a5bfda04e25604af5f4734d69d", + url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip", + strip_prefix = "rules_nodejs-0.5.0", + sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6", ) load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_repositories") @@ -16,13 +12,11 @@ load("@build_bazel_rules_nodejs//:defs.bzl", "check_bazel_version", "node_reposi check_bazel_version("0.9.0") node_repositories(package_json = ["//:package.json"]) -RULES_TYPESCRIPT_VERSION = "d3cc5cd72d89aee0e4c2553ae1b99c707ecbef4e" - http_archive( name = "build_bazel_rules_typescript", - url = "https://github.com/bazelbuild/rules_typescript/archive/%s.zip" % RULES_TYPESCRIPT_VERSION, - strip_prefix = "rules_typescript-%s" % RULES_TYPESCRIPT_VERSION, - sha256 = "a233fcca41c3e59f639ac71c396edb30e9e9716cf8ed5fb20b51ff8910d5d895", + url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.0.zip", + strip_prefix = "rules_typescript-0.11.0", + sha256 = "ce7bac7b5287d5162fcbe4f7c14ff507ae7d506ceb44626ad09f6b7e27d3260b", ) load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace") diff --git a/integration/bazel/WORKSPACE b/integration/bazel/WORKSPACE index e33263b087330..06ca4806eb5d2 100644 --- a/integration/bazel/WORKSPACE +++ b/integration/bazel/WORKSPACE @@ -1,28 +1,20 @@ workspace(name = "bazel_integration_test") -load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") - -# Using a pre-release snapshot to pick up a commit that makes all nodejs_binary -# programs produce source-mapped stack traces. -RULES_NODEJS_VERSION = "926349cea4cd360afcd5647ccdd09d2d2fb471aa" - http_archive( name = "build_bazel_rules_nodejs", - url = "https://github.com/bazelbuild/rules_nodejs/archive/%s.zip" % RULES_NODEJS_VERSION, - strip_prefix = "rules_nodejs-%s" % RULES_NODEJS_VERSION, - sha256 = "5ba3c8c209078c2e3f0c6aa4abd01a1a561f92a5bfda04e25604af5f4734d69d", + url = "https://github.com/bazelbuild/rules_nodejs/archive/0.5.0.zip", + strip_prefix = "rules_nodejs-0.5.0", + sha256 = "06aabb253c3867d51724386ac5622a0a238bbd82e2c70ce1d09ee3ceac4c31d6", ) load("@build_bazel_rules_nodejs//:defs.bzl", "node_repositories") node_repositories(package_json = ["//:package.json"]) -RULES_TYPESCRIPT_VERSION = "d3cc5cd72d89aee0e4c2553ae1b99c707ecbef4e" - http_archive( name = "build_bazel_rules_typescript", - url = "https://github.com/bazelbuild/rules_typescript/archive/%s.zip" % RULES_TYPESCRIPT_VERSION, - strip_prefix = "rules_typescript-%s" % RULES_TYPESCRIPT_VERSION, - sha256 = "a233fcca41c3e59f639ac71c396edb30e9e9716cf8ed5fb20b51ff8910d5d895", + url = "https://github.com/bazelbuild/rules_typescript/archive/0.11.0.zip", + strip_prefix = "rules_typescript-0.11.0", + sha256 = "ce7bac7b5287d5162fcbe4f7c14ff507ae7d506ceb44626ad09f6b7e27d3260b", ) load("@build_bazel_rules_typescript//:defs.bzl", "ts_setup_workspace") diff --git a/packages/bazel/src/esm5.bzl b/packages/bazel/src/esm5.bzl index 514ed7e35747b..0d550c5579269 100644 --- a/packages/bazel/src/esm5.bzl +++ b/packages/bazel/src/esm5.bzl @@ -113,7 +113,7 @@ esm5_outputs_aspect = aspect( # For some reason, having the compiler output as an input to the action above # is not sufficient. "_tsc_wrapped": attr.label( - default = Label("@build_bazel_rules_typescript//internal/tsc_wrapped:tsc_wrapped_bin"), + default = Label("@build_bazel_rules_typescript//internal:tsc_wrapped_bin"), executable = True, cfg = "host", ), diff --git a/packages/bazel/src/ngc-wrapped/BUILD.bazel b/packages/bazel/src/ngc-wrapped/BUILD.bazel index beca2b1f0f49d..75b98f6d71602 100644 --- a/packages/bazel/src/ngc-wrapped/BUILD.bazel +++ b/packages/bazel/src/ngc-wrapped/BUILD.bazel @@ -16,7 +16,7 @@ ts_library( # Users will get this dependency from node_modules. "//packages/compiler-cli", # END-INTERNAL - "@build_bazel_rules_typescript//internal/tsc_wrapped", + "@build_bazel_rules_typescript//internal:tsc_wrapped", ], ) diff --git a/packages/service-worker/worker/src/driver.ts b/packages/service-worker/worker/src/driver.ts index 65c1d3c9f1edf..b4e046539f8b4 100644 --- a/packages/service-worker/worker/src/driver.ts +++ b/packages/service-worker/worker/src/driver.ts @@ -243,7 +243,7 @@ export class Driver implements Debuggable, UpdateSource { } private async handlePush(data: any): Promise { - this.broadcast({ + await this.broadcast({ type: 'PUSH', data, }); @@ -254,7 +254,7 @@ export class Driver implements Debuggable, UpdateSource { let options: {[key: string]: string | undefined} = {}; NOTIFICATION_OPTION_NAMES.filter(name => desc.hasOwnProperty(name)) .forEach(name => options[name] = desc[name]); - this.scope.registration.showNotification(desc['title'] !, options); + await this.scope.registration.showNotification(desc['title'] !, options); } private async reportStatus(client: Client, promise: Promise, nonce: number): Promise { @@ -614,7 +614,7 @@ export class Driver implements Debuggable, UpdateSource { if (!res.ok) { if (res.status === 404) { await this.deleteAllCaches(); - this.scope.registration.unregister(); + await this.scope.registration.unregister(); } throw new Error('Manifest fetch failed!'); } @@ -707,7 +707,7 @@ export class Driver implements Debuggable, UpdateSource { // Firstly, check if the manifest version is correct. if (manifest.configVersion !== SUPPORTED_CONFIG_VERSION) { await this.deleteAllCaches(); - this.scope.registration.unregister(); + await this.scope.registration.unregister(); throw new Error( `Invalid config version: expected ${SUPPORTED_CONFIG_VERSION}, got ${manifest.configVersion}.`); } diff --git a/packages/service-worker/worker/test/happy_spec.ts b/packages/service-worker/worker/test/happy_spec.ts index bf0d71fd2a6ae..994e6f326dfd2 100644 --- a/packages/service-worker/worker/test/happy_spec.ts +++ b/packages/service-worker/worker/test/happy_spec.ts @@ -527,7 +527,7 @@ const manifestUpdateHash = sha1(JSON.stringify(manifestUpdate)); expect(await driver.checkForUpdate()).toEqual(true); serverUpdate.assertSawRequestFor('/quux.txt'); serverUpdate.clearRequests(); - driver.updateClient(await scope.clients.get('default')); + await driver.updateClient(await scope.clients.get('default')); expect(await makeRequest(scope, '/quux.txt')).toEqual('this is quux v2'); serverUpdate.assertNoOtherRequests(); }); From 984a13e45b7481b415101772e344b8f9a668ea0b Mon Sep 17 00:00:00 2001 From: "SangKa.Z" Date: Fri, 2 Mar 2018 21:52:58 +0800 Subject: [PATCH 12/18] docs(aio): fix table header (#22553) PR Close #22553 --- aio/content/guide/comparing-observables.md | 28 ++++++++++++---------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/aio/content/guide/comparing-observables.md b/aio/content/guide/comparing-observables.md index 9cb663cd56de8..5e7b9b0ca4aed 100644 --- a/aio/content/guide/comparing-observables.md +++ b/aio/content/guide/comparing-observables.md @@ -89,11 +89,11 @@ promise.then(() => { The following code snippets illustrate how the same kind of operation is defined using observables and promises. - - - - + + + + +
- OperationObservablePromise
OperationObservablePromise
Creation @@ -141,10 +141,11 @@ Using observables to handle events and asynchronous operations can have the adva Here are some code samples that illustrate how the same kind of operation is defined using observables and the events API. - - - + + + + +
- ObservableEvents API
ObservableEvents API
Creation & cancellation @@ -203,10 +204,11 @@ button.removeEventListener(‘click’, handler); An observable produces values over time. An array is created as a static set of values. In a sense, observables are asynchronous where arrays are synchronous. In the following examples, ➞ implies asynchronous value delivery. - - - + + + + +
- ObservableArray
ObservableArray
Given From 789a47ec44c28d7ab51c2a59cde92324d30e2960 Mon Sep 17 00:00:00 2001 From: Jason Aden Date: Tue, 20 Feb 2018 15:08:41 -0800 Subject: [PATCH 13/18] fix(router): fix URL serialization so special characters are only encoded where needed (#22337) This change brings Angular largely in line with how AngularJS previously serialized URLs. This is based on RFC 3986 and resolves issues such as the above #10280 where URLs could be parsed, re-serialized, then parsed again producing a different result on the second parsing. Adjustments to be aware of in this commit: * URI fragments will now serialize the same as query strings * In the URI path or segments (portion prior to query string and/or fragment), the plus sign (`+`) and ampersand (`&`) will appear decoded * In the URL path or segments, parentheses values (`(` and `)`) will now appear percent encoded as `%28` and `%29` respectively * In the URL path or segments, semicolons will be encoded in their percent encoding `%3B` NOTE: Parentheses and semicolons denoting auxillary routes or matrix params will still appear in their decoded form -- only parentheses and semicolons used as values in a segment or key/value pair for matrix params will be encoded. While these changes are not considered breaking because applications should be decoding URLs and key/value pairs, it is possible that some unit tests will break if comparing hard-coded URLs in tests since that hard coded string will represent the old encoding. Therefore we are releasing this fix in the upcoming Angular v6 rather than adding it to a patch for v5. Fixes: #10280 PR Close #22337 --- packages/router/src/url_tree.ts | 60 ++++++--- packages/router/test/url_serializer.spec.ts | 141 ++++++++++++++++++-- 2 files changed, 174 insertions(+), 27 deletions(-) diff --git a/packages/router/src/url_tree.ts b/packages/router/src/url_tree.ts index 63c3a7ea018f7..13f0ab46e16d9 100644 --- a/packages/router/src/url_tree.ts +++ b/packages/router/src/url_tree.ts @@ -280,7 +280,7 @@ export class DefaultUrlSerializer implements UrlSerializer { serialize(tree: UrlTree): string { const segment = `/${serializeSegment(tree.root, true)}`; const query = serializeQueryParams(tree.queryParams); - const fragment = typeof tree.fragment === `string` ? `#${encodeURI(tree.fragment !)}` : ''; + const fragment = typeof tree.fragment === `string` ? `#${encodeUriQuery(tree.fragment !)}` : ''; return `${segment}${query}${fragment}`; } @@ -326,9 +326,10 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string { } /** - * This method is intended for encoding *key* or *value* parts of query component. We need a custom - * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be - * encoded per http://tools.ietf.org/html/rfc3986: + * Encodes a URI string with the default encoding. This function will only ever be called from + * `encodeUriQuery` or `encodeUriSegment` as it's the base set of encodings to be used. We need + * a custom encoding because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: * query = *( pchar / "/" / "?" ) * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" @@ -336,32 +337,61 @@ function serializeSegment(segment: UrlSegmentGroup, root: boolean): string { * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" * / "*" / "+" / "," / ";" / "=" */ -export function encode(s: string): string { +function encodeUriString(s: string): string { return encodeURIComponent(s) .replace(/%40/g, '@') .replace(/%3A/gi, ':') .replace(/%24/g, '$') - .replace(/%2C/gi, ',') - .replace(/%3B/gi, ';'); + .replace(/%2C/gi, ','); +} + +/** + * This function should be used to encode both keys and values in a query string key/value or the + * URL fragment. In the following URL, you need to call encodeUriQuery on "k", "v" and "f": + * + * http://www.site.org/html;mk=mv?k=v#f + */ +export function encodeUriQuery(s: string): string { + return encodeUriString(s).replace(/%3B/gi, ';'); +} + +/** + * This function should be run on any URI segment as well as the key and value in a key/value + * pair for matrix params. In the following URL, you need to call encodeUriSegment on "html", + * "mk", and "mv": + * + * http://www.site.org/html;mk=mv?k=v#f + */ +export function encodeUriSegment(s: string): string { + return encodeUriString(s).replace(/\(/g, '%28').replace(/\)/g, '%29').replace(/%26/gi, '&'); } export function decode(s: string): string { return decodeURIComponent(s); } +// Query keys/values should have the "+" replaced first, as "+" in a query string is " ". +// decodeURIComponent function will not decode "+" as a space. +export function decodeQuery(s: string): string { + return decode(s.replace(/\+/g, '%20')); +} + export function serializePath(path: UrlSegment): string { - return `${encode(path.path)}${serializeParams(path.parameters)}`; + return `${encodeUriSegment(path.path)}${serializeMatrixParams(path.parameters)}`; } -function serializeParams(params: {[key: string]: string}): string { - return Object.keys(params).map(key => `;${encode(key)}=${encode(params[key])}`).join(''); +function serializeMatrixParams(params: {[key: string]: string}): string { + return Object.keys(params) + .map(key => `;${encodeUriSegment(key)}=${encodeUriSegment(params[key])}`) + .join(''); } function serializeQueryParams(params: {[key: string]: any}): string { const strParams: string[] = Object.keys(params).map((name) => { const value = params[name]; - return Array.isArray(value) ? value.map(v => `${encode(name)}=${encode(v)}`).join('&') : - `${encode(name)}=${encode(value)}`; + return Array.isArray(value) ? + value.map(v => `${encodeUriQuery(name)}=${encodeUriQuery(v)}`).join('&') : + `${encodeUriQuery(name)}=${encodeUriQuery(value)}`; }); return strParams.length ? `?${strParams.join("&")}` : ''; @@ -414,7 +444,7 @@ class UrlParser { } parseFragment(): string|null { - return this.consumeOptional('#') ? decodeURI(this.remaining) : null; + return this.consumeOptional('#') ? decodeURIComponent(this.remaining) : null; } private parseChildren(): {[outlet: string]: UrlSegmentGroup} { @@ -506,8 +536,8 @@ class UrlParser { } } - const decodedKey = decode(key); - const decodedVal = decode(value); + const decodedKey = decodeQuery(key); + const decodedVal = decodeQuery(value); if (params.hasOwnProperty(decodedKey)) { // Append to existing values diff --git a/packages/router/test/url_serializer.spec.ts b/packages/router/test/url_serializer.spec.ts index a318011b10828..f71538cc3a788 100644 --- a/packages/router/test/url_serializer.spec.ts +++ b/packages/router/test/url_serializer.spec.ts @@ -7,7 +7,7 @@ */ import {PRIMARY_OUTLET} from '../src/shared'; -import {DefaultUrlSerializer, UrlSegmentGroup, encode, serializePath} from '../src/url_tree'; +import {DefaultUrlSerializer, UrlSegmentGroup, encodeUriQuery, encodeUriSegment, serializePath} from '../src/url_tree'; describe('url serializer', () => { const url = new DefaultUrlSerializer(); @@ -189,7 +189,7 @@ describe('url serializer', () => { describe('encoding/decoding', () => { it('should encode/decode path segments and parameters', () => { const u = - `/${encode("one two")};${encode("p 1")}=${encode("v 1")};${encode("p 2")}=${encode("v 2")}`; + `/${encodeUriSegment("one two")};${encodeUriSegment("p 1")}=${encodeUriSegment("v 1")};${encodeUriSegment("p 2")}=${encodeUriSegment("v 2")}`; const tree = url.parse(u); expect(tree.root.children[PRIMARY_OUTLET].segments[0].path).toEqual('one two'); @@ -199,7 +199,8 @@ describe('url serializer', () => { }); it('should encode/decode "slash" in path segments and parameters', () => { - const u = `/${encode("one/two")};${encode("p/1")}=${encode("v/1")}/three`; + const u = + `/${encodeUriSegment("one/two")};${encodeUriSegment("p/1")}=${encodeUriSegment("v/1")}/three`; const tree = url.parse(u); const segment = tree.root.children[PRIMARY_OUTLET].segments[0]; expect(segment.path).toEqual('one/two'); @@ -210,7 +211,8 @@ describe('url serializer', () => { }); it('should encode/decode query params', () => { - const u = `/one?${encode("p 1")}=${encode("v 1")}&${encode("p 2")}=${encode("v 2")}`; + const u = + `/one?${encodeUriQuery("p 1")}=${encodeUriQuery("v 1")}&${encodeUriQuery("p 2")}=${encodeUriQuery("v 2")}`; const tree = url.parse(u); expect(tree.queryParams).toEqual({'p 1': 'v 1', 'p 2': 'v 2'}); @@ -219,28 +221,143 @@ describe('url serializer', () => { expect(url.serialize(tree)).toEqual(u); }); + it('should decode spaces in query as %20 or +', () => { + const u1 = `/one?foo=bar baz`; + const u2 = `/one?foo=bar+baz`; + const u3 = `/one?foo=bar%20baz`; + + const u1p = url.parse(u1); + const u2p = url.parse(u2); + const u3p = url.parse(u3); + + expect(url.serialize(u1p)).toBe(url.serialize(u2p)); + expect(url.serialize(u2p)).toBe(url.serialize(u3p)); + expect(u1p.queryParamMap.get('foo')).toBe('bar baz'); + expect(u2p.queryParamMap.get('foo')).toBe('bar baz'); + expect(u3p.queryParamMap.get('foo')).toBe('bar baz'); + }); + it('should encode query params leaving sub-delimiters intact', () => { - const percentChars = '/?#[]&+= '; - const percentCharsEncoded = '%2F%3F%23%5B%5D%26%2B%3D%20'; + const percentChars = '/?#&+=[] '; + const percentCharsEncoded = '%2F%3F%23%26%2B%3D%5B%5D%20'; const intactChars = '!$\'()*,;:'; const params = percentChars + intactChars; const paramsEncoded = percentCharsEncoded + intactChars; const mixedCaseString = 'sTrInG'; - expect(percentCharsEncoded).toEqual(encode(percentChars)); - expect(intactChars).toEqual(encode(intactChars)); + expect(percentCharsEncoded).toEqual(encodeUriQuery(percentChars)); + expect(intactChars).toEqual(encodeUriQuery(intactChars)); // Verify it replaces repeated characters correctly - expect(paramsEncoded + paramsEncoded).toEqual(encode(params + params)); + expect(paramsEncoded + paramsEncoded).toEqual(encodeUriQuery(params + params)); // Verify it doesn't change the case of alpha characters - expect(mixedCaseString + paramsEncoded).toEqual(encode(mixedCaseString + params)); + expect(mixedCaseString + paramsEncoded).toEqual(encodeUriQuery(mixedCaseString + params)); }); it('should encode/decode fragment', () => { - const u = `/one#${encodeURI("one two=three four")}`; + const u = `/one#${encodeUriQuery('one two=three four')}`; const tree = url.parse(u); expect(tree.fragment).toEqual('one two=three four'); - expect(url.serialize(tree)).toEqual(u); + expect(url.serialize(tree)).toEqual('/one#one%20two%3Dthree%20four'); + }); + }); + + describe('special character encoding/decoding', () => { + + // Tests specific to https://github.com/angular/angular/issues/10280 + it('should parse encoded parens in matrix params', () => { + const auxRoutesUrl = '/abc;foo=(other:val)'; + const fooValueUrl = '/abc;foo=%28other:val%29'; + + const auxParsed = url.parse(auxRoutesUrl).root; + const fooParsed = url.parse(fooValueUrl).root; + + + // Test base case + expect(auxParsed.children[PRIMARY_OUTLET].segments.length).toBe(1); + expect(auxParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc'); + expect(auxParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({foo: ''}); + expect(auxParsed.children['other'].segments.length).toBe(1); + expect(auxParsed.children['other'].segments[0].path).toBe('val'); + + // Confirm matrix params are URL decoded + expect(fooParsed.children[PRIMARY_OUTLET].segments.length).toBe(1); + expect(fooParsed.children[PRIMARY_OUTLET].segments[0].path).toBe('abc'); + expect(fooParsed.children[PRIMARY_OUTLET].segments[0].parameters).toEqual({ + foo: '(other:val)' + }); + }); + + it('should serialize encoded parens in matrix params', () => { + const testUrl = '/abc;foo=%28one%29'; + + const parsed = url.parse(testUrl); + + expect(url.serialize(parsed)).toBe('/abc;foo=%28one%29'); + }); + + it('should not serialize encoded parens in query params', () => { + const testUrl = '/abc?foo=%28one%29'; + + const parsed = url.parse(testUrl); + + expect(parsed.queryParams).toEqual({foo: '(one)'}); + + expect(url.serialize(parsed)).toBe('/abc?foo=(one)'); + }); + + // Test special characters in general + + // From http://www.ietf.org/rfc/rfc3986.txt + const unreserved = `abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~`; + + it('should encode a minimal set of special characters in queryParams and fragment', () => { + const notEncoded = unreserved + `:@!$'*,();`; + const encode = ` +%&=#[]/?`; + const encoded = `%20%2B%25%26%3D%23%5B%5D%2F%3F`; + + const parsed = url.parse('/foo'); + + parsed.queryParams = {notEncoded, encode}; + + expect(url.serialize(parsed)).toBe(`/foo?notEncoded=${notEncoded}&encode=${encoded}`); + }); + + it('should encode a minimal set of special characters in fragment', () => { + const notEncoded = unreserved + `:@!$'*,();`; + const encode = ` +%&=#[]/?`; + const encoded = `%20%2B%25%26%3D%23%5B%5D%2F%3F`; + + const parsed = url.parse('/foo'); + + parsed.fragment = notEncoded + encode; + + expect(url.serialize(parsed)).toBe(`/foo#${notEncoded}${encoded}`); + }); + + it('should encode minimal special characters plus parens and semi-colon in matrix params', + () => { + const notEncoded = unreserved + `:@!$'*,&`; + const encode = ` /%=#()[];?+`; + const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`; + + const parsed = url.parse('/foo'); + + parsed.root.children[PRIMARY_OUTLET].segments[0].parameters = {notEncoded, encode}; + + expect(url.serialize(parsed)).toBe(`/foo;notEncoded=${notEncoded};encode=${encoded}`); + }); + + it('should encode special characters in the path the same as matrix params', () => { + const notEncoded = unreserved + `:@!$'*,&`; + const encode = ` /%=#()[];?+`; + const encoded = `%20%2F%25%3D%23%28%29%5B%5D%3B%3F%2B`; + + const parsed = url.parse('/foo'); + + parsed.root.children[PRIMARY_OUTLET].segments[0].path = notEncoded + encode; + + expect(url.serialize(parsed)).toBe(`/${notEncoded}${encoded}`); }); }); From 5b7b20863728722f8e2090fe0bfa6bbba24e612d Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Tue, 20 Feb 2018 17:10:46 -0800 Subject: [PATCH 14/18] docs: fix cli-quickstart doc and specs (#22338) * tests were broken * incorrect instructions. * didn't match current CLI template for new project PR Close #22338 --- .../cli-quickstart/src/app/app.component.html | 11 +++++------ .../cli-quickstart/src/app/app.component.spec.ts | 6 ++---- .../examples/cli-quickstart/src/app/app.component.ts | 2 +- aio/content/guide/quickstart.md | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/aio/content/examples/cli-quickstart/src/app/app.component.html b/aio/content/examples/cli-quickstart/src/app/app.component.html index 1a1d09dc781d4..24c56edee4d5e 100644 --- a/aio/content/examples/cli-quickstart/src/app/app.component.html +++ b/aio/content/examples/cli-quickstart/src/app/app.component.html @@ -1,20 +1,19 @@

- Welcome to {{title}}!! + Welcome to {{ title }}!

- Angular logo + Angular Logo

Here are some links to help you start:

- diff --git a/aio/content/examples/cli-quickstart/src/app/app.component.spec.ts b/aio/content/examples/cli-quickstart/src/app/app.component.spec.ts index 7d2799ceb660e..1f5da50d19fe9 100644 --- a/aio/content/examples/cli-quickstart/src/app/app.component.spec.ts +++ b/aio/content/examples/cli-quickstart/src/app/app.component.spec.ts @@ -1,7 +1,5 @@ import { TestBed, async } from '@angular/core/testing'; - import { AppComponent } from './app.component'; - describe('AppComponent', () => { beforeEach(async(() => { TestBed.configureTestingModule({ @@ -20,13 +18,13 @@ describe('AppComponent', () => { it(`should have as title 'app'`, async(() => { const fixture = TestBed.createComponent(AppComponent); const app = fixture.debugElement.componentInstance; - expect(app.title).toEqual('app'); + expect(app.title).toMatch(/app/i); })); it('should render title in a h1 tag', async(() => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.debugElement.nativeElement; - expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!!'); + expect(compiled.querySelector('h1').textContent).toMatch(/app/i); })); }); diff --git a/aio/content/examples/cli-quickstart/src/app/app.component.ts b/aio/content/examples/cli-quickstart/src/app/app.component.ts index 4c1b4a9bf7418..d977bbe40a3c6 100644 --- a/aio/content/examples/cli-quickstart/src/app/app.component.ts +++ b/aio/content/examples/cli-quickstart/src/app/app.component.ts @@ -11,6 +11,6 @@ import { Component } from '@angular/core'; // #enddocregion metadata // #docregion title, class export class AppComponent { - title = 'My First Angular App'; + title = 'My First Angular App!'; } // #enddocregion title, class diff --git a/aio/content/guide/quickstart.md b/aio/content/guide/quickstart.md index 6d94197581b15..6ea048918804a 100644 --- a/aio/content/guide/quickstart.md +++ b/aio/content/guide/quickstart.md @@ -126,7 +126,7 @@ This is the _root component_ and it is named `app-root`. You can find it in `./src/app/app.component.ts`. -Open the component file and change the `title` property from _Welcome to app!!_ to _Welcome to My First Angular App!!_: +Open the component file and change the `title` property from `'app'` to `'My First Angular App!'`. From 5876fb01250614418a0633e6199870bb75a159a1 Mon Sep 17 00:00:00 2001 From: yerkebulan Date: Fri, 2 Feb 2018 16:06:30 +0600 Subject: [PATCH 15/18] docs(aio): update deprecated Http reference to HttpClientModule, remove Http reference because another context is used (#21984) docs(aio): change HttpClientModule reference to HttpClient docs(aio): capitalize Http to HTTP docs(aio): fix typo mistake in 'universal' guide docs(aio): gets rid of the parentheses and the "e.g." in 'universal' guide PR Close #21984 --- aio/content/guide/universal.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aio/content/guide/universal.md b/aio/content/guide/universal.md index 3fecd8c9a8802..746299e07ceb2 100644 --- a/aio/content/guide/universal.md +++ b/aio/content/guide/universal.md @@ -210,10 +210,10 @@ You can get runtime information about the current platform and the `appId` by in #### Absolute HTTP URLs -The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `Http` module to fetch application data. +The tutorial's `HeroService` and `HeroSearchService` delegate to the Angular `HttpClient` module to fetch application data. These services send requests to _relative_ URLs such as `api/heroes`. -In a Universal app, `Http` URLs must be _absolute_ (e.g., `https://my-server.com/api/heroes`) +In a Universal app, HTTP URLs must be _absolute_, for example, `https://my-server.com/api/heroes` even when the Universal web server is capable of handling those requests. You'll have to change the services to make requests with absolute URLs when running on the server @@ -416,7 +416,7 @@ Create a `tsconfig.server.json` file in the project root directory to configure This config extends from the root's `tsconfig.json` file. Certain settings are noteworthy for their differences. -* The `module` property must be **commonjs** which can be require()'d into our server application. +* The `module` property must be **commonjs** which can be required into our server application. * The `angularCompilerOptions` section guides the AOT compiler: * `entryModule` - the root module of the server application, expressed as `path/to/file#ClassName`. From 4aeb04dcb071b5bfb7b022be9a3814da3a4ce3bd Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Tue, 6 Mar 2018 15:26:05 -0800 Subject: [PATCH 16/18] docs: update RELEASE_SCHEDULE.md by pushing out v6 rc by one week We are pushing RC and Final out by one week because of RxJS v6 complications that are blocking the release. No further delays are currently expected. --- docs/RELEASE_SCHEDULE.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/docs/RELEASE_SCHEDULE.md b/docs/RELEASE_SCHEDULE.md index d873bbc041e0a..4c988528d40e0 100644 --- a/docs/RELEASE_SCHEDULE.md +++ b/docs/RELEASE_SCHEDULE.md @@ -40,13 +40,14 @@ Week Of | Stable Release
(@latest npm tag) | Beta/RC Release
(@n 2018-02-14   | 5.2.5                               | 6.0.0‑beta.4                       | 2018-02-21   | 5.2.6                               | 6.0.0‑beta.5                       | 2018-02-28   | 5.2.7                               | 6.0.0‑beta.6                       | -2018-03-07   | 5.2.8                               | 6.0.0‑rc.0                         | -2018-03-14   | 5.2.9                               | 6.0.0‑rc.1                         | -2018-03-21   | 5.2.10                              | 6.0.0‑rc.2                         | -2018-03-28   | 6.0.0                               | -                                  | Major Release -2018-04-04   | 6.0.1                               | -                                  | -2018-04-11   | 6.0.2                               | -                                  | -2018-04-18   | -                                   | -                                  | [ng-conf](https://www.ng-conf.org/) +2018-03-07   | 5.2.8                               | 6.0.0‑beta.7                       | +2018-03-14   | 5.2.9                               | 6.0.0‑rc.0                         | +2018-03-21   | 5.2.10                              | 6.0.0‑rc.1                         | +2018-03-28   | 5.2.11                              | 6.0.0‑rc.2                         | +2018-04-04   | 6.0.0                               | -                                  | Major Release +2018-04-11   | 6.0.1                               | -                                  | +2018-04-18   | 6.0.2                               | -                                  | [ng-conf](https://www.ng-conf.org/) + ## Tentative Schedule After April 2018 From bdee824292ee9640d3dbcdcf3911af0715f9d27d Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 7 Mar 2018 14:44:18 -0800 Subject: [PATCH 17/18] release: cut the 5.2.8 release --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3d5d5aea040aa..50881c68b8ecd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-srcs", - "version": "5.2.7", + "version": "5.2.8", "private": true, "branchPattern": "2.0.*", "description": "Angular - a web framework for modern web apps", From 2a236b40666c1714cee35efc42bb059761a24a40 Mon Sep 17 00:00:00 2001 From: Alex Eagle Date: Wed, 7 Mar 2018 14:45:07 -0800 Subject: [PATCH 18/18] docs: add changelog for 5.2.8 --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f97026713f91..f5b660bd53e60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ + +## [5.2.8](https://github.com/angular/angular/compare/5.2.7...5.2.8) (2018-03-07) + + +### Bug Fixes + +* **platform-server:** generate correct stylings for camel case names ([#22263](https://github.com/angular/angular/issues/22263)) ([de02a7a](https://github.com/angular/angular/commit/de02a7a)), closes [#19235](https://github.com/angular/angular/issues/19235) +* **router:** don't mutate route configs ([#22358](https://github.com/angular/angular/issues/22358)) ([8f0a064](https://github.com/angular/angular/commit/8f0a064)), closes [#22203](https://github.com/angular/angular/issues/22203) +* **router:** fix URL serialization so special characters are only encoded where needed ([#22337](https://github.com/angular/angular/issues/22337)) ([789a47e](https://github.com/angular/angular/commit/789a47e)), closes [#10280](https://github.com/angular/angular/issues/10280) +* **upgrade:** correctly destroy nested downgraded component ([#22400](https://github.com/angular/angular/issues/22400)) ([4aef9de](https://github.com/angular/angular/commit/4aef9de)), closes [#22392](https://github.com/angular/angular/issues/22392) +* **upgrade:** correctly handle `=` bindings in `[@angular](https://github.com/angular)/upgrade` ([#22167](https://github.com/angular/angular/issues/22167)) ([6638390](https://github.com/angular/angular/commit/6638390)) +* **upgrade:** fix empty transclusion content with AngularJS@>=1.5.8 ([#22167](https://github.com/angular/angular/issues/22167)) ([a9a0e27](https://github.com/angular/angular/commit/a9a0e27)), closes [#22175](https://github.com/angular/angular/issues/22175) + + + ## [5.2.7](https://github.com/angular/angular/compare/5.2.6...5.2.7) (2018-02-28)