From e620827fa89aec7d7aba038d8dcaeb85ed4ae58f Mon Sep 17 00:00:00 2001 From: Michael Prentice Date: Wed, 22 Jul 2020 15:54:19 -0400 Subject: [PATCH 001/253] =?UTF-8?q?docs:=20traducir=20p=C3=A1gina=20de=20i?= =?UTF-8?q?nicio,=20navegaci=C3=B3n,=20cuadro=20de=20b=C3=BAsqueda=20y=20p?= =?UTF-8?q?ie=20de=20p=C3=A1gina?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aio/content/marketing/index.html | 28 +++--- aio/content/navigation.json | 88 ++++++++++++------- aio/src/app/app.component.html | 4 +- .../app/layout/footer/footer.component.html | 8 +- .../search/search-box/search-box.component.ts | 4 +- aio/src/index.html | 10 +-- 6 files changed, 82 insertions(+), 60 deletions(-) diff --git a/aio/content/marketing/index.html b/aio/content/marketing/index.html index f6a68b4dab6a..1fb2e919a092 100755 --- a/aio/content/marketing/index.html +++ b/aio/content/marketing/index.html @@ -14,8 +14,8 @@
-
One framework.
Mobile & desktop.
- Get Started +
Un framework.
Móvil y escritorio.
+ Empezar
@@ -41,8 +41,8 @@

-
Develop Across All Platforms
-

Learn one way to build applications with Angular and reuse your code and abilities to build apps for any deployment target. For web, mobile web, native mobile and native desktop. +

Desarrollar en todas las plataformas
+

Aprenda una forma de crear aplicaciones con Angular y reutilice su código y habilidades para crear aplicaciones para cualquier objetivo de implementación. Para web, web móvil, móvil nativo y escritorio nativo.

@@ -53,9 +53,9 @@

-
Speed & Performance
-

Achieve the maximum speed possible on the Web Platform today, and take it further, via Web Workers and server-side rendering.

-

Angular puts you in control over scalability. Meet huge data requirements by building data models on RxJS, Immutable.js or another push-model.

+
Velocidad y Rendimiento
+

Logre la máxima velocidad posible en la Plataforma Web hoy y avance, a través de Web Workers y renderizado del lado del servidor.

+

Angular te permite controlar la escalabilidad. Satisface requerimientos enormes de datos construyendo modelos en RxJS, Immutable.js o algún otro.

@@ -75,8 +75,8 @@

-
Incredible Tooling
-

Build features quickly with simple, declarative templates. Extend the template language with your own components and use a wide array of existing components. Get immediate Angular-specific help and feedback with nearly every IDE and editor. All this comes together so you can focus on building amazing apps rather than trying to make the code work. +

Herramientas Increíbles
+

Cree funciones rápidamente con plantillas simples y declarativas. Extienda el lenguaje de plantilla con sus propios componentes y use una amplia gama de componentes existentes. Obtenga ayuda inmediata y comentarios específicos de Angular con casi todos los IDE y editores. Todo esto se une para que pueda concentrarse en crear aplicaciones increíbles en lugar de intentar que el código funcione.

@@ -88,8 +88,9 @@

-
Loved by Millions
-

From prototype through global deployment, Angular delivers the productivity and scalable infrastructure that supports Google's largest applications.

+
Amada por millones
+

Desde el prototipo hasta la implementación global, Angular ofrece la productividad y la infraestructura escalable que soportan a las aplicaciones más grandes de Google. +

@@ -106,8 +107,9 @@

Get Started with Angular
-
Try it now
-

Explore Angular's capabilities with a ready-made sample app. No setup required.

+
Pruebalo ahora
+

Explore las capacidades de Angular con una aplicación de muestra preparada. No se requiere configuración. +

diff --git a/aio/content/navigation.json b/aio/content/navigation.json index f6d9b8a52523..667f7bfc837a 100644 --- a/aio/content/navigation.json +++ b/aio/content/navigation.json @@ -2,7 +2,7 @@ "TopBar": [ { "url": "features", - "title": "Features" + "title": "Caracteristicas" }, { "url": "docs", @@ -10,11 +10,11 @@ }, { "url": "resources", - "title": "Resources" + "title": "Recursos" }, { "url": "events", - "title": "Events" + "title": "Eventos" }, { "url": "https://blog.angular.io/", @@ -23,19 +23,19 @@ ], "TopBarNarrow": [ { - "title": "About Angular", + "title": "Acerca de Angular", "children": [ { "url": "features", - "title": "Features" + "title": "Caracteristicas" }, { "url": "resources", - "title": "Resources" + "title": "Recursos" }, { "url": "events", - "title": "Events" + "title": "Eventos" }, { "url": "https://blog.angular.io/", @@ -955,80 +955,100 @@ ], "Footer": [ { - "title": "Resources", + "title": "Recursos", "children": [ { "url": "about", - "title": "About", - "tooltip": "Angular contributors." + "title": "Contribuyentes", + "tooltip": "Contribuyentes de Angular." }, { "url": "resources", - "title": "Resource Listing", - "tooltip": "Angular tools, training, and blogs from around the web." + "title": "Listado de recursos", + "tooltip": "Herramientas de Angular, capacitación y blogs de toda la web." }, { "url": "presskit", - "title": "Press Kit", - "tooltip": "Press contacts, logos, and branding." + "title": "Kit de prensa", + "tooltip": "Contactos de prensa, logotipos y marcas." }, { "url": "https://blog.angular.io/", "title": "Blog", - "tooltip": "Angular Blog" + "tooltip": "Blog de Angular" }, { "url": "analytics", - "title": "Usage Analytics", - "tooltip": "Angular Usage Analytics" + "title": "Analítica de uso", + "tooltip": "Analítica de uso Angular" } ] }, { - "title": "Help", + "title": "Consigue ayuda", "children": [ + { + "url": "https://chat.angular.lat/", + "title": "Angular Hispano Chat", + "tooltip": "Chatea en castellano sobre Angular con otros miembros de la comunidad." + }, + { + "url": "https://angular.lat/coc", + "title": "Código de Conducta", + "tooltip": "Tratarnos con respeto y proporcionar un lugar seguro para contribuir." + }, { "url": "https://stackoverflow.com/questions/tagged/angular", "title": "Stack Overflow", - "tooltip": "Stack Overflow: where the community answers your technical Angular questions." + "tooltip": "Stack Overflow: donde la comunidad responde sus preguntas técnicas de Angular." }, { "url": "https://gitter.im/angular/angular", "title": "Gitter", - "tooltip": "Chat about Angular with other birds of a feather." + "tooltip": "Chatea en inglés sobre Angular con otros miembros de la comunidad." }, { "url": "https://github.com/angular/angular/issues", - "title": "Report Issues", - "tooltip": "Post issues and suggestions on github." + "title": "Informar Issues", + "tooltip": "Publica problemas y sugerencias en GitHub." }, { - "url": "https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md", - "title": "Code of Conduct", - "tooltip": "Treating each other with respect." + "url": "https://github.com/angular-hispano/angular/issues", + "title": "Issues de traducción", + "tooltip": "Publica issues y sugerencias de traducción en GitHub." } ] }, { - "title": "Community", + "title": "Comunidad", "children": [ { - "url": "events", - "title": "Events", - "tooltip": "Angular events around the world." + "url": "https://angular.lat/conferencias", + "title": "Eventos Hispanos", + "tooltip": "Eventos en castellano de Angular alrededor del mundo." + }, + { + "url": "https://angular.lat/meetups", + "title": "Meetups Hispanos", + "tooltip": "Asista a una reunión y aprenda de otros desarrolladores." }, { "url": "http://www.meetup.com/topics/angularjs/", - "title": "Meetups", - "tooltip": "Attend a meetup and learn from fellow developers." + "title": "Mas Meetups", + "tooltip": "Asista a una reunión y aprenda de otros desarrolladores." + }, + { + "url": "events", + "title": "Mas Eventos", + "tooltip": "Eventos de Angular alrededor del mundo." }, { - "url": "https://twitter.com/angular", + "url": "https://twitter.com/AngularHispana", "title": "Twitter", "tooltip": "Twitter" }, { - "url": "https://github.com/angular/angular", + "url": "https://github.com/angular-hispano", "title": "GitHub", "tooltip": "GitHub" }, @@ -1040,7 +1060,7 @@ ] }, { - "title": "Languages", + "title": "Idiomas", "children": [ { "title": "简体中文版", diff --git a/aio/src/app/app.component.html b/aio/src/app/app.component.html index 96b5e6df2953..855025e82b49 100644 --- a/aio/src/app/app.component.html +++ b/aio/src/app/app.component.html @@ -25,10 +25,10 @@ diff --git a/aio/src/app/layout/footer/footer.component.html b/aio/src/app/layout/footer/footer.component.html index 9ca6c62b6aae..b0ceadc56bf1 100644 --- a/aio/src/app/layout/footer/footer.component.html +++ b/aio/src/app/layout/footer/footer.component.html @@ -10,11 +10,11 @@

{{node.title}}

- Super-powered by Google ©2010-2020. - Code licensed under an MIT-style License. - Documentation licensed under + Superalimentado por Google LLC ©2020. + Código licenciado bajo un Licencia de estilo MIT. + Documentación bajo licencia CC BY 4.0.

- Version {{versionInfo?.full}}. + Versión {{versionInfo?.full}}.

diff --git a/aio/src/app/search/search-box/search-box.component.ts b/aio/src/app/search/search-box/search-box.component.ts index 10b90866a2c5..737b3ac1fba3 100644 --- a/aio/src/app/search/search-box/search-box.component.ts +++ b/aio/src/app/search/search-box/search-box.component.ts @@ -17,8 +17,8 @@ import { debounceTime, distinctUntilChanged } from 'rxjs/operators'; selector: 'aio-search-box', template: ` - + Angular - + @@ -101,11 +101,11 @@ Angular
-
One framework.
Mobile & desktop.
+
Un framework.
Móvil y escritorio.

- This website requires JavaScript. + Este sitio web requiere JavaScript.

From 95681b16bd04f10908b7a81384c481aa4e6d9d6b Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 26 Jul 2020 15:10:52 -0600 Subject: [PATCH 002/253] fix(docs): changed the way to express the idea Changed the way to express the idea from "usted" to "tu" --- aio/content/marketing/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/aio/content/marketing/index.html b/aio/content/marketing/index.html index 1fb2e919a092..1c6419e7598d 100755 --- a/aio/content/marketing/index.html +++ b/aio/content/marketing/index.html @@ -41,8 +41,8 @@

-
Desarrollar en todas las plataformas
-

Aprenda una forma de crear aplicaciones con Angular y reutilice su código y habilidades para crear aplicaciones para cualquier objetivo de implementación. Para web, web móvil, móvil nativo y escritorio nativo. +

Desarrolla en todas las plataformas
+

Aprende una forma de crear aplicaciones con Angular y reutiliza tu código y habilidades para crear aplicaciones para cualquier objetivo de implementación. Para web, web móvil, móvil nativo y escritorio nativo.

@@ -54,7 +54,7 @@

Velocidad y Rendimiento
-

Logre la máxima velocidad posible en la Plataforma Web hoy y avance, a través de Web Workers y renderizado del lado del servidor.

+

Logra la máxima velocidad posible en la Plataforma Web hoy y avance, a través de Web Workers y renderizado del lado del servidor.

Angular te permite controlar la escalabilidad. Satisface requerimientos enormes de datos construyendo modelos en RxJS, Immutable.js o algún otro.

@@ -76,7 +76,7 @@

Herramientas Increíbles
-

Cree funciones rápidamente con plantillas simples y declarativas. Extienda el lenguaje de plantilla con sus propios componentes y use una amplia gama de componentes existentes. Obtenga ayuda inmediata y comentarios específicos de Angular con casi todos los IDE y editores. Todo esto se une para que pueda concentrarse en crear aplicaciones increíbles en lugar de intentar que el código funcione. +

Crea funciones rápidamente con plantillas simples y declarativas. Extiende el lenguaje de plantilla con tus propios componentes y usa una amplia gama de componentes existentes. Obtén ayuda inmediata y comentarios específicos de Angular con casi todos los IDE y editores. Todo esto se une para que puedas concentrarte en crear aplicaciones increíbles en lugar de intentar que el código funcione.

@@ -108,7 +108,7 @@

Get Started with Angular
Pruebalo ahora
-

Explore las capacidades de Angular con una aplicación de muestra preparada. No se requiere configuración. +

Explora las capacidades de Angular con una aplicación de muestra preparada. No se requiere configuración.

From cf2663b034abc41ea66cfa3c99a180b9b6de9e7d Mon Sep 17 00:00:00 2001 From: Alejandro Lora Date: Mon, 27 Jul 2020 22:21:00 +0200 Subject: [PATCH 003/253] docs: translate the app-shell.md file (#41) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: translate the app-shell.md file * Update aio/content/guide/app-shell.md Co-authored-by: Christian Morante * Update aio/content/guide/app-shell.md Co-authored-by: Christian Morante * Update aio/content/guide/app-shell.md Co-authored-by: Christian Morante * add PR feedback * docs: update 'usted'-'tú' (Grammatical person) Co-authored-by: Christian Morante --- aio/content/guide/app-shell.md | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/aio/content/guide/app-shell.md b/aio/content/guide/app-shell.md index 88049808733a..b1c9bcf8f4ec 100644 --- a/aio/content/guide/app-shell.md +++ b/aio/content/guide/app-shell.md @@ -1,32 +1,32 @@ # App shell -App shell is a way to render a portion of your application via a route at build time. -It can improve the user experience by quickly launching a static rendered page (a skeleton common to all pages) while the browser downloads the full client version and switches to it automatically after the code loads. +App shell es una manera de renderizar una porción de tu aplicación a través de una ruta en tiempo de compilación (build time). +Puede mejorar la experiencia de usuario lanzando rápidamente una página estática renderizada (un esqueleto común a todas las páginas) mientras el navegador descarga la versión completa del cliente y la muestra automáticamente al finalizar su carga. -This gives users a meaningful first paint of your application that appears quickly because the browser can simply render the HTML and CSS without the need to initialize any JavaScript. +Esto da a los usuarios una primera visualización significativa de su aplicación que aparece rápidamente porque el navegador simplemente puede renderizar HTML y CSS sin la necesidad de inicializar JavaScript. -Learn more in [The App Shell Model](https://developers.google.com/web/fundamentals/architecture/app-shell). +Obténga más información en [El modelo de aplicación Shell](https://developers.google.com/web/fundamentals/architecture/app-shell). -## Step 1: Prepare the application +## Paso 1: Prepara la aplicación -You can do this with the following CLI command: +Puedes hacer esto con el siguiente comando CLI: ng new my-app --routing -For an existing application, you have to manually add the `RouterModule` and defining a `` within your application. +Para una aplicación existente, debes agregar manualmente el `RouterModule` y definir un` `dentro de tu aplicación. -## Step 2: Create the app shell +## Paso 2: Crea el shell de la aplicación -Use the CLI to automatically create the app shell. +Usa la CLI para crear automáticamente el shell de la aplicación. ng generate app-shell -* `client-project` takes the name of your client application. +* `client-project` toma el nombre de tu aplicación cliente. -After running this command you will notice that the `angular.json` configuration file has been updated to add two new targets, with a few other changes. +Después de ejecutar este comando, notará que el archivo de configuración `angular.json` se ha actualizado para agregar dos nuevos targets, con algunos otros cambios. "server": { @@ -53,20 +53,18 @@ After running this command you will notice that the `angular.json` configuration } -## Step 3: Verify the app is built with the shell content +## Paso 3: Verifica que la aplicación está construida con el contenido del shell -Use the CLI to build the `app-shell` target. +Usa la CLI para construir el `app-shell` target. ng run my-app:app-shell -Or to use the production configuration. +O usa la configuración de producción. ng run my-app:app-shell:production -To verify the build output, open `dist/my-app/index.html`. Look for default text `app-shell works!` to show that the app shell route was rendered as part of the output. - - +Para verificar el resultado de la compilación, abre `dist/my-app/index.html`. Busca el texto por defecto `app-shell works!` para mostrar que la ruta del shell de la aplicación se ha renderizado como parte de la carpeta de distribución. From 4cbb90daf712375ebe157c40a8b2d9da6f0d5fd2 Mon Sep 17 00:00:00 2001 From: devpato Date: Thu, 23 Jul 2020 19:21:30 -0400 Subject: [PATCH 004/253] feat(github): traduccion de templates para issues --- .github/ISSUE_TEMPLATE/1-bug-report.md | 61 ++++++++----------- .github/ISSUE_TEMPLATE/2-feature-request.md | 30 ++++----- .github/ISSUE_TEMPLATE/3-docs-bug.md | 52 ++++++++-------- .../4-security-issue-disclosure.md | 6 +- .github/ISSUE_TEMPLATE/5-support-request.md | 10 +-- .github/ISSUE_TEMPLATE/6-angular-cli.md | 6 +- .../ISSUE_TEMPLATE/7-angular-components.md | 8 +-- .github/ISSUE_TEMPLATE/8-translate-docs.md | 53 ++++++++++++++++ 8 files changed, 135 insertions(+), 91 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/8-translate-docs.md diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md index 39b3eb686232..c21d61d05164 100644 --- a/.github/ISSUE_TEMPLATE/1-bug-report.md +++ b/.github/ISSUE_TEMPLATE/1-bug-report.md @@ -1,69 +1,60 @@ --- -name: "\U0001F41EBug report" -about: Report a bug in the Angular Framework +name: "\U0001F41EReporta un bug" +about: Reporta un bug en el framework de Angular --- -# 🐞 bug report +# 🐞 Reporte de un bug -### Affected Package - - The issue is caused by package @angular/.... +### Paquete afectado + + El problema se debe a la @angular del paquete/.... -### Is this a regression? +### ¿Es una regresión? - - Yes, the previous version in which this bug was not present was: .... + + Sí, la versión anterior en la que este error no estaba presente era: .... -### Description +### Descripción - A clear and concise description of the problem... + Una descripción clara y concisa del problema... -## 🔬 Minimal Reproduction - +## 🔬 Reproducción mínima + https://stackblitz.com/... - + -## 🔥 Exception or Error +## 🔥 Excepción o Error

-
+
 
 
 
-## 🌍 Your Environment +## 🌍 Su entorno -**Angular Version:** +**Versión Angular:**

-
+
 
 
 
-**Anything else relevant?** - +**¿Algo más relevante?** + - + diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.md b/.github/ISSUE_TEMPLATE/2-feature-request.md index 2a85f8237581..9efed690e1ea 100644 --- a/.github/ISSUE_TEMPLATE/2-feature-request.md +++ b/.github/ISSUE_TEMPLATE/2-feature-request.md @@ -1,32 +1,32 @@ --- -name: "\U0001F680Feature request" -about: Suggest a feature for Angular Framework +name: "\U0001F680Solicitud de funcionalidad" +about: Solicitud de funcionalidad para el framework de Angular --- -# 🚀 feature request +# 🚀 Solicitud de funcionalidad -### Relevant Package - - This feature request is for @angular/.... +### Paquetes relevantes + + Esta funcionalidad es para @angular/.... -### Description - A clear and concise description of the problem or missing capability... +### Descripción + Una descripción clara y concisa del problema o falta de capacidad... -### Describe the solution you'd like - If you have a solution in mind, please describe it. +### Describe la solución que te gustaría + Si tienes una solución en mente, por favor describela. -### Describe alternatives you've considered - Have you considered any alternative solutions or workarounds? +### Describe las alternativas que ha considerado + ¿Ha considerado alguna solución alternativa? diff --git a/.github/ISSUE_TEMPLATE/3-docs-bug.md b/.github/ISSUE_TEMPLATE/3-docs-bug.md index c7ed324cce15..a08e9981c618 100644 --- a/.github/ISSUE_TEMPLATE/3-docs-bug.md +++ b/.github/ISSUE_TEMPLATE/3-docs-bug.md @@ -1,55 +1,55 @@ --- -name: "📚 Docs or angular.io issue report" -about: Report an issue in Angular's documentation or angular.io application +name: "📚 Informa problemas en los documentos o angular.io" +about: Informar de un problema en la documentación de Angular o angular.io aplicación --- -# 📚 Docs or angular.io bug report +# 📚 Informe de errores de documentos o angular.io -### Description +### Descripción - A clear and concise description of the problem... + Una descripción clara y concisa del problema... -## 🔬 Minimal Reproduction +## 🔬 Reproducción mínima -### What's the affected URL?** - https://angular.io/... +### ¿Cuál es la URL afectada?** + https://angular.io/... ### Reproduction Steps** - - + + -### Expected vs Actual Behavior** - - +### Comportamiento esperado vs real** + + -## 📷Screenshot - - +## 📷Captura de pantall + + -## 🔥 Exception or Error +## 🔥 Excepción o Error

-
+
 
 
 
-## 🌍 Your Environment +## 🌍 Tu entorno -### Browser info - +### Información del navegador + -### Anything else relevant? - +### ¿Es este un problema específico del + diff --git a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md b/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md index 70736318d2a3..de34a8cb40b1 100644 --- a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md +++ b/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md @@ -1,11 +1,11 @@ --- -name: ⚠️ Security issue disclosure -about: Report a security issue in Angular Framework, Material, or CLI +name: ⚠️ Divulgación del problema de seguridad +about: Reporta un problema de seguridad en el framework de Angular, Material, o CLI --- 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 -Please read https://angular.io/guide/security#report-issues on how to disclose security related issues. +Por favor, lee https://angular.io/guide/security#report-issues sobre cómo revelar problemas relacionados con la seguridad. 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/5-support-request.md b/.github/ISSUE_TEMPLATE/5-support-request.md index 2dbeb3061294..684d47cb701a 100644 --- a/.github/ISSUE_TEMPLATE/5-support-request.md +++ b/.github/ISSUE_TEMPLATE/5-support-request.md @@ -1,16 +1,16 @@ --- -name: "❓Support request" -about: Questions and requests for support +name: "❓Solicitud de Soporte" +about: Preguntas e solicitudes de soporte --- 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 -Please do not file questions or support requests on the GitHub issues tracker. +Por favor, no hagas preguntas o solicitudes de soporte técnico en el rastreador de problemas de GitHub. -You can get your questions answered using other communication channels. Please see: +Puede obtener respuestas a sus preguntas utilizando otros canales de comunicación. Por favor, vea: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question -Thank you! +¡Gracias! 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/6-angular-cli.md b/.github/ISSUE_TEMPLATE/6-angular-cli.md index 8bad6e69cd3b..6feee2a92e0d 100644 --- a/.github/ISSUE_TEMPLATE/6-angular-cli.md +++ b/.github/ISSUE_TEMPLATE/6-angular-cli.md @@ -1,13 +1,13 @@ --- name: "\U0001F6E0️Angular CLI" -about: Issues and feature requests for Angular CLI +about: Problemas y solicitudes para el Angular CLI --- 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 -Please file any Angular CLI issues at: https://github.com/angular/angular-cli/issues/new +Por favor, presente cualquier problema de Angular CLI en: https://github.com/angular/angular-cli/issues/new -For the time being, we keep Angular CLI issues in a separate repository. +Por el momento, mantenemos los problemas del Angular CLI en un repositorio 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/7-angular-components.md b/.github/ISSUE_TEMPLATE/7-angular-components.md index 181b418b5501..c2b35744b8f7 100644 --- a/.github/ISSUE_TEMPLATE/7-angular-components.md +++ b/.github/ISSUE_TEMPLATE/7-angular-components.md @@ -1,13 +1,13 @@ --- -name: "\U0001F48EAngular Components" -about: Issues and feature requests for Angular Components +name: "\U0001F48EComponentes de Angular" +about: Problemas y solicitudes de característica para los componentes de Angular --- 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 -Please file any Angular Components issues at: https://github.com/angular/components/issues/new +Por favor, presenta cualquier problema con los componentes de Angulares en: https://github.com/angular/components/issues/new -For the time being, we keep Angular Components issues in a separate repository. +Por el momento, mantenemos los problemas de componentes de Angular en un repositorio independiente. 🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/8-translate-docs.md b/.github/ISSUE_TEMPLATE/8-translate-docs.md new file mode 100644 index 000000000000..1a0c2d14651c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/8-translate-docs.md @@ -0,0 +1,53 @@ +--- +name: "🇪🇦Traducir doc al español" +about: Solicitud para traducir ciertos docs al español + +--- + +🇪🇦 Traducir: creating-libraries.md + + + + +## Nombre del archivo: + creating-libraries.md + + +## Ruta donde se encuentra el archivo dentro del proyecto de Angular + + https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md + +## Tendras que crear un nuevo archivo que es el que contiene la traducción + + + +- [ ] Se han creado dos archivos con la extensión correspondiente + +## ⚠️ Consulta el diccionario de términos + +- [ ] Consulte el diccionario de términos + \ No newline at end of file From 2e42123870d6f053e8506edbac9274b80ed15b75 Mon Sep 17 00:00:00 2001 From: devpato Date: Thu, 23 Jul 2020 19:32:45 -0400 Subject: [PATCH 005/253] fix(merge): conflict --- .github/ISSUE_TEMPLATE/1-bug-report.md | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md index c21d61d05164..b1e2a52f4da8 100644 --- a/.github/ISSUE_TEMPLATE/1-bug-report.md +++ b/.github/ISSUE_TEMPLATE/1-bug-report.md @@ -32,10 +32,17 @@ Los problemas existentes a menudo contienen información sobre soluciones altern ## 🔬 Reproducción mínima - + https://stackblitz.com/... - + ## 🔥 Excepción o Error


From 7fd1733882c0ac15485cd4050e93cc510229f859 Mon Sep 17 00:00:00 2001
From: devpato 
Date: Thu, 23 Jul 2020 21:57:29 -0400
Subject: [PATCH 006/253] fix(pr): comments

---
 .github/ISSUE_TEMPLATE/1-bug-report.md | 9 +++++----
 .github/ISSUE_TEMPLATE/3-docs-bug.md   | 2 +-
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md
index b1e2a52f4da8..7c878ca2b590 100644
--- a/.github/ISSUE_TEMPLATE/1-bug-report.md
+++ b/.github/ISSUE_TEMPLATE/1-bug-report.md
@@ -6,7 +6,7 @@ about: Reporta un bug en el framework de Angular
 
 ¡Hola! 😄
 
-Para agilizar el procesamiento de issues, busque issues abiertas y cerradas antes de enviar uno nuevo.
+Para agilizar el procesamiento de issues, busque issues abiertas y cerradas antes de enviar una nueva.
 Los problemas existentes a menudo contienen información sobre soluciones alternativas, resolución o actualizaciones de progreso.
 
 
@@ -17,7 +17,7 @@ Los problemas existentes a menudo contienen información sobre soluciones altern
 
 ### Paquete afectado
 
- El problema se debe a la @angular del paquete/....
+ El problema es ocasionado por el paquete @angular/...
 
 
 ### ¿Es una regresión?
@@ -37,7 +37,8 @@ Los problemas existentes a menudo contienen información sobre soluciones altern
 
 
 
-
+
diff --git a/.github/ISSUE_TEMPLATE/3-docs-bug.md b/.github/ISSUE_TEMPLATE/3-docs-bug.md
index a08e9981c618..406e216cad6a 100644
--- a/.github/ISSUE_TEMPLATE/3-docs-bug.md
+++ b/.github/ISSUE_TEMPLATE/3-docs-bug.md
@@ -33,7 +33,7 @@ Los problemas existentes a menudo contienen información sobre soluciones altern
 
 
 
-## 📷Captura de pantall
+## 📷Captura de pantalla
 
 
 

From 599d34b41e419302ba331ff5b848bc78d004d0ba Mon Sep 17 00:00:00 2001
From: devpato 
Date: Thu, 23 Jul 2020 21:59:48 -0400
Subject: [PATCH 007/253] fix(comment): based on PR

---
 .github/ISSUE_TEMPLATE/1-bug-report.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/ISSUE_TEMPLATE/1-bug-report.md b/.github/ISSUE_TEMPLATE/1-bug-report.md
index 7c878ca2b590..4eb28a70ad3b 100644
--- a/.github/ISSUE_TEMPLATE/1-bug-report.md
+++ b/.github/ISSUE_TEMPLATE/1-bug-report.md
@@ -38,6 +38,7 @@ Los problemas existentes a menudo contienen información sobre soluciones altern
 
-
-
-# 🐞 Reporte de un bug
-
-### Paquete afectado
-
- El problema es ocasionado por el paquete @angular/...
-
-
-### ¿Es una regresión?
-
-
- Sí, la versión anterior en la que este error no estaba presente era: ....
-
-
-### Descripción
-
- Una descripción clara y concisa del problema...
-
-
-## 🔬 Reproducción mínima
-
- https://stackblitz.com/...
-
-
-
-## 🔥 Excepción o Error
-

-
-
-
-
- - -## 🌍 Su entorno - -**Versión Angular:** -

-
-
-
-
- -**¿Algo más relevante?** - - - diff --git a/.github/ISSUE_TEMPLATE/2-feature-request.md b/.github/ISSUE_TEMPLATE/2-feature-request.md deleted file mode 100644 index 9efed690e1ea..000000000000 --- a/.github/ISSUE_TEMPLATE/2-feature-request.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -name: "\U0001F680Solicitud de funcionalidad" -about: Solicitud de funcionalidad para el framework de Angular - ---- - - - -# 🚀 Solicitud de funcionalidad - -### Paquetes relevantes - - Esta funcionalidad es para @angular/.... - - -### Descripción - Una descripción clara y concisa del problema o falta de capacidad... - - -### Describe la solución que te gustaría - Si tienes una solución en mente, por favor describela. - - -### Describe las alternativas que ha considerado - ¿Ha considerado alguna solución alternativa? diff --git a/.github/ISSUE_TEMPLATE/3-docs-bug.md b/.github/ISSUE_TEMPLATE/3-docs-bug.md deleted file mode 100644 index 406e216cad6a..000000000000 --- a/.github/ISSUE_TEMPLATE/3-docs-bug.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -name: "📚 Informa problemas en los documentos o angular.io" -about: Informar de un problema en la documentación de Angular o angular.io aplicación - ---- - - -# 📚 Informe de errores de documentos o angular.io - -### Descripción - - Una descripción clara y concisa del problema... - - -## 🔬 Reproducción mínima - -### ¿Cuál es la URL afectada?** - https://angular.io/... - -### Reproduction Steps** - - - -### Comportamiento esperado vs real** - - - - -## 📷Captura de pantalla - - - - -## 🔥 Excepción o Error -

-
-
-
-
- - -## 🌍 Tu entorno - -### Información del navegador - - -### ¿Es este un problema específico del - diff --git a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md b/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md deleted file mode 100644 index de34a8cb40b1..000000000000 --- a/.github/ISSUE_TEMPLATE/4-security-issue-disclosure.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -name: ⚠️ Divulgación del problema de seguridad -about: Reporta un problema de seguridad en el framework de Angular, Material, o CLI - ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Por favor, lee https://angular.io/guide/security#report-issues sobre cómo revelar problemas relacionados con la seguridad. - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/5-support-request.md b/.github/ISSUE_TEMPLATE/5-support-request.md deleted file mode 100644 index 684d47cb701a..000000000000 --- a/.github/ISSUE_TEMPLATE/5-support-request.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -name: "❓Solicitud de Soporte" -about: Preguntas e solicitudes de soporte - ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Por favor, no hagas preguntas o solicitudes de soporte técnico en el rastreador de problemas de GitHub. - -Puede obtener respuestas a sus preguntas utilizando otros canales de comunicación. Por favor, vea: -https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question - -¡Gracias! - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/6-angular-cli.md b/.github/ISSUE_TEMPLATE/6-angular-cli.md deleted file mode 100644 index 6feee2a92e0d..000000000000 --- a/.github/ISSUE_TEMPLATE/6-angular-cli.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: "\U0001F6E0️Angular CLI" -about: Problemas y solicitudes para el Angular CLI - ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Por favor, presente cualquier problema de Angular CLI en: https://github.com/angular/angular-cli/issues/new - -Por el momento, mantenemos los problemas del Angular CLI en un repositorio - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/7-angular-components.md b/.github/ISSUE_TEMPLATE/7-angular-components.md deleted file mode 100644 index c2b35744b8f7..000000000000 --- a/.github/ISSUE_TEMPLATE/7-angular-components.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -name: "\U0001F48EComponentes de Angular" -about: Problemas y solicitudes de característica para los componentes de Angular - ---- - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 - -Por favor, presenta cualquier problema con los componentes de Angulares en: https://github.com/angular/components/issues/new - -Por el momento, mantenemos los problemas de componentes de Angular en un repositorio independiente. - -🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑🛑 diff --git a/.github/ISSUE_TEMPLATE/8-translate-docs.md b/.github/ISSUE_TEMPLATE/8-translate-docs.md index 1a0c2d14651c..743deb85687f 100644 --- a/.github/ISSUE_TEMPLATE/8-translate-docs.md +++ b/.github/ISSUE_TEMPLATE/8-translate-docs.md @@ -1,14 +1,14 @@ --- -name: "🇪🇦Traducir doc al español" +name: "📚Traducir doc al español" about: Solicitud para traducir ciertos docs al español --- -🇪🇦 Traducir: creating-libraries.md +📚Traducir: creating-libraries.md From 3325cb2f8642ffbd1c8f3ed62ca99ded9321b0d0 Mon Sep 17 00:00:00 2001 From: devpato Date: Sun, 26 Jul 2020 16:30:50 -0400 Subject: [PATCH 009/253] fix(code): based on comments from PR reviewrs --- .github/ISSUE_TEMPLATE/8-translate-docs.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/8-translate-docs.md b/.github/ISSUE_TEMPLATE/8-translate-docs.md index 743deb85687f..3bebe1d5e4c3 100644 --- a/.github/ISSUE_TEMPLATE/8-translate-docs.md +++ b/.github/ISSUE_TEMPLATE/8-translate-docs.md @@ -50,4 +50,14 @@ Temporalmente tenemos la terminología utilizada en este tema. Se migrará a un La terminologia que estamos usando la podras encontrar aqui: https://github.com/angular-hispano/angular/issues/9 ---> \ No newline at end of file +--> + +## Enlaza la PR con el issue correspondiente + +- [ ] PR enlazada con el issue correspondiente + https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md - -## Tendras que crear un nuevo archivo que es el que contiene la traducción - - - -- [ ] Se han creado dos archivos con la extensión correspondiente - -## ⚠️ Consulta el diccionario de términos - -- [ ] Consulte el diccionario de términos - - -## Enlaza la PR con el issue correspondiente - -- [ ] PR enlazada con el issue correspondiente - https://github.com/angular-hispano/angular/blob/master/aio/content/guide/creating-libraries.md \ No newline at end of file From 04dcc3bcebfde489a021ffc2d383149b90d9a404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Jos=C3=A9=20S=C3=A1nchez?= Date: Thu, 23 Jul 2020 17:04:28 +0200 Subject: [PATCH 011/253] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Traducción del README.md al español. --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 846270ca0429..006f6595c1af 100644 --- a/README.md +++ b/README.md @@ -5,22 +5,22 @@ # Angular -Angular is a development platform for building mobile and desktop web applications using TypeScript/JavaScript and other languages. +Angular es una plataforma de desarrollo para construir aplicaciones web y móviles que usa TypeScript/JavaScript y otros lenguajes de programación. -## Quickstart +## Guía rápida -[Get started in 5 minutes][quickstart]. +[Comienza a usarlo en 5 minutos][quickstart]. -## Changelog +## Registro de cambios (Changelog) -[Learn about the latest improvements][changelog]. +[Últimas mejoras realizadas][changelog]. -## Want to help? +## ¿Quieres ayudar? -Want to file a bug, contribute some code, or improve documentation? Excellent! Read up on our -guidelines for [contributing][contributing] and then check out one of our issues in the [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help). +¿Quieres encontrar fallos, colaborar con código, o mejorar la documentación? ¡Excelente! Lee nuestras +pautas para [colaborar][contributing] y luego revisa algunos de nuestras incidencias (issues) en [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help). -[contributing]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md -[quickstart]: https://angular.io/start -[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md +[colaborar]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md +[guía rápida]: https://angular.io/start +[registro de cambios]: https://github.com/angular/angular/blob/master/CHANGELOG.md [ng]: https://angular.io From 38554288f51c0d77f98e300432185ce9c388a9c4 Mon Sep 17 00:00:00 2001 From: Michael Prentice Date: Tue, 28 Jul 2020 23:21:35 -0400 Subject: [PATCH 012/253] =?UTF-8?q?docs(readme):=20aplicar=20sugerencias?= =?UTF-8?q?=20de=20revisi=C3=B3n=20de=20c=C3=B3digo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 006f6595c1af..81e9fa455d60 100644 --- a/README.md +++ b/README.md @@ -18,9 +18,8 @@ Angular es una plataforma de desarrollo para construir aplicaciones web y móvil ## ¿Quieres ayudar? ¿Quieres encontrar fallos, colaborar con código, o mejorar la documentación? ¡Excelente! Lee nuestras -pautas para [colaborar][contributing] y luego revisa algunos de nuestras incidencias (issues) en [hotlist: community-help](https://github.com/angular/angular/labels/hotlist%3A%20community-help). +pautas para [colaborar][contributing] y luego revisa algunos de nuestras incidencias (issues) en [ayuda comunitaria](https://github.com/angular-hispano/angular/labels/ayuda%20comunitaria). -[colaborar]: https://github.com/angular/angular/blob/master/CONTRIBUTING.md -[guía rápida]: https://angular.io/start -[registro de cambios]: https://github.com/angular/angular/blob/master/CHANGELOG.md -[ng]: https://angular.io +[contributing]: https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md +[quickstart]: https://docs.angular.lat/start +[changelog]: https://github.com/angular/angular/blob/master/CHANGELOG.md From 37668d159e53aeb636ed7ca50d868c837be3aa7f Mon Sep 17 00:00:00 2001 From: Alejandro Date: Sun, 26 Jul 2020 22:51:26 +0200 Subject: [PATCH 013/253] docs: translat cheatsheet.md file to Spanish --- aio/content/guide/cheatsheet.md | 172 ++++++++++++++++---------------- 1 file changed, 87 insertions(+), 85 deletions(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index f3e55928d3e7..87e57d4e5f60 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -10,7 +10,7 @@ platformBrowserDynamic().bootstrapModule(AppModule); -

Bootstraps the app, using the root component from the specified NgModule.

+

Empaqueta la app, usando el componente raíz del NgModule especificado.

@@ -24,370 +24,372 @@ @NgModule({ declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...})
class MyModule {}
-

Defines a module that contains components, directives, pipes, and providers.

+

Define un módulo que contiene componentes, directivas, tuberías y proveedores.

declarations: [MyRedComponent, MyBlueComponent, MyDatePipe] -

List of components, directives, and pipes that belong to this module.

+

Lista de componentes, directivas y tuberías que pertenecen a este módulo.

imports: [BrowserModule, SomeOtherModule] -

List of modules to import into this module. Everything from the imported modules -is available to declarations of this module.

+

Lista de módulos para importar en este módulo. Todo, desde los módulos importados, +está disponible para las declaraciones (declarations) de este módulo. exports: [MyRedComponent, MyDatePipe] -

List of components, directives, and pipes visible to modules that import this module.

+

Lista de componentes, directivas y tuberías visibles a los módulos que importan este módulo.

providers: [MyService, { provide: ... }] -

List of dependency injection providers visible both to the contents of this module and to importers of this module.

+

Lista de proveedores de inyección de dependencias visibles tanto para los contenidos de este módulo como para los importadores de este módulo.

entryComponents: [SomeComponent, OtherComponent] -

List of components not referenced in any reachable template, for example dynamically created from code.

+

Lista de componentes no referenciados en cualquier plantilla accesible, por ejemplo, creada dinámicamente a partir de código.

bootstrap: [MyAppComponent] -

List of components to bootstrap when this module is bootstrapped.

+

Lista de componentes a empaquetar cuando este módulo se inicia.

- + - - - - - - + + - - + - - - - - - -
Template syntaxSintaxis de plantilla
<input [value]="firstName">

Binds property value to the result of expression firstName.

+

Vincula la propiedad value al resultado de la expresión firstName.

<div [attr.role]="myAriaRole">

Binds attribute role to the result of expression myAriaRole.

+

Vincula el atributo role al resultado de la expresión myAriaRole.

<div [class.extra-sparkle]="isDelightful">

Binds the presence of the CSS class extra-sparkle on the element to the truthiness of the expression isDelightful.

+

Vincula la presencia de la clase CSS extra-sparkle sobre el elemento a la veracidad de la expresión isDelightful.

<div [style.width.px]="mySize">

Binds style property width to the result of expression mySize in pixels. Units are optional.

+

Vincula la propiedad de estilo width al resultado de la expresión mySize en píxeles. La unidad de medida es opcional.

<button (click)="readRainbow($event)">

Calls method readRainbow when a click event is triggered on this button element (or its children) and passes in the event object.

+

Llama al método readRainbow cuando se lanza un evento clic en este elemento botón (o sus hijos) y pasa por argumento el objeto evento.

<div title="Hello {{ponyName}}"><div title="Hola {{ponyName}}">

Vincula una propiedad a una cadena interpolada, por ejemplo, "Hola Seabiscuit". Equivalente a:

Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to: -<div [title]="'Hello ' + ponyName">

+<div [title]="'Hola ' + ponyName">

<p>Hello {{ponyName}}</p>

Binds text content to an interpolated string, for example, "Hello Seabiscuit".

+
<p>Hola {{ponyName}}</p>

Vincula el contenido de texto a una cadena interpolada, por ejemplo, "Hola Seabiscuit".

<my-cmp [(title)]="name">

Sets up two-way data binding. Equivalent to: <my-cmp [title]="name" (titleChange)="name=$event">

+

Establece el two-way data binding. Equivalente a: <my-cmp [title]="name" (titleChange)="name=$event">

<video #movieplayer ...>
<button (click)="movieplayer.play()">
</video>

Creates a local variable movieplayer that provides access to the video element instance in data-binding and event-binding expressions in the current template.

+

Crea una variable local movieplayer que provee acceso a la instancia del elemento video en las expresiones de data-binding y event-binding de la actual plantilla.

<p *myUnless="myExpression">...</p>

The * symbol turns the current element into an embedded template. Equivalent to: +

El símbolo * convierte el elemento actual en una plantilla incrustada. Equivalente a: <ng-template [myUnless]="myExpression"><p>...</p></ng-template>

<p>Card No.: {{cardNumber | myCardNumberFormatter}}</p>

Transforms the current value of expression cardNumber via the pipe called myCardNumberFormatter.

+

Transforma el valor actual de la expresión cardNumber a través de la tubería myCardNumberFormatter.

<p>Employer: {{employer?.companyName}}</p>

The safe navigation operator (?) means that the employer field is optional and if undefined, the rest of the expression should be ignored.

+

El operador de navegación seguro (?) significa que el campo employer es opcional y que si es undefined, el resto de la expresión debería ser ignorado.

<svg:rect x="0" y="0" width="100" height="100"/>

An SVG snippet template needs an svg: prefix on its root element to disambiguate the SVG element from an HTML component.

+

Una plantilla de fragmento SVG necesita un prefijo svg: en su elemento raíz para distinguir el elemento SVG de un componente HTML.

<svg>
<rect x="0" y="0" width="100" height="100"/>
</svg>

An <svg> root element is detected as an SVG element automatically, without the prefix.

+

Un elemento raíz <svg> es detectado como un elemento SVG automáticamente, sin el prefijo.

- + - - - - -
Built-in directivesDirectivas incorporadas

import { CommonModule } from '@angular/common';

<section *ngIf="showSection">

Removes or recreates a portion of the DOM tree based on the showSection expression.

+

Elimina o recrea una parte del árbol DOM basado en la expresión showSection.

<li *ngFor="let item of list">

Turns the li element and its contents into a template, and uses that to instantiate a view for each item in list.

+

Convierte el elemento li y su contenido en una plantilla, y lo utiliza para crear una vista por cada elemento de la lista.

<div [ngSwitch]="conditionExpression">
<ng-template [ngSwitchCase]="case1Exp">...</ng-template>
<ng-template ngSwitchCase="case2LiteralString">...</ng-template>
<ng-template ngSwitchDefault>...</ng-template>
</div>

Conditionally swaps the contents of the div by selecting one of the embedded templates based on the current value of conditionExpression.

+

Intercambia condicionalmente el contenido del div seleccionando una de las plantillas incrustadas en función del valor actual de conditionExpression.

<div [ngClass]="{'active': isActive, 'disabled': isDisabled}">

Binds the presence of CSS classes on the element to the truthiness of the associated map values. The right-hand expression should return {class-name: true/false} map.

+

Vincula la presencia de clases CSS en el elemento a la veracidad de los valores de mapa asociados. La expresión de la derecha debería devolver el mapa {class-name: true/false}.

<div [ngStyle]="{'property': 'value'}">
<div [ngStyle]="dynamicStyles()">

Allows you to assign styles to an HTML element using CSS. You can use CSS directly, as in the first example, or you can call a method from the component.

+

Le permite asignar estilos a un elemento HTML usando CSS. Puede usar CSS directamente, como en el primer ejemplo, o puede llamar a un método desde el componente.

- + -
FormsFormularios

import { FormsModule } from '@angular/forms';

<input [(ngModel)]="userName">

Provides two-way data-binding, parsing, and validation for form controls.

+

Provee two-way data-binding, conversión y validación para controles de formulario.

- + - - - -
Class decoratorsDecoradores de clases

import { Directive, ... } from '@angular/core';

@Component({...})
class MyComponent() {}

Declares that a class is a component and provides metadata about the component.

+

Declara que una clase es un componente y proporciona metadatos sobre el componente.

@Directive({...})
class MyDirective() {}

Declares that a class is a directive and provides metadata about the directive.

+

Declara que una clase es una directiva y proporciona metadatos sobre la directiva.

@Pipe({...})
class MyPipe() {}

Declares that a class is a pipe and provides metadata about the pipe.

+

Declara que una clase es una tubería and y proporciona metadatos sobre la tubería.

@Injectable()
class MyService() {}

Declares that a class can be provided and injected by other classes. Without this decorator, the compiler won't generate enough metadata to allow the class to be created properly when it's injected somewhere.

+

Declara que una clase puede ser proporcionada e inyectada por otras clases. Sin este decorador, el compilador no generará suficientes metadatos para permitir que la clase se cree correctamente cuando se inyecta en alguna parte.

- + - -
Directive configurationConfiguración de Directiva

@Directive({ property1: value1, ... })

selector: '.cool-button:not(a)'

Specifies a CSS selector that identifies this directive within a template. Supported selectors include element, +

Especifica un selector CSS que identifica esta directiva dentro de una plantilla. Los selectores compatibles incluyen element, [attribute], .class, and :not().

-

Does not support parent-child relationship selectors.

+

No soporta selectores de relación padre-hijo.

providers: [MyService, { provide: ... }]

List of dependency injection providers for this directive and its children.

+

Lista de proveedores de inyección de dependencia para esta directiva y sus hijos.

- + - - - - + -
Component configurationConfiguración de Componente

-@Component extends @Directive, -so the @Directive configuration applies to components as well

+@Component extiende @Directive, +entonces la configuración de @Directive se aplica también a los componentes

moduleId: module.id

If set, the templateUrl and styleUrl are resolved relative to the component.

+

Si está presente, el templateUrl y styleUrl se resuelven en relación con el componente.

viewProviders: [MyService, { provide: ... }]

List of dependency injection providers scoped to this component's view.

+

Lista de proveedores de inyección de dependencias en la vista de este componente.

template: 'Hello {{name}}'
templateUrl: 'my-component.html'

Inline template or external template URL of the component's view.

+
template: 'Hola {{name}}'
templateUrl: 'my-component.html'

Plantilla en línea o URL de plantilla externa de la vista del componente.

styles: ['.primary {color: red}']
styleUrls: ['my-component.css']

List of inline CSS styles or external stylesheet URLs for styling the component’s view.

+

Lista de estilos CSS en línea o URL de hojas de estilo externas para estilar la vista del componente.

- + - - - - - - - -
Class field decorators for directives and componentsDecoradores para los campos de la clase para directivas y componentes.

import { Input, ... } from '@angular/core';

@Input() myProperty;

Declares an input property that you can update via property binding (example: +

Declara una propiedad de entrada (input) que puede actualizar mediante el enlace de propiedad (property binding) (ejemplo: <my-cmp [myProperty]="someExpression">).

@Output() myEvent = new EventEmitter();

Declares an output property that fires events that you can subscribe to with an event binding (example: <my-cmp (myEvent)="doSomething()">).

+

Declara una propiedad de salida (output) que dispara eventos a los que puede suscribirse con un enlace de evento (event binding) (ejemplo: <my-cmp (myEvent)="doSomething()">).

@HostBinding('class.valid') isValid;

Binds a host element property (here, the CSS class valid) to a directive/component property (isValid).

+

Vincula una propiedad del elemento anfitrión (aquí, la clase CSS valid) a una propiedad de directiva/componente (isValid).

@HostListener('click', ['$event']) onClick(e) {...}

Subscribes to a host element event (click) with a directive/component method (onClick), optionally passing an argument ($event).

+

Se suscribe a un evento del elemento anfitrión (click) con un método de directiva/componente (onClick), opcionalmente, pasando un argumento ($event).

@ContentChild(myPredicate) myChildComponent;

Binds the first result of the component content query (myPredicate) to a property (myChildComponent) of the class.

+

Vincula el primer resultado de la consulta de contenido del componente (myPredicate) a una propiedad (myChildComponent) de la clase.

@ContentChildren(myPredicate) myChildComponents;

Binds the results of the component content query (myPredicate) to a property (myChildComponents) of the class.

+

Vincula los resultados de la consulta de contenido del componente (myPredicate) a una propiedad (myChildComponents) de la clase.

@ViewChild(myPredicate) myChildComponent;

Binds the first result of the component view query (myPredicate) to a property (myChildComponent) of the class. Not available for directives.

+

Vincula el primer resultado de la consulta de vista del componente (myPredicate) a una propiedad (myChildComponent) de la clase. No disponible para directivas.

@ViewChildren(myPredicate) myChildComponents;

Binds the results of the component view query (myPredicate) to a property (myChildComponents) of the class. Not available for directives.

+

Vincula los resultados de la consulta de vista del componente (myPredicate) a una propiedad (myChildComponents) de la clase. No disponible para directivas.

- - + - - - - - - - - -
Directive and component change detection and lifecycle hooks

(implemented as class methods) + +

Detección de cambios (change detection) y ciclos de vida (lifecycle hooks) en directivas y componentes

(implementado como métodos de clase)

constructor(myService: MyService, ...) { ... }

Called before any other lifecycle hook. Use it to inject dependencies, but avoid any serious work here.

+

Se llama antes que cualquier ciclo de vida. Úselo para inyectar dependencias, pero evite cualquier trabajo serio aquí.

ngOnChanges(changeRecord) { ... }

Called after every change to input properties and before processing content or child views.

+

Se llama después de cada cambio en las propiedades de entrada (input) y antes de procesar contenido o vistas de hijos.

ngOnInit() { ... }

Called after the constructor, initializing input properties, and the first call to ngOnChanges.

+

Se llama después del constructor, inicializando propiedades de entrada (input), y la primera llamada a ngOnChanges.

ngDoCheck() { ... }

Called every time that the input properties of a component or a directive are checked. Use it to extend change detection by performing a custom check.

+

Se llama cada vez que se verifican las propiedades de entrada (input) de un componente o una directiva. Úselo para extender la detección de cambios (change detection) realizando una verificación personalizada.

ngAfterContentInit() { ... }

Called after ngOnInit when the component's or directive's content has been initialized.

+

Se llama después de ngOnInit cuando el contenido del componente o directiva ha sido inicializado.

ngAfterContentChecked() { ... }

Called after every check of the component's or directive's content.

+

Se llama después de cada verificación del contenido del componente o directiva.

ngAfterViewInit() { ... }

Called after ngAfterContentInit when the component's views and child views / the view that a directive is in has been initialized.

+

Se llama después de ngAfterContentInit cuando las vistas del componente y las vistas hijas / la vista en la que se encuentra una directiva ha sido inicializado.

ngAfterViewChecked() { ... }

Called after every check of the component's views and child views / the view that a directive is in.

+

Se llama después de cada verificación de las vistas del componentes y las vistas hijas / la vista en la que se encuentra una directiva.

ngOnDestroy() { ... }

Called once, before the instance is destroyed.

+

Se llama una vez, antes de que la instancia se destruya.

- + - - -
Dependency injection configurationConfiguración de inyección de dependencia
{ provide: MyService, useClass: MyMockService }

Sets or overrides the provider for MyService to the MyMockService class.

+

Establece o sobre-escribe el proveedor para MyService en la clase MyMockService.

{ provide: MyService, useFactory: myFactory }

Sets or overrides the provider for MyService to the myFactory factory function.

+

Establece o sobre-escribe el proveedor para MyService en la factoría de función myFactory.

{ provide: MyValue, useValue: 41 }

Sets or overrides the provider for MyValue to the value 41.

+

Establece o sobre-escribe el proveedor para MyValue al valor 41.

- + - - - - - - - - -
Routing and navigationEnrutamiento y navegación

import { Routes, RouterModule, ... } from '@angular/router';

const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'path/:routeParam', component: MyComponent },
{ path: 'staticPath', component: ... },
{ path: '**', component: ... },
{ path: 'oldPath', redirectTo: '/staticPath' },
{ path: ..., component: ..., data: { message: 'Custom' } }
]);

const routing = RouterModule.forRoot(routes);

Configures routes for the application. Supports static, parameterized, redirect, and wildcard routes. Also supports custom route data and resolve.

+

Configura rutas para la aplicación. Soporta rutas estáticas, parametrizadas, de redireccionamiento y comodines. También soporta datos de ruta personalizados y los resuelve.


<router-outlet></router-outlet>
<router-outlet name="aux"></router-outlet>

Marks the location to load the component of the active route.

+

Marca la ubicación para cargar el componente de la ruta activa.


<a routerLink="/path">
<a [routerLink]="[ '/path', routeParam ]">
<a [routerLink]="[ '/path', { matrixParam: 'value' } ]">
<a [routerLink]="[ '/path' ]" [queryParams]="{ page: 1 }">
<a [routerLink]="[ '/path' ]" fragment="anchor">

Creates a link to a different view based on a route instruction consisting of a route path, required and optional parameters, query parameters, and a fragment. To navigate to a root route, use the / prefix; for a child route, use the ./prefix; for a sibling or parent, use the ../ prefix.

+

Crea un enlace a una vista diferente basada en una instrucción de ruta que consta de un camino de de ruta, parámetros obligatorios y opcionales, parámetros de consulta y un fragmento. Para navegar a un camino de ruta, usa el prefijo /; para una ruta hija, usa el prefijo ./; para un padre o hermano, usa el prefijo ../.

<a [routerLink]="[ '/path' ]" routerLinkActive="active">

The provided classes are added to the element when the routerLink becomes the current active route.

+

Las clases proporcionadas se agregan al elemento cuando el routerLink se convierte en la ruta activa actual.

class CanActivateGuard implements CanActivate {
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
}

{ path: ..., canActivate: [CanActivateGuard] }

An interface for defining a class that the router should call first to determine if it should activate this component. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.

+

Una interfaz para definir una clase que el enrutador debe llamar primero para determinar si debe activar este componente. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelba en un boolean|UrlTree.

class CanDeactivateGuard implements CanDeactivate<T> {
canDeactivate(
component: T,
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
}

{ path: ..., canDeactivate: [CanDeactivateGuard] }

An interface for defining a class that the router should call first to determine if it should deactivate this component after a navigation. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.

+

Una interfaz para definir una clase que el enrutador debería llamar primero para determinar si debería desactivar este componente después de una navegación. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva a boolean|UrlTree.

class CanActivateChildGuard implements CanActivateChild {
canActivateChild(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
}

{ path: ..., canActivateChild: [CanActivateGuard],
children: ... }

An interface for defining a class that the router should call first to determine if it should activate the child route. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.

+

Una interfaz para definir una clase que el enrutador debe llamar primero para determinar si debe activar la ruta hija. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva en un boolean|UrlTree.

class ResolveGuard implements Resolve<T> {
resolve(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<any>|Promise<any>|any { ... }
}

{ path: ..., resolve: [ResolveGuard] }

An interface for defining a class that the router should call first to resolve route data before rendering the route. Should return a value or an Observable/Promise that resolves to a value.

+

Una interfaz para definir una clase que el enrutador debe llamar primero para resolver los datos de la ruta antes de representar la ruta. Debe devolver un valor o un Observable/Promise que se resuelva en un valor.

class CanLoadGuard implements CanLoad {
canLoad(
route: Route
): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolean|UrlTree { ... }
}

{ path: ..., canLoad: [CanLoadGuard], loadChildren: ... }

An interface for defining a class that the router should call first to check if the lazy loaded module should be loaded. Should return a boolean|UrlTree or an Observable/Promise that resolves to a boolean|UrlTree.

+

Una interfaz para definir una clase a la que el enrutador debe llamar primero para verificar si el módulo perezoso cargado (lazy loaded module) debe cargarse. Debe devolver un boolean|UrlTree o un Observable/Promise que se resuelva en un boolean|UrlTree.

From f67774d84b9f406f055e6d46cdaa17995f497c40 Mon Sep 17 00:00:00 2001 From: Alejandro Lora Date: Mon, 27 Jul 2020 10:35:27 +0200 Subject: [PATCH 014/253] Update aio/content/guide/cheatsheet.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> --- aio/content/guide/cheatsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index 87e57d4e5f60..82c44673c011 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -146,7 +146,7 @@ está disponible para las declaraciones (declarations) de este mód <div [ngStyle]="{'property': 'value'}">
<div [ngStyle]="dynamicStyles()"> -

Le permite asignar estilos a un elemento HTML usando CSS. Puede usar CSS directamente, como en el primer ejemplo, o puede llamar a un método desde el componente.

+

Te permite asignar estilos a un elemento HTML usando CSS. Puedes usar CSS directamente, como en el primer ejemplo, o puedes llamar a un método desde el componente.

From 0d1491b1a66c2aa5517a11466938531e4e503c86 Mon Sep 17 00:00:00 2001 From: Alejandro Date: Mon, 27 Jul 2020 10:36:24 +0200 Subject: [PATCH 015/253] docs: implement feedback PR --- aio/content/guide/cheatsheet.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index 82c44673c011..cd63ded658c2 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -24,11 +24,11 @@ @NgModule({ declarations: ..., imports: ...,
exports: ..., providers: ..., bootstrap: ...})
class MyModule {}
-

Define un módulo que contiene componentes, directivas, tuberías y proveedores.

+

Define un módulo que contiene componentes, directivas, pipes y proveedores.

declarations: [MyRedComponent, MyBlueComponent, MyDatePipe] -

Lista de componentes, directivas y tuberías que pertenecen a este módulo.

+

Lista de componentes, directivas y pipes que pertenecen a este módulo.

imports: [BrowserModule, SomeOtherModule] @@ -37,7 +37,7 @@ está disponible para las declaraciones (declarations) de este mód exports: [MyRedComponent, MyDatePipe] -

Lista de componentes, directivas y tuberías visibles a los módulos que importan este módulo.

+

Lista de componentes, directivas y pipes visibles a los módulos que importan este módulo.

providers: [MyService, { provide: ... }] @@ -76,7 +76,7 @@ está disponible para las declaraciones (declarations) de este mód <button (click)="readRainbow($event)"> -

Llama al método readRainbow cuando se lanza un evento clic en este elemento botón (o sus hijos) y pasa por argumento el objeto evento.

+

Llama al método readRainbow cuando se lanza un evento click en este elemento botón (o sus hijos) y pasa por argumento el objeto evento.

<div title="Hola {{ponyName}}"> @@ -103,7 +103,7 @@ está disponible para las declaraciones (declarations) de este mód <p>Card No.: {{cardNumber | myCardNumberFormatter}}</p> -

Transforma el valor actual de la expresión cardNumber a través de la tubería myCardNumberFormatter.

+

Transforma el valor actual de la expresión cardNumber a través de la pipe myCardNumberFormatter.

<p>Employer: {{employer?.companyName}}</p> @@ -182,7 +182,7 @@ está disponible para las declaraciones (declarations) de este mód @Pipe({...})
class MyPipe() {}
-

Declara que una clase es una tubería and y proporciona metadatos sobre la tubería.

+

Declara que una clase es una pipe y proporciona metadatos sobre la pipe.

@Injectable()
class MyService() {}
From cd1817bf6d55a8aad5c885e0e547634c70baddc3 Mon Sep 17 00:00:00 2001 From: Alejandro Lora Date: Mon, 27 Jul 2020 10:37:23 +0200 Subject: [PATCH 016/253] Update aio/content/guide/cheatsheet.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> --- aio/content/guide/cheatsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index cd63ded658c2..6ba93b31b348 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -252,7 +252,7 @@ entonces la configuración de @Directive se aplica también a los c @Output() myEvent = new EventEmitter(); -

Declara una propiedad de salida (output) que dispara eventos a los que puede suscribirse con un enlace de evento (event binding) (ejemplo: <my-cmp (myEvent)="doSomething()">).

+

Declara una propiedad de salida (output) que dispara eventos a los que puedes suscribirse con un enlace de evento (event binding) (ejemplo: <my-cmp (myEvent)="doSomething()">).

@HostBinding('class.valid') isValid; From d133525502a4b38eeb91c20a182a695be853be38 Mon Sep 17 00:00:00 2001 From: Alejandro Date: Tue, 28 Jul 2020 23:56:53 +0200 Subject: [PATCH 017/253] docs: update typo for bootstraping word --- aio/content/guide/cheatsheet.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index 6ba93b31b348..58935f2883ee 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -10,7 +10,7 @@ platformBrowserDynamic().bootstrapModule(AppModule); -

Empaqueta la app, usando el componente raíz del NgModule especificado.

+

Carga la app, usando el componente raíz del NgModule especificado.

From 92c7145139fd6e236df20a9bed8b539b60135d59 Mon Sep 17 00:00:00 2001 From: Pato <11162114+devpato@users.noreply.github.com> Date: Thu, 30 Jul 2020 03:57:48 -0400 Subject: [PATCH 018/253] fix(pr): template (#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Alejandro Lora Co-authored-by: Andrés Villanueva Co-authored-by: Michael Prentice --- .github/PULL_REQUEST_TEMPLATE.md | 66 ++++++++++++++------------------ 1 file changed, 29 insertions(+), 37 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index ffec1591b654..4cccd14f4d53 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,43 +1,35 @@ -## PR Checklist -Please check if your PR fulfills the following requirements: +## Lista de Verificación del PR +Comprueba si tu PR cumple los siguientes requisitos: -- [ ] The commit message follows our guidelines: https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit -- [ ] Tests for the changes have been added (for bug fixes / features) -- [ ] Docs have been added / updated (for bug fixes / features) +- [ ] El mensaje de commit conforme con [nuestras reglas](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#commit) +- [ ] Prueba los cambios que agregaste (arreglo de bugs / funcionalidades) +- [ ] Revisa tus traducciones o cambios de contenido +- [ ] Consulté el [diccionario de términos](https://github.com/angular-hispano/angular/issues/9) en español +- [ ] Se han creado dos archivos con la extensión correspondiente(.en.md para el archivo en inglés y .md para el Archivo en español) +- [ ] PR enlazada con el issue correspondiente -## PR Type -What kind of change does this PR introduce? +## Tipo de PR +¿Qué tipo de cambio introduce este PR? - + - [ ] Bugfix -- [ ] Feature -- [ ] Code style update (formatting, local variables) -- [ ] Refactoring (no functional changes, no api changes) -- [ ] Build related changes -- [ ] CI related changes -- [ ] Documentation content changes -- [ ] angular.io application / infrastructure changes -- [ ] Other... Please describe: - - -## What is the current behavior? - - -Issue Number: N/A - - -## What is the new behavior? - - -## Does this PR introduce a breaking change? - -- [ ] Yes -- [ ] No - - - - - -## Other information +- [ ] Funcionalidad +- [ ] Actualizar el estilo del código (formato, variables locales) +- [ ] Refactorización (no cambios en la funcionalidad, no cambios en el api) +- [ ] Cambios relacionados al build +- [ ] Cambios relacionados al CI (Integración continua) +- [ ] Cambios en el contenido de la documentación +- [ ] Cambios en la aplicación / infrastructura de angular.io +- [ ] Otro... Por favor describela: + +## ¿Cuál es el comportamiento actual? + + + +## ¿Cuál es el nuevo comportamiento? + From db394e2b817afa6a05196a1dc676ea1c7424b095 Mon Sep 17 00:00:00 2001 From: Alejandro Date: Mon, 3 Aug 2020 09:47:54 +0200 Subject: [PATCH 019/253] docs: Fix a typo for cheatsheet translation --- aio/content/guide/cheatsheet.md | 1 - 1 file changed, 1 deletion(-) diff --git a/aio/content/guide/cheatsheet.md b/aio/content/guide/cheatsheet.md index 58935f2883ee..d1ee34570ff6 100644 --- a/aio/content/guide/cheatsheet.md +++ b/aio/content/guide/cheatsheet.md @@ -81,7 +81,6 @@ está disponible para las declaraciones (declarations) de este mód <div title="Hola {{ponyName}}">

Vincula una propiedad a una cadena interpolada, por ejemplo, "Hola Seabiscuit". Equivalente a: -

Binds a property to an interpolated string, for example, "Hello Seabiscuit". Equivalent to: <div [title]="'Hola ' + ponyName">

From c4d76a65da2c27358c138bb9c50996bff18b89dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Jos=C3=A9=20S=C3=A1nchez?= Date: Wed, 5 Aug 2020 21:40:54 +0200 Subject: [PATCH 020/253] Traducido: accessibility.md (#50) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Traducido Traducido el apartado "Accesibilidad en Angular". Pendiente de revisión. * Update aio/content/guide/accessibility.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> * Update aio/content/guide/accessibility.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> * Update aio/content/guide/accessibility.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> * Update aio/content/guide/accessibility.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> --- aio/content/guide/accessibility.md | 118 ++++++++++++++--------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/aio/content/guide/accessibility.md b/aio/content/guide/accessibility.md index 042d61cecaf0..d38113f1fb02 100644 --- a/aio/content/guide/accessibility.md +++ b/aio/content/guide/accessibility.md @@ -1,111 +1,112 @@ -# Accessibility in Angular +# Accesibilidad en Angular -The web is used by a wide variety of people, including those who have visual or motor impairments. -A variety of assistive technologies are available that make it much easier for these groups to -interact with web-based software applications. -In addition, designing an application to be more accessible generally improves the user experience for all users. +Hay una amplia variedad de personas que utilizan la web, algunas de ellas con discapacidad visual o motora. +Existen diferentes tecnologías de apoyo que hacen que sea mucho más fácil para estos grupos +interactuar con aplicaciones de software basadas en la web. +Además, diseñar una aplicación para que sea más accesible, normalmente mejora la experiencia de usuario en general. -For an in-depth introduction to issues and techniques for designing accessible applications, see the [Accessibility](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) section of the Google's [Web Fundamentals](https://developers.google.com/web/fundamentals/). +Para una introducción en profundidad a los problemas y técnicas sobre el diseño de aplicaciones accesibles, puede consultar la sección de [Accesibilidad](https://developers.google.com/web/fundamentals/accessibility/#what_is_accessibility) de Google [Fundamentos Web](https://developers.google.com/web/fundamentals/). -This page discusses best practices for designing Angular applications that -work well for all users, including those who rely on assistive technologies. +Esta página habla de las mejores prácticas para diseñar aplicaciones en Angular que funcionan +bien para todos los usuarios, incluyendo aquéllos que necesitan tecnologías de apoyo.
- For the sample app that this page describes, see the . + Para ver la aplicación de ejemplo que describe esta página, ir a .
-## Accessibility attributes +## Atributos de accesibilidad -Building accessible web experience often involves setting [ARIA attributes](https://developers.google.com/web/fundamentals/accessibility/semantics-aria) -to provide semantic meaning where it might otherwise be missing. -Use [attribute binding](guide/attribute-binding) template syntax to control the values of accessibility-related attributes. +Crear una web accesible a menudo implica establecer los [atributos ARIA](https://developers.google.com/web/fundamentals/accessibility/semantics-aria) +para proporcionar la semántica que, de otro modo, podría no estar presente. +Usa la plantilla de sintaxis del [enlace de atributos](attribute binding) (guide/attribute-binding) para controlar los valores de los atributos relacionados con la accesibilidad. -When binding to ARIA attributes in Angular, you must use the `attr.` prefix, as the ARIA -specification depends specifically on HTML attributes rather than properties of DOM elements. +Para enlazar los atributos ARIA en Angular, debes usar el prefijo `attr.`, ya que la especificación ARIA +depende de los atributos HTML y no de las propiedades de los elementos del DOM. ```html ``` -Note that this syntax is only necessary for attribute _bindings_. -Static ARIA attributes require no extra syntax. +Observa que esta sintaxis solo es necesaria para los _enlaces_ de atributos. +Los atributos ARIA estáticos no requieren de ninguna sintaxis adicional. ```html ``` -NOTE: +NOTA:
- By convention, HTML attributes use lowercase names (`tabindex`), while properties use camelCase names (`tabIndex`). + Por convenio, los atributos HTML se escriben en minúscula (`tabindex`), mientras que para las propiedades se usa *camelCase* (`tabIndex`). - See the [Binding syntax](guide/binding-syntax#html-attribute-vs-dom-property) guide for more background on the difference between attributes and properties. + Consulta la guía [Sintaxis del enlace](guide/binding-syntax#html-attribute-vs-dom-property) para saber más sobre las diferencias entre atributos y propiedades.
-## Angular UI components +## Componentes del interfaz de usuario de Angular -The [Angular Material](https://material.angular.io/) library, which is maintained by the Angular team, is a suite of reusable UI components that aims to be fully accessible. -The [Component Development Kit (CDK)](https://material.angular.io/cdk/categories) includes the `a11y` package that provides tools to support various areas of accessibility. -For example: +La librería [Angular Material](https://material.angular.io/), que es mantenida por el equipo Angular, es un conjunto de componentes reutilizables para la interfaz de usuario que pretende ser totalmente accesible. +El [Kit de Desarrollo de Componentes (CDK)](https://material.angular.io/cdk/categories) (Component Development Kit) incluye el paquete `a11y` que proporciona herramientas para dar soporte a distintos aspectos de la accesibilidad. +Por ejemplo: -* `LiveAnnouncer` is used to announce messages for screen-reader users using an `aria-live` region. See the W3C documentation for more information on [aria-live regions](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live). +* `LiveAnnouncer` se utiliza para comunicar mensajes a los usuarios de lectores de pantalla que usan la region `aria-live`. Se puede consultar la documentación de la W3C para obtener más información sobre [regiones aria-live](https://www.w3.org/WAI/PF/aria-1.1/states_and_properties#aria-live). -* The `cdkTrapFocus` directive traps Tab-key focus within an element. Use it to create accessible experience for components like modal dialogs, where focus must be constrained. +* La directiva `cdkTrapFocus` limita el foco de la tecla de tabulación para que se quede dentro de un elemento. Úsala para crear una experiencia accesible en componentes como las ventanas modales, donde el foco debe estar limitado. -For full details of these and other tools, see the [Angular CDK accessibility overview](https://material.angular.io/cdk/a11y/overview). +Para obtener más detalles sobre esta y otras herramientas, consulta el [resumen de accesibilidad del Angular CDK](https://material.angular.io/cdk/a11y/overview). -### Augmenting native elements +### Aumento de elementos nativos -Native HTML elements capture a number of standard interaction patterns that are important to accessibility. -When authoring Angular components, you should re-use these native elements directly when possible, rather than re-implementing well-supported behaviors. +Los elementos HTML nativos capturan una serie de patrones de interacción estándar que son importantes para la accesibilidad. +Al crear componentes de Angular, deberías reutilizar estos elementos nativos directamente cuando sea posible, en lugar de volver a implementar comportamientos bien soportados. -For example, instead of creating a custom element for a new variety of button, you can create a component that uses an attribute selector with a native ` + + `, +}) +class TemplateFormsComponent { + name = {first: 'Nancy', last: 'Drew', subscribed: true}; + addresses = [{city: 'Toronto'}]; + constructor() { + // We use this reference in our test + (window as any).templateFormsComponent = this; + } + + addCity() { + this.addresses.push(({city: ''})); + } +} + +@Component({ + selector: 'app-reactive-forms', + template: ` +
+
+ First Name: + +
+
+ Last Name: + +
+ +
+ Subscribe: + +
+ +
Disabled:
+
+
+
City:
+
+
+ +
`, +}) +class ReactiveFormsComponent { + profileForm!: FormGroup; + addresses!: FormArray; + + get itemControls() { + return (this.profileForm.get('addresses') as FormArray).controls; + } + + constructor(private formBuilder: FormBuilder) { + // We use this reference in our test + (window as any).reactiveFormsComponent = this; + } + + ngOnInit() { + this.profileForm = new FormGroup({ + firstName: new FormControl('', Validators.required), + lastName: new FormControl(''), + addresses: new FormArray([]), + subscribed: new FormControl(), + disabledInput: new FormControl({value: '', disabled: true}), + }); + + this.addCity(); + } + + createItem(): FormGroup { + return this.formBuilder.group({ + city: '', + }); + } + + addCity(): void { + this.addresses = this.profileForm.get('addresses') as FormArray; + this.addresses.push(this.createItem()); + } +} + +@Component({ + selector: 'app-root', + template: ` + + + ` +}) +class RootComponent { +} + +@NgModule({ + declarations: [RootComponent, TemplateFormsComponent, ReactiveFormsComponent], + imports: [BrowserModule, FormsModule, ReactiveFormsModule] +}) +class FormsExampleModule { + ngDoBootstrap(app: any) { + app.bootstrap(RootComponent); + } +} + +(window as any).waitForApp = platformBrowser().bootstrapModuleFactory( + new NgModuleFactory(FormsExampleModule), {ngZone: 'noop'}); diff --git a/packages/core/test/bundling/forms/treeshaking_spec.ts b/packages/core/test/bundling/forms/treeshaking_spec.ts new file mode 100644 index 000000000000..546a88ee0a4b --- /dev/null +++ b/packages/core/test/bundling/forms/treeshaking_spec.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright Google LLC 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://angular.io/license + */ + +import '@angular/compiler'; +import * as fs from 'fs'; +import * as path from 'path'; + +const UTF8 = { + encoding: 'utf-8' +}; +const PACKAGE = 'angular/packages/core/test/bundling/forms'; + +describe('treeshaking with uglify', () => { + let content: string; + // We use the debug version as otherwise symbols/identifiers would be mangled (and the test would + // always pass) + const contentPath = require.resolve(path.join(PACKAGE, 'bundle.min_debug.js')); + beforeAll(() => { + content = fs.readFileSync(contentPath, UTF8); + }); + + it('should drop unused TypeScript helpers', () => { + expect(content).not.toContain('__asyncGenerator'); + }); + + it('should not contain rxjs from commonjs distro', () => { + expect(content).not.toContain('commonjsGlobal'); + expect(content).not.toContain('createCommonjsModule'); + }); +}); From 1d46ef38d24572b639f99b3212785b606dc170bd Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Mon, 20 Jul 2020 11:53:26 -0700 Subject: [PATCH 039/253] refactor(dev-infra): Add support for groups in the conditions evaluator (#38164) Conditions can refer to the groups array that is a list of the preceding groups. This commit adds support to the verification for those conditions. This commit also adds some tests to the parsing and condition matching to ensure everything works as expected. PR Close #38164 --- dev-infra/pullapprove/BUILD.bazel | 24 ++++++ dev-infra/pullapprove/condition_evaluator.ts | 69 ++++----------- dev-infra/pullapprove/group.ts | 35 +++++--- dev-infra/pullapprove/parse-yaml.ts | 10 +++ dev-infra/pullapprove/pullapprove_arrays.ts | 89 ++++++++++++++++++++ dev-infra/pullapprove/utils.ts | 24 ++++++ dev-infra/pullapprove/verify.spec.ts | 88 +++++++++++++++++++ dev-infra/pullapprove/verify.ts | 10 +-- dev-infra/utils/BUILD.bazel | 1 + 9 files changed, 280 insertions(+), 70 deletions(-) create mode 100644 dev-infra/pullapprove/pullapprove_arrays.ts create mode 100644 dev-infra/pullapprove/utils.ts create mode 100644 dev-infra/pullapprove/verify.spec.ts diff --git a/dev-infra/pullapprove/BUILD.bazel b/dev-infra/pullapprove/BUILD.bazel index f73a2aaecab8..4cd28756f03b 100644 --- a/dev-infra/pullapprove/BUILD.bazel +++ b/dev-infra/pullapprove/BUILD.bazel @@ -1,4 +1,5 @@ load("@npm_bazel_typescript//:index.bzl", "ts_library") +load("//tools:defaults.bzl", "jasmine_node_test") ts_library( name = "pullapprove", @@ -8,6 +9,8 @@ ts_library( "group.ts", "logging.ts", "parse-yaml.ts", + "pullapprove_arrays.ts", + "utils.ts", "verify.ts", ], module_name = "@angular/dev-infra-private/pullapprove", @@ -25,3 +28,24 @@ ts_library( "@npm//yargs", ], ) + +ts_library( + name = "pullapprove_test_lib", + testonly = True, + srcs = glob( + ["*.spec.ts"], + ), + visibility = ["//visibility:private"], + deps = [ + ":pullapprove", + "@npm//@types/jasmine", + "@npm//@types/node", + "@npm//typescript", + ], +) + +jasmine_node_test( + name = "pullapprove_test", + srcs = [":pullapprove_test_lib"], + visibility = ["//visibility:private"], +) diff --git a/dev-infra/pullapprove/condition_evaluator.ts b/dev-infra/pullapprove/condition_evaluator.ts index 340e0b84a213..b64eb7a5a8f0 100644 --- a/dev-infra/pullapprove/condition_evaluator.ts +++ b/dev-infra/pullapprove/condition_evaluator.ts @@ -6,10 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ -import {IMinimatch, Minimatch} from 'minimatch'; - -/** Map that holds patterns and their corresponding Minimatch globs. */ -const patternCache = new Map(); +import {PullApproveGroup} from './group'; +import {PullApproveGroupArray, PullApproveStringArray} from './pullapprove_arrays'; +import {getOrCreateGlob} from './utils'; /** * Context that is provided to conditions. Conditions can use various helpers @@ -18,30 +17,34 @@ const patternCache = new Map(); */ const conditionContext = { 'len': (value: any[]) => value.length, - 'contains_any_globs': (files: PullApproveArray, patterns: string[]) => { + 'contains_any_globs': (files: PullApproveStringArray, patterns: string[]) => { // Note: Do not always create globs for the same pattern again. This method // could be called for each source file. Creating glob's is expensive. return files.some(f => patterns.some(pattern => getOrCreateGlob(pattern).match(f))); - } + }, }; /** * Converts a given condition to a function that accepts a set of files. The returned * function can be called to check if the set of files matches the condition. */ -export function convertConditionToFunction(expr: string): (files: string[]) => boolean { - // Creates a dynamic function with the specified expression. The first parameter will - // be `files` as that corresponds to the supported `files` variable that can be accessed - // in PullApprove condition expressions. The followed parameters correspond to other - // context variables provided by PullApprove for conditions. - const evaluateFn = new Function('files', ...Object.keys(conditionContext), ` +export function convertConditionToFunction(expr: string): ( + files: string[], groups: PullApproveGroup[]) => boolean { + // Creates a dynamic function with the specified expression. + // The first parameter will be `files` as that corresponds to the supported `files` variable that + // can be accessed in PullApprove condition expressions. The second parameter is the list of + // PullApproveGroups that are accessible in the condition expressions. The followed parameters + // correspond to other context variables provided by PullApprove for conditions. + const evaluateFn = new Function('files', 'groups', ...Object.keys(conditionContext), ` return (${transformExpressionToJs(expr)}); `); // Create a function that calls the dynamically constructed function which mimics // the condition expression that is usually evaluated with Python in PullApprove. - return files => { - const result = evaluateFn(new PullApproveArray(...files), ...Object.values(conditionContext)); + return (files, groups) => { + const result = evaluateFn( + new PullApproveStringArray(...files), new PullApproveGroupArray(...groups), + ...Object.values(conditionContext)); // If an array is returned, we consider the condition as active if the array is not // empty. This matches PullApprove's condition evaluation that is based on Python. if (Array.isArray(result)) { @@ -59,41 +62,3 @@ export function convertConditionToFunction(expr: string): (files: string[]) => b function transformExpressionToJs(expression: string): string { return expression.replace(/not\s+/g, '!'); } - -/** - * Superset of a native array. The superset provides methods which mimic the - * list data structure used in PullApprove for files in conditions. - */ -class PullApproveArray extends Array { - constructor(...elements: string[]) { - super(...elements); - - // Set the prototype explicitly because in ES5, the prototype is accidentally - // lost due to a limitation in down-leveling. - // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. - Object.setPrototypeOf(this, PullApproveArray.prototype); - } - - /** Returns a new array which only includes files that match the given pattern. */ - include(pattern: string): PullApproveArray { - return new PullApproveArray(...this.filter(s => getOrCreateGlob(pattern).match(s))); - } - - /** Returns a new array which only includes files that did not match the given pattern. */ - exclude(pattern: string): PullApproveArray { - return new PullApproveArray(...this.filter(s => !getOrCreateGlob(pattern).match(s))); - } -} - -/** - * Gets a glob for the given pattern. The cached glob will be returned - * if available. Otherwise a new glob will be created and cached. - */ -function getOrCreateGlob(pattern: string) { - if (patternCache.has(pattern)) { - return patternCache.get(pattern)!; - } - const glob = new Minimatch(pattern, {dot: true}); - patternCache.set(pattern, glob); - return glob; -} diff --git a/dev-infra/pullapprove/group.ts b/dev-infra/pullapprove/group.ts index a27ef876cf99..45de9eac236c 100644 --- a/dev-infra/pullapprove/group.ts +++ b/dev-infra/pullapprove/group.ts @@ -6,14 +6,15 @@ * found in the LICENSE file at https://angular.io/license */ -import {error} from '../utils/console'; +import {error, warn} from '../utils/console'; import {convertConditionToFunction} from './condition_evaluator'; import {PullApproveGroupConfig} from './parse-yaml'; +import {PullApproveGroupStateDependencyError} from './pullapprove_arrays'; /** A condition for a group. */ interface GroupCondition { expression: string; - checkFn: (files: string[]) => boolean; + checkFn: (files: string[], groups: PullApproveGroup[]) => boolean; matchedFiles: Set; } @@ -39,7 +40,9 @@ export class PullApproveGroup { /** List of conditions for the group. */ conditions: GroupCondition[] = []; - constructor(public groupName: string, config: PullApproveGroupConfig) { + constructor( + public groupName: string, config: PullApproveGroupConfig, + readonly precedingGroups: PullApproveGroup[] = []) { this._captureConditions(config); } @@ -78,18 +81,30 @@ export class PullApproveGroup { testFile(filePath: string): boolean { return this.conditions.every(({matchedFiles, checkFn, expression}) => { try { - const matchesFile = checkFn([filePath]); + const matchesFile = checkFn([filePath], this.precedingGroups); if (matchesFile) { matchedFiles.add(filePath); } return matchesFile; } catch (e) { - const errMessage = `Condition could not be evaluated: \n\n` + - `From the [${this.groupName}] group:\n` + - ` - ${expression}` + - `\n\n${e.message} ${e.stack}\n\n`; - error(errMessage); - process.exit(1); + // In the case of a condition that depends on the state of groups we want to just + // warn that the verification can't accurately evaluate the condition and then + // continue processing. Other types of errors fail the verification, as conditions + // should otherwise be able to execute without throwing. + if (e instanceof PullApproveGroupStateDependencyError) { + const errMessage = `Condition could not be evaluated: \n` + + `${e.message}\n` + + `From the [${this.groupName}] group:\n` + + ` - ${expression}`; + warn(errMessage); + } else { + const errMessage = `Condition could not be evaluated: \n\n` + + `From the [${this.groupName}] group:\n` + + ` - ${expression}` + + `\n\n${e.message} ${e.stack}\n\n`; + error(errMessage); + process.exit(1); + } } }); } diff --git a/dev-infra/pullapprove/parse-yaml.ts b/dev-infra/pullapprove/parse-yaml.ts index c0856d176385..fc0289ecce7e 100644 --- a/dev-infra/pullapprove/parse-yaml.ts +++ b/dev-infra/pullapprove/parse-yaml.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ import {parse as parseYaml} from 'yaml'; +import {PullApproveGroup} from './group'; export interface PullApproveGroupConfig { conditions?: string[]; @@ -33,3 +34,12 @@ export interface PullApproveConfig { export function parsePullApproveYaml(rawYaml: string): PullApproveConfig { return parseYaml(rawYaml, {merge: true}) as PullApproveConfig; } + +/** Parses all of the groups defined in the pullapprove yaml. */ +export function getGroupsFromYaml(pullApproveYamlRaw: string): PullApproveGroup[] { + /** JSON representation of the pullapprove yaml file. */ + const pullApprove = parsePullApproveYaml(pullApproveYamlRaw); + return Object.entries(pullApprove.groups).reduce((groups, [groupName, group]) => { + return groups.concat(new PullApproveGroup(groupName, group, groups)); + }, [] as PullApproveGroup[]); +} diff --git a/dev-infra/pullapprove/pullapprove_arrays.ts b/dev-infra/pullapprove/pullapprove_arrays.ts new file mode 100644 index 000000000000..46cec6d5227b --- /dev/null +++ b/dev-infra/pullapprove/pullapprove_arrays.ts @@ -0,0 +1,89 @@ +/** + * @license + * Copyright Google LLC 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://angular.io/license + */ +import {PullApproveGroup} from './group'; +import {getOrCreateGlob} from './utils'; + +export class PullApproveGroupStateDependencyError extends Error { + constructor(message?: string) { + super(message); + // Set the prototype explicitly because in ES5, the prototype is accidentally + // lost due to a limitation in down-leveling. + // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. + Object.setPrototypeOf(this, PullApproveGroupStateDependencyError.prototype); + // Error names are displayed in their stack but can't be set in the constructor. + this.name = PullApproveGroupStateDependencyError.name; + } +} + +/** + * Superset of a native array. The superset provides methods which mimic the + * list data structure used in PullApprove for files in conditions. + */ +export class PullApproveStringArray extends Array { + constructor(...elements: string[]) { + super(...elements); + + // Set the prototype explicitly because in ES5, the prototype is accidentally + // lost due to a limitation in down-leveling. + // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. + Object.setPrototypeOf(this, PullApproveStringArray.prototype); + } + /** Returns a new array which only includes files that match the given pattern. */ + include(pattern: string): PullApproveStringArray { + return new PullApproveStringArray(...this.filter(s => getOrCreateGlob(pattern).match(s))); + } + + /** Returns a new array which only includes files that did not match the given pattern. */ + exclude(pattern: string): PullApproveStringArray { + return new PullApproveStringArray(...this.filter(s => !getOrCreateGlob(pattern).match(s))); + } +} + +/** + * Superset of a native array. The superset provides methods which mimic the + * list data structure used in PullApprove for groups in conditions. + */ +export class PullApproveGroupArray extends Array { + constructor(...elements: PullApproveGroup[]) { + super(...elements); + + // Set the prototype explicitly because in ES5, the prototype is accidentally + // lost due to a limitation in down-leveling. + // https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-extending-built-ins-like-error-array-and-map-work. + Object.setPrototypeOf(this, PullApproveGroupArray.prototype); + } + + include(pattern: string): PullApproveGroupArray { + return new PullApproveGroupArray(...this.filter(s => s.groupName.match(pattern))); + } + + /** Returns a new array which only includes files that did not match the given pattern. */ + exclude(pattern: string): PullApproveGroupArray { + return new PullApproveGroupArray(...this.filter(s => s.groupName.match(pattern))); + } + + get pending() { + throw new PullApproveGroupStateDependencyError(); + } + + get active() { + throw new PullApproveGroupStateDependencyError(); + } + + get inactive() { + throw new PullApproveGroupStateDependencyError(); + } + + get rejected() { + throw new PullApproveGroupStateDependencyError(); + } + + get names() { + return this.map(g => g.groupName); + } +} diff --git a/dev-infra/pullapprove/utils.ts b/dev-infra/pullapprove/utils.ts new file mode 100644 index 000000000000..8e93f07a9f7f --- /dev/null +++ b/dev-infra/pullapprove/utils.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright Google LLC 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://angular.io/license + */ +import {IMinimatch, Minimatch} from 'minimatch'; + +/** Map that holds patterns and their corresponding Minimatch globs. */ +const patternCache = new Map(); + +/** + * Gets a glob for the given pattern. The cached glob will be returned + * if available. Otherwise a new glob will be created and cached. + */ +export function getOrCreateGlob(pattern: string) { + if (patternCache.has(pattern)) { + return patternCache.get(pattern)!; + } + const glob = new Minimatch(pattern, {dot: true}); + patternCache.set(pattern, glob); + return glob; +} diff --git a/dev-infra/pullapprove/verify.spec.ts b/dev-infra/pullapprove/verify.spec.ts new file mode 100644 index 000000000000..f3ddb620887e --- /dev/null +++ b/dev-infra/pullapprove/verify.spec.ts @@ -0,0 +1,88 @@ +/** + * @license + * Copyright Google LLC 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://angular.io/license + */ +import {PullApproveGroup} from './group'; +import {getGroupsFromYaml} from './parse-yaml'; + +describe('group parsing', () => { + it('gets group name', () => { + const groupName = 'fw-migrations'; + const groups = getGroupsFromYaml(` + groups: + ${groupName}: + type: optional + `); + expect(groups[0].groupName).toBe(groupName); + }); + + it('gets correct number of groups', () => { + const groups = getGroupsFromYaml(` + groups: + fw-migrations: + type: optional + fw-core: + type: optional + `); + expect(groups.length).toBe(2); + }); + + it('gets preceding groups', () => { + const groups = getGroupsFromYaml(` + groups: + fw-migrations: + type: optional + fw-core: + type: optional + dev-infra: + type: optional + `); + const fwMigrations = getGroupByName(groups, 'fw-migrations')!; + const fwCore = getGroupByName(groups, 'fw-core')!; + const devInfra = getGroupByName(groups, 'dev-infra')!; + expect(getGroupNames(fwMigrations.precedingGroups)).toEqual([]); + expect(getGroupNames(fwCore.precedingGroups)).toEqual([fwMigrations.groupName]); + expect(getGroupNames(devInfra.precedingGroups)).toEqual([ + fwMigrations.groupName, fwCore.groupName + ]); + }); + + it('matches file conditions', () => { + const groups = getGroupsFromYaml(` + groups: + fw-core: + conditions: + - contains_any_globs(files, ['packages/core/**']) + `); + const fwCore = getGroupByName(groups, 'fw-core')!; + expect(fwCore.testFile('packages/core/test.ts')).toBe(true); + expect(fwCore.testFile('some/other/location/test.ts')).toBe(false); + }); + + it('allows conditions based on groups', () => { + const groups = getGroupsFromYaml(` + groups: + fw-migrations: + conditions: + - len(groups) > 0 + fw-core: + conditions: + - len(groups.active) > 0 + `); + const fwMigrations = getGroupByName(groups, 'fw-migrations')!; + expect(() => fwMigrations.testFile('any')).not.toThrow(); + const fwCore = getGroupByName(groups, 'fw-core')!; + expect(() => fwCore.testFile('any')).not.toThrow(); + }); +}); + +function getGroupByName(groups: PullApproveGroup[], name: string): PullApproveGroup|undefined { + return groups.find(g => g.groupName === name); +} + +function getGroupNames(groups: PullApproveGroup[]) { + return groups.map(g => g.groupName); +} diff --git a/dev-infra/pullapprove/verify.ts b/dev-infra/pullapprove/verify.ts index f349edeeefd9..d8302c2caa00 100644 --- a/dev-infra/pullapprove/verify.ts +++ b/dev-infra/pullapprove/verify.ts @@ -11,10 +11,8 @@ import {resolve} from 'path'; import {getRepoBaseDir} from '../utils/config'; import {debug, info} from '../utils/console'; import {allFiles} from '../utils/repo-files'; - -import {PullApproveGroup} from './group'; import {logGroup, logHeader} from './logging'; -import {parsePullApproveYaml} from './parse-yaml'; +import {getGroupsFromYaml} from './parse-yaml'; export function verify() { /** Full path to PullApprove config file */ @@ -23,12 +21,8 @@ export function verify() { const REPO_FILES = allFiles(); /** The pull approve config file. */ const pullApproveYamlRaw = readFileSync(PULL_APPROVE_YAML_PATH, 'utf8'); - /** JSON representation of the pullapprove yaml file. */ - const pullApprove = parsePullApproveYaml(pullApproveYamlRaw); /** All of the groups defined in the pullapprove yaml. */ - const groups = Object.entries(pullApprove.groups).map(([groupName, group]) => { - return new PullApproveGroup(groupName, group); - }); + const groups = getGroupsFromYaml(pullApproveYamlRaw); /** * PullApprove groups without conditions. These are skipped in the verification * as those would always be active and cause zero unmatched files. diff --git a/dev-infra/utils/BUILD.bazel b/dev-infra/utils/BUILD.bazel index f1bdc1976d54..248aaddacfca 100644 --- a/dev-infra/utils/BUILD.bazel +++ b/dev-infra/utils/BUILD.bazel @@ -16,6 +16,7 @@ ts_library( "@npm//@types/node", "@npm//@types/shelljs", "@npm//chalk", + "@npm//inquirer", "@npm//shelljs", "@npm//tslib", "@npm//typed-graphqlify", From ccb0b42ffb6e52b8f8e5954a37e2db97822a5928 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Wed, 22 Jul 2020 20:13:21 +0300 Subject: [PATCH 040/253] build(docs-infra): upgrade cli command docs sources to b0b27361d (#38182) Updating [angular#master](https://github.com/angular/angular/tree/master) from [cli-builds#master](https://github.com/angular/cli-builds/tree/master). ## Relevant changes in [commit range](https://github.com/angular/cli-builds/compare/b76099083...b0b27361d): **Modified** - help/update.json PR Close #38182 --- aio/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/package.json b/aio/package.json index 09fd239d3bd7..d47ce00c4b86 100644 --- a/aio/package.json +++ b/aio/package.json @@ -23,7 +23,7 @@ "build-local-with-viewengine": "yarn ~~build", "prebuild-local-with-viewengine-ci": "node scripts/switch-to-viewengine && yarn setup-local-ci", "build-local-with-viewengine-ci": "yarn ~~build --progress=false", - "extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js b76099083", + "extract-cli-command-docs": "node tools/transforms/cli-docs-package/extract-cli-commands.js b0b27361d", "lint": "yarn check-env && yarn docs-lint && ng lint && yarn example-lint && yarn tools-lint", "test": "yarn check-env && ng test", "pree2e": "yarn check-env && yarn update-webdriver", From 19b577bf66fd2bd2770a43a981225473a6b02dc4 Mon Sep 17 00:00:00 2001 From: Saif Date: Wed, 22 Jul 2020 23:30:08 +0300 Subject: [PATCH 041/253] fix(docs-infra): correctly display copy button in IE11 (#38186) Fix button top portion was clipped in IE11 by setting overflow to visible Fixes #37816 PR Close #38186 --- aio/src/styles/2-modules/_code.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/aio/src/styles/2-modules/_code.scss b/aio/src/styles/2-modules/_code.scss index 9065bda550e9..5e87cec15a53 100644 --- a/aio/src/styles/2-modules/_code.scss +++ b/aio/src/styles/2-modules/_code.scss @@ -108,6 +108,7 @@ aio-code pre { top: -7px; right: -19px; padding: 0; + overflow: visible; // This is required for the button to be displayed correctly in IE11. color: $blue-grey-200; background-color: transparent; From e65e5ea9d0af83b4eab57f94200297b060572161 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Wed, 22 Jul 2020 22:23:55 +0300 Subject: [PATCH 042/253] build(docs-infra): simplify `ExampleZipper` by removing `PackageJsonCustomizer` (#38192) Previously, `ExampleZipper` (the tool used for creating ZIP archives from our docs examples) used the `PackageJsonCustomizer` to generate `package.json` files for each example type. This had the following drawbacks: - The generated files had to be kept up-to-date with the corresponding boilerplate files in `aio/tools/examples/shared/boilerplate/` and there was no easy way to find out when the files got out-of-sync. - The `PackageJsonCustomizer` logic was non-trivial and difficult to reason about. - The same information was duplicated in the boilerplate files and the customizer configuration files. This setup was useful when we used a single `package.json` file for all docs examples. Now, however, each example type can have its own boilerplate `package.json` file, including scripts and dependencies relevant to the example type. Therefore, it is no longer necessary to generate `package.json` files for ZIP archives. This commit eliminates the drawbacks mentioned above and simplifies the `ExampleZipper` tool by removing `PackageJsonCustomizer` and re-using the boilerplate `package.json` files for ZIP archives. The changes in this commit also fix some ZIP archives that were previously broken (for example due to missing dependencies). PR Close #38192 --- aio/tools/RELEASE.md | 8 --- aio/tools/example-zipper/README.md | 31 +++------ .../customizer/package-json/base.json | 34 ---------- .../customizer/package-json/cli-ajs.json | 23 ------- .../customizer/package-json/cli.json | 19 ------ .../customizer/package-json/elements.json | 22 ------- .../package-json/getting-started.json | 19 ------ .../customizer/package-json/i18n.json | 21 ------- .../customizer/package-json/package.json | 19 ------ .../package-json/packageJsonCustomizer.js | 63 ------------------- .../customizer/package-json/schematics.json | 24 ------- .../customizer/package-json/systemjs.json | 60 ------------------ .../customizer/package-json/testing.json | 20 ------ .../customizer/package-json/universal.json | 29 --------- aio/tools/example-zipper/exampleZipper.js | 7 +-- .../shared/boilerplate/cli-ajs/package.json | 1 + .../shared/boilerplate/cli/package.json | 1 + .../shared/boilerplate/elements/package.json | 1 + .../shared/boilerplate/i18n/package.json | 1 + .../boilerplate/service-worker/package.json | 1 + .../shared/boilerplate/systemjs/package.json | 36 +++++------ .../shared/boilerplate/universal/package.json | 1 + 22 files changed, 32 insertions(+), 409 deletions(-) delete mode 100644 aio/tools/example-zipper/customizer/package-json/base.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/cli-ajs.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/cli.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/elements.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/getting-started.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/i18n.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/package.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/packageJsonCustomizer.js delete mode 100644 aio/tools/example-zipper/customizer/package-json/schematics.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/systemjs.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/testing.json delete mode 100644 aio/tools/example-zipper/customizer/package-json/universal.json diff --git a/aio/tools/RELEASE.md b/aio/tools/RELEASE.md index a45f16bec3bd..419d2597db10 100644 --- a/aio/tools/RELEASE.md +++ b/aio/tools/RELEASE.md @@ -14,11 +14,3 @@ There, select all the packages that are updated on the new Angular release. **2)** Changes to the tsconfig.json? There are several files in `/aio/tools/examples/shared/boilerplate/*/tsconfig.json` (based on the example type). ---- -> NOTE(gkalpak): -> There are some `package.json` files in `/aio/tools/examples/shared/boilerplate/*`. -> AFAICT, they are copied over to the examples (based on the example type), but they are neither -> used for installing dependencies (which come from `/aio/tools/examples/shared/package.json`) nor -> used in zips (since they are overwritten by `/aio/tools/example-zipper/customizer`). -> For all stackblitz live-examples, `/aio/tools/examples/shared/boilerplate/cli/package.json` seems -> to be used. diff --git a/aio/tools/example-zipper/README.md b/aio/tools/example-zipper/README.md index 3979c8698fd1..344f68fe2b3b 100644 --- a/aio/tools/example-zipper/README.md +++ b/aio/tools/example-zipper/README.md @@ -23,33 +23,18 @@ to flag an example as something to stackblitz or zip. For example: The zipper will use this information for creating new zips. -## Three kinds of examples +## Two kinds of examples -The majority of examples in AIO use `CLI`, with some additionally using `Webpack` and upgrade usiing `SystemJS`. This -tool is able to differentiate between them. +There are mainly two kinds of AIO docs examples: The ones based on the Angular CLI and the ones based on SystemJS. +The majority of the examples are CLI-based with only some of the `ngUpgrade` examples using SystemJS. -The boilerplate uses a `package.json` that contains packages and scripts to run any kind of example. -Using that `package.json` in the zips would confuse the users. +Some of the CLI-based examples require small tweaks to the default layout/configuration (for example, to add support for Angular elements, i18n, universal, etc.). +These example types have separate boilerplate directories with the files that are different from the default `cli` boilerplate. -Thanks to the `package.json` customizer, we can create a new `package.json` on the fly that would -only contain the packages and scripts needed to run that example. +There are appropriate `package.json` files for each type of example in the boilerplate directories. +If there is no special `package.json` file for an example type, the one from the `cli` boilerplate directory will be used instead. -The `exampleZipper.js` won't include any `System.js` related files for `CLI` or `Webpack` projects. - -### The package.json customizer - -Given a `type`, this tool will populate a `package.json` file customized for that type. - -Here you find a: - -* **base.json** - All the common scripts and packages -* **cli.json** - Extra scripts and packages for the CLI -* **universal.json** - Extra scripts and packages for universal -* **i18n.json** - Extra scripts and packages for i18n -* **systemjs.json** - All the System.js related packages but it also contains the remainder scripts - that are not in the other files. - -The tool will also give some standard names to the scripts. +The `exampleZipper.js` won't include any `System.js` related files for CLI-based projects. ## The zipper.json diff --git a/aio/tools/example-zipper/customizer/package-json/base.json b/aio/tools/example-zipper/customizer/package-json/base.json deleted file mode 100644 index ba3f3d49c5ff..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/base.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "scripts": [ - { "name": "lint" } - ], - "dependencies": [ - "@angular/animations", - "@angular/common", - "@angular/compiler", - "@angular/core", - "@angular/forms", - "@angular/platform-browser", - "@angular/platform-browser-dynamic", - "@angular/router", - "@angular/upgrade", - "angular-in-memory-web-api", - "rxjs", - "zone.js" - ], - "devDependencies": [ - "@angular/compiler-cli", - "@types/jasmine", - "@types/node", - "jasmine-core", - "karma", - "karma-chrome-launcher", - "karma-cli", - "karma-jasmine", - "karma-jasmine-html-reporter", - "lodash", - "protractor", - "tslint", - "typescript" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/cli-ajs.json b/aio/tools/example-zipper/customizer/package-json/cli-ajs.json deleted file mode 100644 index ef9c75606a26..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/cli-ajs.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [ - "angular", - "angular-route" - ], - "devDependencies": [ - "@angular/cli", - "@types/angular", - "@types/angular-route", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/cli.json b/aio/tools/example-zipper/customizer/package-json/cli.json deleted file mode 100644 index ebbbbc1341ba..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/cli.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/elements.json b/aio/tools/example-zipper/customizer/package-json/elements.json deleted file mode 100644 index 1732dc9ae8a0..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/elements.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [ - "@angular/elements", - "@webcomponents/custom-elements" - ], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/getting-started.json b/aio/tools/example-zipper/customizer/package-json/getting-started.json deleted file mode 100644 index ebbbbc1341ba..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/getting-started.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/i18n.json b/aio/tools/example-zipper/customizer/package-json/i18n.json deleted file mode 100644 index f3434be8d1dc..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/i18n.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "scripts": [ - { "name": "start", "command": "ng serve" }, - { "name": "start:fr", "command": "ng serve --configuration=fr" }, - { "name": "build", "command": "ng build" }, - { "name": "build:fr", "command": "ng build --configuration=production-fr" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" }, - { "name": "extract", "command": "ng xi18n --output-path=locale" } - ], - "dependencies": [], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/package.json b/aio/tools/example-zipper/customizer/package-json/package.json deleted file mode 100644 index a4afa9a41e87..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "angular-io-example", - "version": "1.0.0", - "private": true, - "description": "Example project from an angular.io guide.", - "scripts": { - - }, - "keywords": [], - "author": "", - "license": "MIT", - "dependencies": { - - }, - "devDependencies": { - - }, - "repository": {} -} diff --git a/aio/tools/example-zipper/customizer/package-json/packageJsonCustomizer.js b/aio/tools/example-zipper/customizer/package-json/packageJsonCustomizer.js deleted file mode 100644 index 2255244dcce2..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/packageJsonCustomizer.js +++ /dev/null @@ -1,63 +0,0 @@ -'use strict'; - -const path = require('canonical-path'); -const fs = require('fs'); - -const examplesPath = path.resolve(__dirname, '../../../examples'); -const packageFolder = path.resolve(__dirname); - -class PackageJsonCustomizer { - constructor() { - this.dependenciesPackageJson = this.readJson(path.join(examplesPath, '/shared/package.json')); - this.scriptsPackageJson = this.readJson(path.join(examplesPath, '/shared/boilerplate/systemjs/package.json')); - this.basePackageJson = this.readJson(`${packageFolder}/base.json`); - this.templatePackageJson = this.readJson(`${packageFolder}/package.json`, false); - } - - generate(type = 'systemjs') { - let packageJson = JSON.parse(this.templatePackageJson); - let rules = require(`${packageFolder}/${type}.json`); - - this._mergeJSON(rules, this.basePackageJson); - - rules.scripts.forEach((r) => { - const scriptName = r.name; - const script = this.scriptsPackageJson.scripts[scriptName]; - const finalName = r.rename ? r.rename : r.name; - const finalScript = r.command ? r.command : script; - packageJson.scripts[finalName] = finalScript; - }); - - rules.dependencies.forEach((name) => { - const version = this.dependenciesPackageJson.dependencies[name]; - packageJson.dependencies[name] = version; - }); - - rules.devDependencies.forEach((name) => { - const version = this.dependenciesPackageJson.devDependencies[name]; - packageJson.devDependencies[name] = version; - }); - - return JSON.stringify(packageJson, null, 2); - } - - _mergeJSON(json1, json2) { - var result = json1; - for (var prop in json2) - { - if (json2.hasOwnProperty(prop)) - { - result[prop] = (result[prop].concat(json2[prop])).sort(); - } - } - return result; - } - - readJson(jsonFile, parse = true) { - const contents = fs.readFileSync(jsonFile, 'utf8'); - - return parse ? JSON.parse(contents) : contents; - } -} - -module.exports = PackageJsonCustomizer; diff --git a/aio/tools/example-zipper/customizer/package-json/schematics.json b/aio/tools/example-zipper/customizer/package-json/schematics.json deleted file mode 100644 index 947a1917c20f..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/schematics.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "build:lib", "command": "ng build my-lib" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular-devkit/build-ng-packagr", - "@angular/cli", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ng-packagr", - "tsickle", - "tslib", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/systemjs.json b/aio/tools/example-zipper/customizer/package-json/systemjs.json deleted file mode 100644 index 3deb16df0295..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/systemjs.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "scripts": [ - { "name": "build" }, - { "name": "build:watch" }, - { "name": "serve" }, - { "name": "prestart" }, - { "name": "start" }, - { "name": "pretest" }, - { "name": "test" }, - { "name": "pretest:once" }, - { "name": "test:once" }, - { "name": "build:upgrade" }, - { "name": "serve:upgrade" }, - { "name": "build:aot" }, - { "name": "serve:aot" }, - { "name": "copy-dist-files" } - ], - "dependencies": [ - "@angular/animations", - "@angular/common", - "@angular/compiler", - "@angular/core", - "@angular/forms", - "@angular/platform-browser", - "@angular/platform-browser-dynamic", - "@angular/router", - "@angular/upgrade", - "core-js", - "rxjs", - "systemjs", - "tslib", - "zone.js" - ], - "devDependencies": [ - "@angular/compiler-cli", - "@types/angular", - "@types/angular-animate", - "@types/angular-mocks", - "@types/angular-resource", - "@types/angular-route", - "@types/jasmine", - "@types/jasminewd2", - "@types/node", - "concurrently", - "http-server", - "jasmine-core", - "karma", - "karma-chrome-launcher", - "karma-jasmine", - "karma-jasmine-html-reporter", - "lite-server", - "protractor", - "rollup", - "rollup-plugin-commonjs", - "rollup-plugin-node-resolve", - "rollup-plugin-uglify", - "tslint", - "typescript" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/testing.json b/aio/tools/example-zipper/customizer/package-json/testing.json deleted file mode 100644 index 37c304b4cca2..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/testing.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" } - ], - "dependencies": [], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@types/jasminewd2", - "jasmine-marbles", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/customizer/package-json/universal.json b/aio/tools/example-zipper/customizer/package-json/universal.json deleted file mode 100644 index 7a69d07ec4e2..000000000000 --- a/aio/tools/example-zipper/customizer/package-json/universal.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "scripts": [ - { "name": "ng", "command": "ng" }, - { "name": "build", "command": "ng build" }, - { "name": "start", "command": "ng serve" }, - { "name": "test", "command": "ng test" }, - { "name": "lint", "command": "ng lint" }, - { "name": "e2e", "command": "ng e2e" }, - { "name": "dev:ssr", "command": "ng run angular.io-example:serve-ssr" }, - { "name": "build:ssr", "command": "ng build --prod && ng run angular.io-example:server:production" }, - { "name": "serve:ssr", "command": "node dist/server/main.js" }, - { "name": "prerender", "command": "ng run angular.io-example:prerender" } - ], - "dependencies": [ - "@angular/platform-server", - "@nguniversal/express-engine", - "express" - ], - "devDependencies": [ - "@angular-devkit/build-angular", - "@angular/cli", - "@nguniversal/builders", - "@types/express", - "@types/jasminewd2", - "jasmine-spec-reporter", - "karma-coverage-istanbul-reporter", - "ts-node" - ] -} diff --git a/aio/tools/example-zipper/exampleZipper.js b/aio/tools/example-zipper/exampleZipper.js index 7245e2fa6365..a3830bf0fc36 100644 --- a/aio/tools/example-zipper/exampleZipper.js +++ b/aio/tools/example-zipper/exampleZipper.js @@ -6,7 +6,6 @@ const archiver = require('archiver'); const fs = require('fs-extra'); const globby = require('globby'); -const PackageJsonCustomizer = require('./customizer/package-json/packageJsonCustomizer'); const regionExtractor = require('../transforms/examples-package/services/region-parser'); const EXAMPLE_CONFIG_NAME = 'example-config.json'; @@ -17,7 +16,6 @@ class ExampleZipper { this.examplesSystemjsConfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/systemjs.config.js'); this.examplesSystemjsLoaderConfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/systemjs-angular-loader.js'); this.exampleTsconfig = path.join(__dirname, '../examples/shared/boilerplate/systemjs/src/tsconfig.json'); - this.customizer = new PackageJsonCustomizer(); let gpathStackblitz = path.join(sourceDirName, '**/*stackblitz.json'); let gpathZipper = path.join(sourceDirName, '**/zipper.json'); @@ -91,6 +89,7 @@ class ExampleZipper { 'bs-config.json', 'karma.conf.js', 'karma-test-shim.js', + 'package.json', 'tsconfig.*', 'tslint.*', 'e2e/protractor.conf.js', @@ -100,8 +99,6 @@ class ExampleZipper { 'src/test.ts', 'src/environments/**/*', 'src/testing/**/*', - // Only ignore root package.json - '!package.json' ]; var alwaysExcludes = [ '!**/bs-config.e2e.json', @@ -167,8 +164,6 @@ class ExampleZipper { zip.append(output, { name: relativePath } ); }); - // we need the package.json from _examples root, not the _boilerplate one - zip.append(this.customizer.generate(exampleType), { name: 'package.json' }); // also a systemjs config if (exampleType === 'systemjs') { zip.append(fs.readFileSync(this.examplesSystemjsConfig, 'utf8'), { name: 'src/systemjs.config.js' }); diff --git a/aio/tools/examples/shared/boilerplate/cli-ajs/package.json b/aio/tools/examples/shared/boilerplate/cli-ajs/package.json index 4a07637f769f..d025bc756a28 100644 --- a/aio/tools/examples/shared/boilerplate/cli-ajs/package.json +++ b/aio/tools/examples/shared/boilerplate/cli-ajs/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", diff --git a/aio/tools/examples/shared/boilerplate/cli/package.json b/aio/tools/examples/shared/boilerplate/cli/package.json index 693114462e8e..fbdd7de6f88e 100644 --- a/aio/tools/examples/shared/boilerplate/cli/package.json +++ b/aio/tools/examples/shared/boilerplate/cli/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", diff --git a/aio/tools/examples/shared/boilerplate/elements/package.json b/aio/tools/examples/shared/boilerplate/elements/package.json index 6d412b59a20b..a0b396cf8a0f 100644 --- a/aio/tools/examples/shared/boilerplate/elements/package.json +++ b/aio/tools/examples/shared/boilerplate/elements/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", diff --git a/aio/tools/examples/shared/boilerplate/i18n/package.json b/aio/tools/examples/shared/boilerplate/i18n/package.json index 6d10e0759b87..d0944e64c4b3 100644 --- a/aio/tools/examples/shared/boilerplate/i18n/package.json +++ b/aio/tools/examples/shared/boilerplate/i18n/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", diff --git a/aio/tools/examples/shared/boilerplate/service-worker/package.json b/aio/tools/examples/shared/boilerplate/service-worker/package.json index e88091c1eae3..9c30e90cea4d 100644 --- a/aio/tools/examples/shared/boilerplate/service-worker/package.json +++ b/aio/tools/examples/shared/boilerplate/service-worker/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", diff --git a/aio/tools/examples/shared/boilerplate/systemjs/package.json b/aio/tools/examples/shared/boilerplate/systemjs/package.json index b73fefce44bf..1a609f662650 100644 --- a/aio/tools/examples/shared/boilerplate/systemjs/package.json +++ b/aio/tools/examples/shared/boilerplate/systemjs/package.json @@ -1,8 +1,8 @@ { - "name": "angular-examples", - "version": "1.0.0", - "private": true, - "description": "Example package.json, only contains needed scripts for examples. See _examples/package.json for master package.json.", + "name": "angular.io-example", + "version": "0.0.0", + "description": "Example project from an angular.io guide.", + "license": "MIT", "scripts": { "build": "tsc -p src/", "build:watch": "tsc -p src/ -w", @@ -25,26 +25,25 @@ "serve:aot": "lite-server -c bs-config.aot.json", "copy-dist-files": "node ./copy-dist-files.js" }, - "keywords": [], - "author": "", - "license": "MIT", + "private": true, "dependencies": { - "@angular/animations": "~9.0.3", - "@angular/common": "~9.0.3", - "@angular/compiler": "~9.0.3", - "@angular/core": "~9.0.3", - "@angular/forms": "~9.0.3", - "@angular/platform-browser": "~9.0.3", - "@angular/platform-browser-dynamic": "~9.0.3", - "@angular/router": "~9.0.3", - "@angular/upgrade": "~9.0.3", + "@angular/animations": "~9.1.4", + "@angular/common": "~9.1.4", + "@angular/compiler": "~9.1.4", + "@angular/core": "~9.1.4", + "@angular/forms": "~9.1.4", + "@angular/platform-browser": "~9.1.4", + "@angular/platform-browser-dynamic": "~9.1.4", + "@angular/router": "~9.1.4", + "@angular/upgrade": "~9.1.4", "core-js": "^2.5.4", "rxjs": "~6.5.4", "tslib": "^1.10.0", "zone.js": "~0.10.3" }, "devDependencies": { - "@angular/compiler-cli": "~9.0.3", + "@angular/compiler-cli": "~9.1.4", + "@angular/language-service": "~9.1.4", "@types/angular": "1.6.47", "@types/angular-animate": "1.5.10", "@types/angular-mocks": "1.6.0", @@ -68,6 +67,5 @@ "rollup-plugin-terser": "^5.3.0", "tslint": "~5.18.0", "typescript": "~3.7.5" - }, - "repository": {} + } } diff --git a/aio/tools/examples/shared/boilerplate/universal/package.json b/aio/tools/examples/shared/boilerplate/universal/package.json index d7ce74c3314d..9b503635f999 100644 --- a/aio/tools/examples/shared/boilerplate/universal/package.json +++ b/aio/tools/examples/shared/boilerplate/universal/package.json @@ -1,6 +1,7 @@ { "name": "angular.io-example", "version": "0.0.0", + "description": "Example project from an angular.io guide.", "license": "MIT", "scripts": { "ng": "ng", From 8de04115ec56a5575e9fc159910bd86d03f3c012 Mon Sep 17 00:00:00 2001 From: k-ta-yamada Date: Fri, 24 Jul 2020 23:15:19 +0900 Subject: [PATCH 043/253] docs: fixed that class attribute is not closed (#38219) PR Close #38219 --- aio/content/guide/lifecycle-hooks.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/lifecycle-hooks.md b/aio/content/guide/lifecycle-hooks.md index 46d06fbb9826..27396d9e16b6 100644 --- a/aio/content/guide/lifecycle-hooks.md +++ b/aio/content/guide/lifecycle-hooks.md @@ -569,7 +569,7 @@ which can only be reached by querying for them via the property decorated with {@a no-unidirectional-flow-worries} -
No need to wait for content updates
From cb0aeaf70810f80e1f16c43983fd2ceb718a2f1e Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 23 Jul 2020 16:30:31 -0700 Subject: [PATCH 044/253] docs(core): Fix incorrectly rendered code example in structural directives guide (#38207) The code example was missing a close brace and also incorrectly rendered the template div as an actual div in the page DOM. PR Close #38207 --- aio/content/guide/structural-directives.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aio/content/guide/structural-directives.md b/aio/content/guide/structural-directives.md index 8b2bd6bc2d4e..b49c5199d8c2 100644 --- a/aio/content/guide/structural-directives.md +++ b/aio/content/guide/structural-directives.md @@ -879,12 +879,14 @@ export type LoadingState = Loaded | Loading; export class IfLoadedDirective { @Input('ifLoaded') set state(state: LoadingState) {} static ngTemplateGuard_state(dir: IfLoadedDirective, expr: LoadingState): expr is Loaded { return true; }; +} + export interface Person { name: string; } @Component({ - template: `
{{ state.data }}
`, + template: `<div *ifLoaded="state">{{ state.data }}</div>`, }) export class AppComponent { state: LoadingState; From 54679ea9ccabbdd10b06f82f1dc9535a1dc9ed84 Mon Sep 17 00:00:00 2001 From: Andrii Date: Fri, 24 Jul 2020 06:44:28 +0300 Subject: [PATCH 045/253] docs: Fix link by removing a space (#38214) PR Close #38214 --- aio/content/guide/interpolation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/interpolation.md b/aio/content/guide/interpolation.md index 411829328a35..524cc42f90de 100644 --- a/aio/content/guide/interpolation.md +++ b/aio/content/guide/interpolation.md @@ -170,6 +170,6 @@ If an idempotent expression returns a string or a number, it returns the same st
-There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/built-in-directives #ngfor-with-trackby) for details. +There is one exception to this behavior that applies to `*ngFor`. `*ngFor` has `trackBy` functionality that can deal with referential inequality of objects when iterating over them. See [*ngFor with `trackBy`](guide/built-in-directives#ngfor-with-trackby) for details.
From 788532dc991ca3057151c85618b9a4c0bda8d42d Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Fri, 19 Jul 2019 23:14:28 +0900 Subject: [PATCH 046/253] feat(zone.js): move MutationObserver/FileReader to different module (#31657) Separate `EventTarget`, `FileReader`, `MutationObserver` and `IntersectionObserver` patches into different module. So the user can disable those modules separately. PR Close #31657 --- packages/zone.js/MODULE.md | 4 ++++ packages/zone.js/lib/browser/browser.ts | 11 ++++++++++- packages/zone.js/lib/zone.configurations.api.ts | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/zone.js/MODULE.md b/packages/zone.js/MODULE.md index 4bd378307ea8..e58fab2b7ec8 100644 --- a/packages/zone.js/MODULE.md +++ b/packages/zone.js/MODULE.md @@ -36,6 +36,10 @@ Below is the full list of currently supported modules. |requestAnimationFrame|requestAnimationFrame will be patched as Zone MacroTask|__Zone_disable_requestAnimationFrame = true| |blocking|alert/prompt/confirm will be patched as Zone.run|__Zone_disable_blocking = true| |EventTarget|target.addEventListener will be patched as Zone aware EventTask|__Zone_disable_EventTarget = true| +|MutationObserver|MutationObserver will be patched as Zone aware operation|__Zone_disable_MutationObserver = true| +|IntersectionObserver|Intersection will be patched as Zone aware operation|__Zone_disable_Intersection = true| +|FileReader|FileReader will be patched as Zone aware operation|__Zone_disable_FileReader = true| +|canvas|HTMLCanvasElement.toBlob will be patched as Zone aware operation|__Zone_disable_canvas = true| |IE BrowserTools check|in IE, browser tool will not use zone patched eventListener|__Zone_disable_IE_check = true| |CrossContext check|in webdriver, enable check event listener is cross context|__Zone_enable_cross_context_check = true| |XHR|XMLHttpRequest will be patched as Zone aware MacroTask|__Zone_disable_XHR = true| diff --git a/packages/zone.js/lib/browser/browser.ts b/packages/zone.js/lib/browser/browser.ts index 0e56beaaec88..3023e1941d85 100644 --- a/packages/zone.js/lib/browser/browser.ts +++ b/packages/zone.js/lib/browser/browser.ts @@ -12,7 +12,7 @@ import {findEventTasks} from '../common/events'; import {patchTimer} from '../common/timers'; -import {patchClass, patchMethod, patchPrototype, scheduleMacroTaskWithCurrentZone, ZONE_SYMBOL_ADD_EVENT_LISTENER, ZONE_SYMBOL_REMOVE_EVENT_LISTENER, zoneSymbol} from '../common/utils'; +import {patchClass, patchMethod, patchPrototype, scheduleMacroTaskWithCurrentZone, ZONE_SYMBOL_ADD_EVENT_LISTENER, ZONE_SYMBOL_REMOVE_EVENT_LISTENER, zoneSymbol,} from '../common/utils'; import {patchCustomElements} from './custom-elements'; import {eventTargetPatch, patchEvent} from './event-target'; @@ -59,9 +59,18 @@ Zone.__load_patch('EventTarget', (global: any, Zone: ZoneType, api: _ZonePrivate if (XMLHttpRequestEventTarget && XMLHttpRequestEventTarget.prototype) { api.patchEventTarget(global, [XMLHttpRequestEventTarget.prototype]); } +}); + +Zone.__load_patch('MutationObserver', (global: any, Zone: ZoneType, api: _ZonePrivate) => { patchClass('MutationObserver'); patchClass('WebKitMutationObserver'); +}); + +Zone.__load_patch('IntersectionObserver', (global: any, Zone: ZoneType, api: _ZonePrivate) => { patchClass('IntersectionObserver'); +}); + +Zone.__load_patch('FileReader', (global: any, Zone: ZoneType, api: _ZonePrivate) => { patchClass('FileReader'); }); diff --git a/packages/zone.js/lib/zone.configurations.api.ts b/packages/zone.js/lib/zone.configurations.api.ts index 4c6cfe98c342..c53c81dd2b35 100644 --- a/packages/zone.js/lib/zone.configurations.api.ts +++ b/packages/zone.js/lib/zone.configurations.api.ts @@ -325,6 +325,21 @@ interface ZoneGlobalConfigurations { */ __Zone_disable_EventTarget?: boolean; + /** + * Disable the monkey patch of the browser `FileReader` APIs. + */ + __Zone_disable_FileReader?: boolean; + + /** + * Disable the monkey patch of the browser `MutationObserver` APIs. + */ + __Zone_disable_MutationObserver?: boolean; + + /** + * Disable the monkey patch of the browser `IntersectionObserver` APIs. + */ + __Zone_disable_IntersectionObserver?: boolean; + /** * Disable the monkey patch of the browser onProperty APIs(such as onclick). * From 9e7ce2c91692ef7fee44931c2a7fe58ca42f23d4 Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Wed, 1 Jul 2020 06:11:14 +0900 Subject: [PATCH 047/253] fix(zone.js): clearTimeout/clearInterval should call on object global (#37858) Close #37333 `clearTimeout` is patched by `zone.js`, and it finally calls the native delegate of `clearTimeout`, the current implemention only call `clearNative(id)`, but it should call on object `global` like `clearNative.call(global, id)`. Otherwise in some env, it will throw error `clearTimeout called on an object that does not implement interface Window` PR Close #37858 --- packages/zone.js/lib/common/timers.ts | 2 +- .../zone.js/test/common/setTimeout.spec.ts | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/zone.js/lib/common/timers.ts b/packages/zone.js/lib/common/timers.ts index 50889dbc0edf..e1d68b5a6d57 100644 --- a/packages/zone.js/lib/common/timers.ts +++ b/packages/zone.js/lib/common/timers.ts @@ -55,7 +55,7 @@ export function patchTimer(window: any, setName: string, cancelName: string, nam } function clearTask(task: Task) { - return clearNative!((task.data).handleId); + return clearNative!.call(window, (task.data).handleId); } setNative = diff --git a/packages/zone.js/test/common/setTimeout.spec.ts b/packages/zone.js/test/common/setTimeout.spec.ts index ed62e586ae8b..7d4f31eb6a91 100644 --- a/packages/zone.js/test/common/setTimeout.spec.ts +++ b/packages/zone.js/test/common/setTimeout.spec.ts @@ -6,7 +6,9 @@ * found in the LICENSE file at https://angular.io/license */ +import {patchTimer} from '../../lib/common/timers'; import {isNode, zoneSymbol} from '../../lib/common/utils'; + declare const global: any; const wtfMock = global.wtfMock; @@ -56,6 +58,25 @@ describe('setTimeout', function() { }); }); + it('should call native clearTimeout with the correct context', function() { + // since clearTimeout has been patched already, we can not test `clearTimeout` directly + // we will fake another API patch to test + let context: any = null; + const fakeGlobal = { + setTimeout: function() { + return 1; + }, + clearTimeout: function(id: number) { + context = this; + } + }; + patchTimer(fakeGlobal, 'set', 'clear', 'Timeout') + const cancelId = fakeGlobal.setTimeout(); + const m = fakeGlobal.clearTimeout; + m.call({}, cancelId); + expect(context).toBe(fakeGlobal); + }); + it('should allow cancelation of fns registered with setTimeout after invocation', function(done) { const testZone = Zone.current.fork((Zone as any)['wtfZoneSpec']).fork({name: 'TestZone'}); testZone.run(() => { From f1a92872a4e6ffaf53736bd6e3c7f8294165bf2a Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Wed, 1 Jul 2020 07:15:22 +0900 Subject: [PATCH 048/253] fix(zone.js): patch nodejs EventEmtter.prototype.off (#37863) Close #35473 zone.js nodejs patch should also patch `EventEmitter.prototype.off` as `removeListener`. So `off` can correctly remove the listeners added by `EventEmitter.prototype.addListener` PR Close #37863 --- packages/zone.js/lib/node/events.ts | 2 ++ packages/zone.js/test/node/events.spec.ts | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/packages/zone.js/lib/node/events.ts b/packages/zone.js/lib/node/events.ts index 2366332c5cd5..f09f8a42167a 100644 --- a/packages/zone.js/lib/node/events.ts +++ b/packages/zone.js/lib/node/events.ts @@ -16,6 +16,7 @@ Zone.__load_patch('EventEmitter', (global: any) => { const EE_REMOVE_ALL_LISTENER = 'removeAllListeners'; const EE_LISTENERS = 'listeners'; const EE_ON = 'on'; + const EE_OFF = 'off'; const compareTaskCallbackVsDelegate = function(task: any, delegate: any) { // same callback, same capture, same event name, just return @@ -47,6 +48,7 @@ Zone.__load_patch('EventEmitter', (global: any) => { }); if (result && result[0]) { obj[EE_ON] = obj[EE_ADD_LISTENER]; + obj[EE_OFF] = obj[EE_REMOVE_LISTENER]; } } diff --git a/packages/zone.js/test/node/events.spec.ts b/packages/zone.js/test/node/events.spec.ts index f50b0eb02fb0..9cab424169c5 100644 --- a/packages/zone.js/test/node/events.spec.ts +++ b/packages/zone.js/test/node/events.spec.ts @@ -66,6 +66,18 @@ describe('nodejs EventEmitter', () => { emitter.emit('test2', 'test value'); }); }); + it('should remove listeners by calling off properly', () => { + zoneA.run(() => { + emitter.on('test', shouldNotRun); + emitter.on('test2', shouldNotRun); + emitter.off('test', shouldNotRun); + }); + zoneB.run(() => { + emitter.off('test2', shouldNotRun); + emitter.emit('test', 'test value'); + emitter.emit('test2', 'test value'); + }); + }); it('remove listener should return event emitter', () => { zoneA.run(() => { emitter.on('test', shouldNotRun); From f0209416296c981079d93a9102dd3eea52334bf9 Mon Sep 17 00:00:00 2001 From: JiaLiPassion Date: Sat, 4 Jul 2020 08:54:19 +0900 Subject: [PATCH 049/253] docs(zone.js): update zone.js bundle doc since the APF change (#37919) Since the PR #36540 change the zone.js bundles to Angular Package Format, the bundle name/location are changed, so this PR updated the `README.md` doc for the zone bundles. Also add the recent added new bundles `zone-patch-message-port` doc. PR Close #37919 --- packages/zone.js/README.md | 61 ++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/packages/zone.js/README.md b/packages/zone.js/README.md index 809435561110..d356f4eabc88 100644 --- a/packages/zone.js/README.md +++ b/packages/zone.js/README.md @@ -54,39 +54,50 @@ For more details, please see [MODULE.md](MODULE.md). ## Bundles -There are several bundles under `dist` folder. + +Starting with `v0.11.0`, `zone.js` uses `Angular Package Format` for bundle distribution. +(For backwards compatibility, all bundles can still be accessed from `dist` folder.) |Bundle|Summary| |---|---| -|zone.js|the default bundle, contains the most used APIs such as `setTimeout/Promise/EventTarget...`, also this bundle supports all evergreen and legacy (IE/Legacy Firefox/Legacy Safari) Browsers| -|zone-evergreen.js|the bundle for evergreen browsers, doesn't include the `patch` for `legacy` browsers such as `IE` or old versions of `Firefox/Safari`| -|zone-legacy.js|the patch bundle for legacy browsers, only includes the `patch` for `legacy` browsers such as `IE` or old versions of `Firefox/Safari`. This bundle must be loaded after `zone-evergreen.js`, **`zone.js`=`zone-evergreen.js` + `zone-legacy.js`**| -|zone-testing.js|the bundle for zone testing support, including `jasmine/mocha` support and `async/fakeAsync/sync` test utilities| -|zone-externs.js|the API definitions for `closure compiler`| - -And here are the additional optional patches not included in the main zone.js bundles +|`zone.js`| The default bundle. Contains the most used APIs such as `setTimeout/Promise/EventTarget...`, it also supports differential loading by importing this bundle using `import zone.js`. In legacy browsers it includes some additional patches such as `registerElement` and `EventTarget` like APIs.| +|`zone-testing.js`| The bundle for zone testing support of `jasmine` / `mocha` / `jest`. Also includes test utility functions `async` / `fakeAsync` / `sync`.| +|`zone-node.js`|The NodeJS support bundle.| +|`zone-mix.js`|A mixed bundle which supports both browser and NodeJS. Useful for mixed environment such as Electron.| +|`zone-externs.js`|the API definitions for `closure compiler`.| + +Additional optional patches not included in the `zone.js` bundles which extend functionality. +The additional bundles can be found under `zone.js/plugins` folder. +To use these bundles, add the following code after importing zone.js bundle. + +``` +import 'zone.js'; +// For example, import canvas patch +import 'zone.js/plugins/zone-patch-canvas'; +``` |Patch|Summary| |---|---| -|webapis-media-query.js|patch for `MediaQuery APIs`| -|webapis-notification.js|patch for `Notification APIs`| -|webapis-rtc-peer-connection.js|patch for `RTCPeerConnection APIs`| -|webapis-shadydom.js|patch for `Shady DOM APIs`| -|zone-bluebird.js|patch for `Bluebird APIs`| -|zone-error.js|patch for `Error Global Object`, supports remove `Zone StackTrace`| -|zone-patch-canvas.js|patch for `Canvas API`| -|zone-patch-cordova.js|patch for `Cordova API`| -|zone-patch-electron.js|patch for `Electron API`| -|zone-patch-fetch.js|patch for `Fetch API`| -|zone-patch-jsonp.js|utility for `jsonp API`| -|zone-patch-resize-observer.js|patch for `ResizeObserver API`| -|zone-patch-rxjs.js|patch for `rxjs API`| -|zone-patch-rxjs-fake-async.js|patch for `rxjs fakeasync test`| -|zone-patch-socket-io.js|patch for `socket-io`| -|zone-patch-user-media.js|patch for `UserMedia API`| +|`webapis-media-query.js`|patch for `MediaQuery APIs`| +|`webapis-notification.js`|patch for `Notification APIs`| +|`webapis-rtc-peer-connection.js`|patch for `RTCPeerConnection APIs`| +|`webapis-shadydom.js`|patch for `Shady DOM APIs`| +|`zone-bluebird.js`|patch for `Bluebird APIs`| +|`zone-error.js`|patch for `Error Global Object`, supports adding zone information to stack frame, and also removing unrelated stack frames from `zone.js` internally| +|`zone-patch-canvas.js`|patch for `Canvas API`| +|`zone-patch-cordova.js`|patch for `Cordova API`| +|`zone-patch-electron.js`|patch for `Electron API`| +|`zone-patch-fetch.js`|patch for `Fetch API`| +|`zone-patch-jsonp.js`|helper utility for `jsonp API`| +|`zone-patch-resize-observer.js`|patch for `ResizeObserver API`| +|`zone-patch-rxjs.js`|patch for `rxjs API`| +|`zone-patch-rxjs-fake-async.js`|patch for `rxjs fakeasync test`| +|`zone-patch-socket-io.js`|patch for `socket-io`| +|`zone-patch-user-media.js`|patch for `UserMedia API`| +|`zone-patch-message-port.js`|patch for `MessagePort API`| ## Promise A+ test passed [![Promises/A+ 1.1 compliant](https://promisesaplus.com/assets/logo-small.png)](https://promisesaplus.com/) ## License -MIT +MIT \ No newline at end of file From 5ec0ba72cd86aa776effe87df49c65fbd75d1ade Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Sat, 27 Jun 2020 12:47:54 -0700 Subject: [PATCH 050/253] refactor(dev-infra): create anchors/aliases for excluded always active groups (#37798) global-approvers, global-docs-approvers, and required-minimum-review groups are always active. It's useful to have aliases for getting groups that are active/pending/rejected while excluding these few. PR Close #37798 --- .pullapprove.yml | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/.pullapprove.yml b/.pullapprove.yml index 78a460640a1e..6eea6693f84b 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -67,6 +67,23 @@ version: 3 # Meta field that goes unused by PullApprove to allow for defining aliases to be # used throughout the config. meta: + # The following groups have no file based conditions and will be initially `active` on all PRs + # - `global-approvers` + # - `global-docs-approvers` + # - `required-minimum-review` + # + # By checking the number of active/pending/rejected groups when these are excluded, we can determine + # if any other groups are matched. + # + # Also note that the ordering of groups matters in this file. The only groups visible to the current + # one are those that appear above it. + no-groups-above-this-pending: &no-groups-above-this-pending + len(groups.pending.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0 + no-groups-above-this-rejected: &no-groups-above-this-rejected + len(groups.rejected.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0 + no-groups-above-this-active: &no-groups-above-this-active + len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0 + can-be-global-approved: &can-be-global-approved "\"global-approvers\" not in groups.approved" can-be-global-docs-approved: &can-be-global-docs-approved "\"global-docs-approvers\" not in groups.approved" defaults: &defaults @@ -1258,14 +1275,7 @@ groups: # `global-approvers` can still approve PRs that match this `fallback` rule, # but that should be an exception and not an expectation. conditions: - # The following groups have no file based conditions and will be initially `active` on all PRs - # - `global-approvers` - # - `global-docs-approvers` - # - `required-minimum-review` - # - # By checking the number of active groups when these are excluded, we can determine - # if any other groups are matched. - - len(groups.active.exclude("required-minimum-review").exclude("global-approvers").exclude("global-docs-approvers")) == 0 + - *no-groups-above-this-active # When any of the `global-*` groups is approved, they cause other groups to deactivate. # In those cases, the condition above would evaluate to `true` while in reality, only a global # approval has been provided. To ensure we don't activate the fallback group in such cases, From 2981656ebee3672a054f92781e740b58708610e6 Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Sat, 27 Jun 2020 12:53:43 -0700 Subject: [PATCH 051/253] feat(dev-infra): add phased review to groups requiring final sign-off after initial review (#37798) The size-tracking, public-api, and circular-dependencies groups can get a lot of PRs to review. In addition, the members of these groups do not always have the necessary context to fully review the PR in question. This change ensures that the owners in the groups where the changes are being made have approve the changes (ie, the aren't pending or rejected) before requesting final sign-off from these three critical groups. PR Close #37798 --- .pullapprove.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.pullapprove.yml b/.pullapprove.yml index 6eea6693f84b..7ecae6ed4cae 100644 --- a/.pullapprove.yml +++ b/.pullapprove.yml @@ -1160,6 +1160,8 @@ groups: public-api: <<: *defaults conditions: + - *no-groups-above-this-pending + - *no-groups-above-this-rejected - *can-be-global-approved - > contains_any_globs(files, [ @@ -1190,6 +1192,8 @@ groups: size-tracking: <<: *defaults conditions: + - *no-groups-above-this-pending + - *no-groups-above-this-rejected - *can-be-global-approved - > contains_any_globs(files, [ @@ -1214,6 +1218,8 @@ groups: circular-dependencies: <<: *defaults conditions: + - *no-groups-above-this-pending + - *no-groups-above-this-rejected - *can-be-global-approved - > contains_any_globs(files, [ From 6bf8d2b3560a43e606f8c98cc4cf426301f6ddff Mon Sep 17 00:00:00 2001 From: Andrew Scott Date: Thu, 23 Jul 2020 15:53:46 -0700 Subject: [PATCH 052/253] fix(dev-infra): Ensure conditions with groups do not fail verification (#37798) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a few changes in this PR to ensure conditions that are based on groups (i.e. `- groups.pending.length == 0`) do not fail the verify task: * Remove the warning when a condition is encountered that depends on the `groups` state. The warning will otherwise be printed once for every file that triggers the execution of the condition (400,000+ times) * Add an `unverifiable` flag to `GroupCondition` interface and set it to true when an error is encountered due to attempting to get the state of `groups` in a condition * Ignore any unverifiable conditions when gathering unmatched conditions. These should not be considered `unmatched` for verification purposes. * Print the unverifiable conditions by group in the results Sample output: ``` ┌──────────────────────────────────────────────────────────────────────────────┐ │ PullApprove results by group │ └──────────────────────────────────────────────────────────────────────────────┘ Groups skipped (4 groups) Matched conditions by Group (37 groups) Unmatched conditions by Group (0 groups) Unverifiable conditions by Group (3 groups) [public-api] len(groups.pending.exclude("required-minimum-review")... len(groups.rejected.exclude("required-minimum-review")... [size-tracking] len(groups.pending.exclude("required-minimum-review")... len(groups.rejected.exclude("required-minimum-review")... [circular-dependencies] len(groups.pending.exclude("required-minimum-review")... len(groups.rejected.exclude("required-minimum-review")... ``` PR Close #37798 --- dev-infra/pullapprove/group.ts | 27 ++++++++++++++++----------- dev-infra/pullapprove/logging.ts | 19 ++++++++++++++----- dev-infra/pullapprove/verify.ts | 9 +++++++-- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/dev-infra/pullapprove/group.ts b/dev-infra/pullapprove/group.ts index 45de9eac236c..3aaeaf1cf60f 100644 --- a/dev-infra/pullapprove/group.ts +++ b/dev-infra/pullapprove/group.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ -import {error, warn} from '../utils/console'; +import {error} from '../utils/console'; import {convertConditionToFunction} from './condition_evaluator'; import {PullApproveGroupConfig} from './parse-yaml'; import {PullApproveGroupStateDependencyError} from './pullapprove_arrays'; @@ -16,6 +16,7 @@ interface GroupCondition { expression: string; checkFn: (files: string[], groups: PullApproveGroup[]) => boolean; matchedFiles: Set; + unverifiable: boolean; } /** Result of testing files against the group. */ @@ -25,6 +26,7 @@ export interface PullApproveGroupResult { matchedCount: number; unmatchedConditions: GroupCondition[]; unmatchedCount: number; + unverifiableConditions: GroupCondition[]; } // Regular expression that matches conditions for the global approval. @@ -61,6 +63,7 @@ export class PullApproveGroup { expression, checkFn: convertConditionToFunction(expression), matchedFiles: new Set(), + unverifiable: false, }); } catch (e) { error(`Could not parse condition in group: ${this.groupName}`); @@ -79,7 +82,8 @@ export class PullApproveGroup { * the pull approve group's conditions. */ testFile(filePath: string): boolean { - return this.conditions.every(({matchedFiles, checkFn, expression}) => { + return this.conditions.every((condition) => { + const {matchedFiles, checkFn, expression} = condition; try { const matchesFile = checkFn([filePath], this.precedingGroups); if (matchesFile) { @@ -87,16 +91,14 @@ export class PullApproveGroup { } return matchesFile; } catch (e) { - // In the case of a condition that depends on the state of groups we want to just - // warn that the verification can't accurately evaluate the condition and then + // In the case of a condition that depends on the state of groups we want to + // ignore that the verification can't accurately evaluate the condition and then // continue processing. Other types of errors fail the verification, as conditions // should otherwise be able to execute without throwing. if (e instanceof PullApproveGroupStateDependencyError) { - const errMessage = `Condition could not be evaluated: \n` + - `${e.message}\n` + - `From the [${this.groupName}] group:\n` + - ` - ${expression}`; - warn(errMessage); + condition.unverifiable = true; + // Return true so that `this.conditions.every` can continue evaluating. + return true; } else { const errMessage = `Condition could not be evaluated: \n\n` + `From the [${this.groupName}] group:\n` + @@ -111,13 +113,16 @@ export class PullApproveGroup { /** Retrieve the results for the Group, all matched and unmatched conditions. */ getResults(): PullApproveGroupResult { - const matchedConditions = this.conditions.filter(c => !!c.matchedFiles.size); - const unmatchedConditions = this.conditions.filter(c => !c.matchedFiles.size); + const matchedConditions = this.conditions.filter(c => c.matchedFiles.size > 0); + const unmatchedConditions = + this.conditions.filter(c => c.matchedFiles.size === 0 && !c.unverifiable); + const unverifiableConditions = this.conditions.filter(c => c.unverifiable); return { matchedConditions, matchedCount: matchedConditions.length, unmatchedConditions, unmatchedCount: unmatchedConditions.length, + unverifiableConditions, groupName: this.groupName, }; } diff --git a/dev-infra/pullapprove/logging.ts b/dev-infra/pullapprove/logging.ts index ea289b7739be..573516e23e73 100644 --- a/dev-infra/pullapprove/logging.ts +++ b/dev-infra/pullapprove/logging.ts @@ -9,14 +9,23 @@ import {info} from '../utils/console'; import {PullApproveGroupResult} from './group'; +type ConditionGrouping = keyof Pick< + PullApproveGroupResult, 'matchedConditions'|'unmatchedConditions'|'unverifiableConditions'>; + /** Create logs for each pullapprove group result. */ -export function logGroup(group: PullApproveGroupResult, matched = true, printMessageFn = info) { - const conditions = matched ? group.matchedConditions : group.unmatchedConditions; +export function logGroup( + group: PullApproveGroupResult, conditionsToPrint: ConditionGrouping, printMessageFn = info) { + const conditions = group[conditionsToPrint]; printMessageFn.group(`[${group.groupName}]`); if (conditions.length) { - conditions.forEach(matcher => { - const count = matcher.matchedFiles.size; - printMessageFn(`${count} ${count === 1 ? 'match' : 'matches'} - ${matcher.expression}`); + conditions.forEach(groupCondition => { + const count = groupCondition.matchedFiles.size; + if (conditionsToPrint === 'unverifiableConditions') { + printMessageFn(`${groupCondition.expression}`); + } else { + printMessageFn( + `${count} ${count === 1 ? 'match' : 'matches'} - ${groupCondition.expression}`); + } }); printMessageFn.groupEnd(); } diff --git a/dev-infra/pullapprove/verify.ts b/dev-infra/pullapprove/verify.ts index d8302c2caa00..167408338328 100644 --- a/dev-infra/pullapprove/verify.ts +++ b/dev-infra/pullapprove/verify.ts @@ -84,11 +84,16 @@ export function verify() { info.groupEnd(); const matchedGroups = resultsByGroup.filter(group => !group.unmatchedCount); info.group(`Matched conditions by Group (${matchedGroups.length} groups)`); - matchedGroups.forEach(group => logGroup(group, true, debug)); + matchedGroups.forEach(group => logGroup(group, 'matchedConditions', debug)); info.groupEnd(); const unmatchedGroups = resultsByGroup.filter(group => group.unmatchedCount); info.group(`Unmatched conditions by Group (${unmatchedGroups.length} groups)`); - unmatchedGroups.forEach(group => logGroup(group, false)); + unmatchedGroups.forEach(group => logGroup(group, 'unmatchedConditions')); + info.groupEnd(); + const unverifiableConditionsInGroups = + resultsByGroup.filter(group => group.unverifiableConditions.length > 0); + info.group(`Unverifiable conditions by Group (${unverifiableConditionsInGroups.length} groups)`); + unverifiableConditionsInGroups.forEach(group => logGroup(group, 'unverifiableConditions')); info.groupEnd(); // Provide correct exit code based on verification success. From e565d97bc8027ff058d61b0bef38db6dd18c21f3 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Fri, 24 Jul 2020 15:41:44 -0700 Subject: [PATCH 053/253] refactor(router): extract Router config utils to a separate file (#38229) This commit refactors Router package to move config utils to a separate file for better organization and to resolve the problem with circular dependency issue. Resolves #38212. PR Close #38229 --- packages/router/src/config.ts | 106 ------------------ packages/router/src/router.ts | 3 +- packages/router/src/router_config_loader.ts | 3 +- packages/router/src/utils/config.ts | 115 ++++++++++++++++++++ packages/router/test/config.spec.ts | 2 +- 5 files changed, 120 insertions(+), 109 deletions(-) create mode 100644 packages/router/src/utils/config.ts diff --git a/packages/router/src/config.ts b/packages/router/src/config.ts index 8b6f2ab078d7..044cdcd7965e 100644 --- a/packages/router/src/config.ts +++ b/packages/router/src/config.ts @@ -9,9 +9,7 @@ import {NgModuleFactory, NgModuleRef, Type} from '@angular/core'; import {Observable} from 'rxjs'; -import {EmptyOutletComponent} from './components/empty_outlet'; import {ActivatedRouteSnapshot} from './router_state'; -import {PRIMARY_OUTLET} from './shared'; import {UrlSegment, UrlSegmentGroup} from './url_tree'; @@ -490,107 +488,3 @@ export interface Route { export class LoadedRouterConfig { constructor(public routes: Route[], public module: NgModuleRef) {} } - -export function validateConfig(config: Routes, parentPath: string = ''): void { - // forEach doesn't iterate undefined values - for (let i = 0; i < config.length; i++) { - const route: Route = config[i]; - const fullPath: string = getFullPath(parentPath, route); - validateNode(route, fullPath); - } -} - -function validateNode(route: Route, fullPath: string): void { - if (!route) { - throw new Error(` - Invalid configuration of route '${fullPath}': Encountered undefined route. - The reason might be an extra comma. - - Example: - const routes: Routes = [ - { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, - { path: 'dashboard', component: DashboardComponent },, << two commas - { path: 'detail/:id', component: HeroDetailComponent } - ]; - `); - } - if (Array.isArray(route)) { - throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`); - } - if (!route.component && !route.children && !route.loadChildren && - (route.outlet && route.outlet !== PRIMARY_OUTLET)) { - throw new Error(`Invalid configuration of route '${ - fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`); - } - if (route.redirectTo && route.children) { - throw new Error(`Invalid configuration of route '${ - fullPath}': redirectTo and children cannot be used together`); - } - if (route.redirectTo && route.loadChildren) { - throw new Error(`Invalid configuration of route '${ - fullPath}': redirectTo and loadChildren cannot be used together`); - } - if (route.children && route.loadChildren) { - throw new Error(`Invalid configuration of route '${ - fullPath}': children and loadChildren cannot be used together`); - } - if (route.redirectTo && route.component) { - throw new Error(`Invalid configuration of route '${ - fullPath}': redirectTo and component cannot be used together`); - } - if (route.path && route.matcher) { - throw new Error( - `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`); - } - if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) { - throw new Error(`Invalid configuration of route '${ - fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`); - } - if (route.path === void 0 && route.matcher === void 0) { - throw new Error(`Invalid configuration of route '${ - fullPath}': routes must have either a path or a matcher specified`); - } - if (typeof route.path === 'string' && route.path.charAt(0) === '/') { - throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`); - } - if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) { - const exp = - `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`; - throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${ - route.redirectTo}"}': please provide 'pathMatch'. ${exp}`); - } - if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') { - throw new Error(`Invalid configuration of route '${ - fullPath}': pathMatch can only be set to 'prefix' or 'full'`); - } - if (route.children) { - validateConfig(route.children, fullPath); - } -} - -function getFullPath(parentPath: string, currentRoute: Route): string { - if (!currentRoute) { - return parentPath; - } - if (!parentPath && !currentRoute.path) { - return ''; - } else if (parentPath && !currentRoute.path) { - return `${parentPath}/`; - } else if (!parentPath && currentRoute.path) { - return currentRoute.path; - } else { - return `${parentPath}/${currentRoute.path}`; - } -} - -/** - * Makes a copy of the config and adds any default required properties. - */ -export function standardizeConfig(r: Route): Route { - const children = r.children && r.children.map(standardizeConfig); - const c = children ? {...r, children} : {...r}; - if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) { - c.component = EmptyOutletComponent; - } - return c; -} diff --git a/packages/router/src/router.ts b/packages/router/src/router.ts index 7809e17892d5..83b915fa3c89 100644 --- a/packages/router/src/router.ts +++ b/packages/router/src/router.ts @@ -11,7 +11,7 @@ import {Compiler, Injectable, Injector, isDevMode, NgModuleFactoryLoader, NgModu import {BehaviorSubject, EMPTY, Observable, of, Subject, SubscriptionLike} from 'rxjs'; import {catchError, filter, finalize, map, switchMap, tap} from 'rxjs/operators'; -import {QueryParamsHandling, Route, Routes, standardizeConfig, validateConfig} from './config'; +import {QueryParamsHandling, Route, Routes} from './config'; import {createRouterState} from './create_router_state'; import {createUrlTree} from './create_url_tree'; import {Event, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationEnd, NavigationError, NavigationStart, NavigationTrigger, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized} from './events'; @@ -28,6 +28,7 @@ import {ActivatedRoute, createEmptyState, RouterState, RouterStateSnapshot} from import {isNavigationCancelingError, navigationCancelingError, Params} from './shared'; import {DefaultUrlHandlingStrategy, UrlHandlingStrategy} from './url_handling_strategy'; import {containsTree, createEmptyUrlTree, UrlSerializer, UrlTree} from './url_tree'; +import {standardizeConfig, validateConfig} from './utils/config'; import {Checks, getAllRouteGuards} from './utils/preactivation'; import {isUrlTree} from './utils/type_guards'; diff --git a/packages/router/src/router_config_loader.ts b/packages/router/src/router_config_loader.ts index d9c014f3459e..4f2bda69759c 100644 --- a/packages/router/src/router_config_loader.ts +++ b/packages/router/src/router_config_loader.ts @@ -10,8 +10,9 @@ import {Compiler, InjectionToken, Injector, NgModuleFactory, NgModuleFactoryLoad import {from, Observable, of} from 'rxjs'; import {map, mergeMap} from 'rxjs/operators'; -import {LoadChildren, LoadedRouterConfig, Route, standardizeConfig} from './config'; +import {LoadChildren, LoadedRouterConfig, Route} from './config'; import {flatten, wrapIntoObservable} from './utils/collection'; +import {standardizeConfig} from './utils/config'; /** * The [DI token](guide/glossary/#di-token) for a router configuration. diff --git a/packages/router/src/utils/config.ts b/packages/router/src/utils/config.ts new file mode 100644 index 000000000000..961ee3c54fe2 --- /dev/null +++ b/packages/router/src/utils/config.ts @@ -0,0 +1,115 @@ +/** + * @license + * Copyright Google LLC 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://angular.io/license + */ + +import {EmptyOutletComponent} from '../components/empty_outlet'; +import {Route, Routes} from '../config'; +import {PRIMARY_OUTLET} from '../shared'; + +export function validateConfig(config: Routes, parentPath: string = ''): void { + // forEach doesn't iterate undefined values + for (let i = 0; i < config.length; i++) { + const route: Route = config[i]; + const fullPath: string = getFullPath(parentPath, route); + validateNode(route, fullPath); + } +} + +function validateNode(route: Route, fullPath: string): void { + if (!route) { + throw new Error(` + Invalid configuration of route '${fullPath}': Encountered undefined route. + The reason might be an extra comma. + + Example: + const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: DashboardComponent },, << two commas + { path: 'detail/:id', component: HeroDetailComponent } + ]; + `); + } + if (Array.isArray(route)) { + throw new Error(`Invalid configuration of route '${fullPath}': Array cannot be specified`); + } + if (!route.component && !route.children && !route.loadChildren && + (route.outlet && route.outlet !== PRIMARY_OUTLET)) { + throw new Error(`Invalid configuration of route '${ + fullPath}': a componentless route without children or loadChildren cannot have a named outlet set`); + } + if (route.redirectTo && route.children) { + throw new Error(`Invalid configuration of route '${ + fullPath}': redirectTo and children cannot be used together`); + } + if (route.redirectTo && route.loadChildren) { + throw new Error(`Invalid configuration of route '${ + fullPath}': redirectTo and loadChildren cannot be used together`); + } + if (route.children && route.loadChildren) { + throw new Error(`Invalid configuration of route '${ + fullPath}': children and loadChildren cannot be used together`); + } + if (route.redirectTo && route.component) { + throw new Error(`Invalid configuration of route '${ + fullPath}': redirectTo and component cannot be used together`); + } + if (route.path && route.matcher) { + throw new Error( + `Invalid configuration of route '${fullPath}': path and matcher cannot be used together`); + } + if (route.redirectTo === void 0 && !route.component && !route.children && !route.loadChildren) { + throw new Error(`Invalid configuration of route '${ + fullPath}'. One of the following must be provided: component, redirectTo, children or loadChildren`); + } + if (route.path === void 0 && route.matcher === void 0) { + throw new Error(`Invalid configuration of route '${ + fullPath}': routes must have either a path or a matcher specified`); + } + if (typeof route.path === 'string' && route.path.charAt(0) === '/') { + throw new Error(`Invalid configuration of route '${fullPath}': path cannot start with a slash`); + } + if (route.path === '' && route.redirectTo !== void 0 && route.pathMatch === void 0) { + const exp = + `The default value of 'pathMatch' is 'prefix', but often the intent is to use 'full'.`; + throw new Error(`Invalid configuration of route '{path: "${fullPath}", redirectTo: "${ + route.redirectTo}"}': please provide 'pathMatch'. ${exp}`); + } + if (route.pathMatch !== void 0 && route.pathMatch !== 'full' && route.pathMatch !== 'prefix') { + throw new Error(`Invalid configuration of route '${ + fullPath}': pathMatch can only be set to 'prefix' or 'full'`); + } + if (route.children) { + validateConfig(route.children, fullPath); + } +} + +function getFullPath(parentPath: string, currentRoute: Route): string { + if (!currentRoute) { + return parentPath; + } + if (!parentPath && !currentRoute.path) { + return ''; + } else if (parentPath && !currentRoute.path) { + return `${parentPath}/`; + } else if (!parentPath && currentRoute.path) { + return currentRoute.path; + } else { + return `${parentPath}/${currentRoute.path}`; + } +} + +/** + * Makes a copy of the config and adds any default required properties. + */ +export function standardizeConfig(r: Route): Route { + const children = r.children && r.children.map(standardizeConfig); + const c = children ? {...r, children} : {...r}; + if (!c.component && (children || c.loadChildren) && (c.outlet && c.outlet !== PRIMARY_OUTLET)) { + c.component = EmptyOutletComponent; + } + return c; +} diff --git a/packages/router/test/config.spec.ts b/packages/router/test/config.spec.ts index fb4bb03d1ec9..76d32f3f5a19 100644 --- a/packages/router/test/config.spec.ts +++ b/packages/router/test/config.spec.ts @@ -6,8 +6,8 @@ * found in the LICENSE file at https://angular.io/license */ -import {validateConfig} from '../src/config'; import {PRIMARY_OUTLET} from '../src/shared'; +import {validateConfig} from '../src/utils/config'; describe('config', () => { describe('validateConfig', () => { From 03e02185d9c733205fd821de567b1474ddc99fb1 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Thu, 23 Jul 2020 15:53:53 +0200 Subject: [PATCH 054/253] docs: add ng-add save option (#38198) PR Close #38198 --- .../projects/my-lib/package.json | 11 +++++++++-- aio/content/guide/schematics-for-libraries.md | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json b/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json index 3607e2c0cef9..a53579e4ddd0 100644 --- a/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json +++ b/aio/content/examples/schematics-for-libraries/projects/my-lib/package.json @@ -16,5 +16,12 @@ "@angular/core": "^7.2.0" }, // #docregion collection - "schematics": "./schematics/collection.json" -} \ No newline at end of file + "schematics": "./schematics/collection.json", +// #enddocregion collection +// #docregion ng-add + "ng-add": { + "save": "devDependencies" + } +// #enddocregion ng-add +// #docregion collection +} diff --git a/aio/content/guide/schematics-for-libraries.md b/aio/content/guide/schematics-for-libraries.md index 1590c4ea871a..e2520c5520b8 100644 --- a/aio/content/guide/schematics-for-libraries.md +++ b/aio/content/guide/schematics-for-libraries.md @@ -57,6 +57,20 @@ The task uses the user's preferred package manager to add the library to the pro In this example, the function receives the current `Tree` and returns it without any modifications. If you need to, you can do additional setup when your package is installed, such as generating files, updating configuration, or any other initial setup your library requires. +### Define dependency type + +Use the `save` option of `ng-add` to configure if the library should be added to the `dependencies`, the `devDepedencies`, or not saved at all in the project's `package.json` configuration file. + + + + +Possible values are: + + * `false` - Don't add the package to package.json + * `true` - Add the package to the dependencies + * `"dependencies"` - Add the package to the dependencies + * `"devDependencies"` - Add the package to the devDependencies + ## Building your schematics To bundle your schematics together with your library, you must configure the library to build the schematics separately, then add them to the bundle. From 47873a339aa54c9abf00cc5385fbc5c1e95c036f Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Thu, 23 Jul 2020 18:43:04 -0700 Subject: [PATCH 055/253] refactor(compiler): separate compilation and transform phases (#38213) This commit splits the transformation into 2 separate steps: Ivy compilation and actual transformation of corresponding TS nodes. This is needed to have all `o.Expression`s generated before any TS transforms happen. This allows `ConstantPool` to properly identify expressions that can be shared across multiple components declared in the same file. Resolves #38203. PR Close #38213 --- .../src/ngtsc/transform/src/transform.ts | 157 +++++++++++------- 1 file changed, 99 insertions(+), 58 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/transform/src/transform.ts b/packages/compiler-cli/src/ngtsc/transform/src/transform.ts index 53ad1e037816..c587ebcc1525 100644 --- a/packages/compiler-cli/src/ngtsc/transform/src/transform.ts +++ b/packages/compiler-cli/src/ngtsc/transform/src/transform.ts @@ -14,6 +14,7 @@ import {Decorator, ReflectionHost} from '../../reflection'; import {ImportManager, translateExpression, translateStatement} from '../../translator'; import {visit, VisitListEntryResult, Visitor} from '../../util/src/visitor'; +import {CompileResult} from './api'; import {TraitCompiler} from './compilation'; import {addImports} from './utils'; @@ -43,12 +44,15 @@ export function ivyTransformFactory( }; } -class IvyVisitor extends Visitor { - constructor( - private compilation: TraitCompiler, private reflector: ReflectionHost, - private importManager: ImportManager, private defaultImportRecorder: DefaultImportRecorder, - private isClosureCompilerEnabled: boolean, private isCore: boolean, - private constantPool: ConstantPool) { +/** + * Visits all classes, performs Ivy compilation where Angular decorators are present and collects + * result in a Map that associates a ts.ClassDeclaration with Ivy compilation results. This visitor + * does NOT perform any TS transformations. + */ +class IvyCompilationVisitor extends Visitor { + public classCompilationMap = new Map(); + + constructor(private compilation: TraitCompiler, private constantPool: ConstantPool) { super(); } @@ -56,56 +60,78 @@ class IvyVisitor extends Visitor { VisitListEntryResult { // Determine if this class has an Ivy field that needs to be added, and compile the field // to an expression if so. - const res = this.compilation.compile(node, this.constantPool); - - if (res !== null) { - // There is at least one field to add. - const statements: ts.Statement[] = []; - const members = [...node.members]; - - res.forEach(field => { - // Translate the initializer for the field into TS nodes. - const exprNode = translateExpression( - field.initializer, this.importManager, this.defaultImportRecorder, - ts.ScriptTarget.ES2015); - - // Create a static property declaration for the new field. - const property = ts.createProperty( - undefined, [ts.createToken(ts.SyntaxKind.StaticKeyword)], field.name, undefined, - undefined, exprNode); - - if (this.isClosureCompilerEnabled) { - // Closure compiler transforms the form `Service.ɵprov = X` into `Service$ɵprov = X`. To - // prevent this transformation, such assignments need to be annotated with @nocollapse. - // Note that tsickle is typically responsible for adding such annotations, however it - // doesn't yet handle synthetic fields added during other transformations. - ts.addSyntheticLeadingComment( - property, ts.SyntaxKind.MultiLineCommentTrivia, '* @nocollapse ', - /* hasTrailingNewLine */ false); - } - - field.statements - .map( - stmt => translateStatement( - stmt, this.importManager, this.defaultImportRecorder, ts.ScriptTarget.ES2015)) - .forEach(stmt => statements.push(stmt)); - - members.push(property); - }); - - // Replace the class declaration with an updated version. - node = ts.updateClassDeclaration( - node, - // Remove the decorator which triggered this compilation, leaving the others alone. - maybeFilterDecorator(node.decorators, this.compilation.decoratorsFor(node)), - node.modifiers, node.name, node.typeParameters, node.heritageClauses || [], - // Map over the class members and remove any Angular decorators from them. - members.map(member => this._stripAngularDecorators(member))); - return {node, after: statements}; + const result = this.compilation.compile(node, this.constantPool); + if (result !== null) { + this.classCompilationMap.set(node, result); } - return {node}; } +} + +/** + * Visits all classes and performs transformation of corresponding TS nodes based on the Ivy + * compilation results (provided as an argument). + */ +class IvyTransformationVisitor extends Visitor { + constructor( + private compilation: TraitCompiler, + private classCompilationMap: Map, + private reflector: ReflectionHost, private importManager: ImportManager, + private defaultImportRecorder: DefaultImportRecorder, + private isClosureCompilerEnabled: boolean, private isCore: boolean) { + super(); + } + + visitClassDeclaration(node: ts.ClassDeclaration): + VisitListEntryResult { + // If this class is not registered in the map, it means that it doesn't have Angular decorators, + // thus no further processing is required. + if (!this.classCompilationMap.has(node)) return {node}; + + // There is at least one field to add. + const statements: ts.Statement[] = []; + const members = [...node.members]; + + this.classCompilationMap.get(node)!.forEach(field => { + // Translate the initializer for the field into TS nodes. + const exprNode = translateExpression( + field.initializer, this.importManager, this.defaultImportRecorder, + ts.ScriptTarget.ES2015); + + // Create a static property declaration for the new field. + const property = ts.createProperty( + undefined, [ts.createToken(ts.SyntaxKind.StaticKeyword)], field.name, undefined, + undefined, exprNode); + + if (this.isClosureCompilerEnabled) { + // Closure compiler transforms the form `Service.ɵprov = X` into `Service$ɵprov = X`. To + // prevent this transformation, such assignments need to be annotated with @nocollapse. + // Note that tsickle is typically responsible for adding such annotations, however it + // doesn't yet handle synthetic fields added during other transformations. + ts.addSyntheticLeadingComment( + property, ts.SyntaxKind.MultiLineCommentTrivia, '* @nocollapse ', + /* hasTrailingNewLine */ false); + } + + field.statements + .map( + stmt => translateStatement( + stmt, this.importManager, this.defaultImportRecorder, ts.ScriptTarget.ES2015)) + .forEach(stmt => statements.push(stmt)); + + members.push(property); + }); + + // Replace the class declaration with an updated version. + node = ts.updateClassDeclaration( + node, + // Remove the decorator which triggered this compilation, leaving the others alone. + maybeFilterDecorator(node.decorators, this.compilation.decoratorsFor(node)), node.modifiers, + node.name, node.typeParameters, node.heritageClauses || [], + // Map over the class members and remove any Angular decorators from them. + members.map(member => this._stripAngularDecorators(member))); + return {node, after: statements}; + } /** * Return all decorators on a `Declaration` which are from @angular/core, or an empty set if none @@ -224,11 +250,26 @@ function transformIvySourceFile( const constantPool = new ConstantPool(); const importManager = new ImportManager(importRewriter); - // Recursively scan through the AST and perform any updates requested by the IvyCompilation. - const visitor = new IvyVisitor( - compilation, reflector, importManager, defaultImportRecorder, isClosureCompilerEnabled, - isCore, constantPool); - let sf = visit(file, visitor, context); + // The transformation process consists of 2 steps: + // + // 1. Visit all classes, perform compilation and collect the results. + // 2. Perform actual transformation of required TS nodes using compilation results from the first + // step. + // + // This is needed to have all `o.Expression`s generated before any TS transforms happen. This + // allows `ConstantPool` to properly identify expressions that can be shared across multiple + // components declared in the same file. + + // Step 1. Go though all classes in AST, perform compilation and collect the results. + const compilationVisitor = new IvyCompilationVisitor(compilation, constantPool); + visit(file, compilationVisitor, context); + + // Step 2. Scan through the AST again and perform transformations based on Ivy compilation + // results obtained at Step 1. + const transformationVisitor = new IvyTransformationVisitor( + compilation, compilationVisitor.classCompilationMap, reflector, importManager, + defaultImportRecorder, isClosureCompilerEnabled, isCore); + let sf = visit(file, transformationVisitor, context); // Generate the constant statements first, as they may involve adding additional imports // to the ImportManager. From 4f842e23df1e426c2aeb3562c712ac8e503ef14a Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Thu, 23 Jul 2020 18:47:33 -0700 Subject: [PATCH 056/253] refactor(compiler): allow strings with certain length to be included into `ConstantPool` (#38213) Prior to this commit, the `ConstantPool` ignored all primitive values. It turned out that it's beneficial to include strings above certain length to the pool as well. This commit updates the `ConstantPool` logic to allow such strings to be shared across multiple instances if needed. For instance, this is helpful for component styles that might be reused across multiple components in the same file. PR Close #38213 --- packages/compiler/src/constant_pool.ts | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/compiler/src/constant_pool.ts b/packages/compiler/src/constant_pool.ts index 5ab77da0ade6..24e800c95d15 100644 --- a/packages/compiler/src/constant_pool.ts +++ b/packages/compiler/src/constant_pool.ts @@ -36,6 +36,13 @@ export const enum DefinitionKind { */ const KEY_CONTEXT = {}; +/** + * Generally all primitive values are excluded from the `ConstantPool`, but there is an exclusion + * for strings that reach a certain length threshold. This constant defines the length threshold for + * strings. + */ +const POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS = 50; + /** * A node that is a place-holder that allows the node to be replaced when the actual * node is known. @@ -96,7 +103,8 @@ export class ConstantPool { private nextNameIndex = 0; getConstLiteral(literal: o.Expression, forceShared?: boolean): o.Expression { - if (literal instanceof o.LiteralExpr || literal instanceof FixupExpression) { + if ((literal instanceof o.LiteralExpr && !isLongStringExpr(literal)) || + literal instanceof FixupExpression) { // Do no put simple literals into the constant pool or try to produce a constant for a // reference to a constant. return literal; @@ -305,3 +313,8 @@ function invalid(this: o.ExpressionVisitor, arg: o.Expression|o.Statement): n function isVariable(e: o.Expression): e is o.ReadVarExpr { return e instanceof o.ReadVarExpr; } + +function isLongStringExpr(expr: o.LiteralExpr): boolean { + return typeof expr.value === 'string' && + expr.value.length > POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS; +} \ No newline at end of file From 6881149540dcc1dec2a3e2b47c1618f8e768b145 Mon Sep 17 00:00:00 2001 From: Andrew Kushnir Date: Thu, 23 Jul 2020 18:51:55 -0700 Subject: [PATCH 057/253] fix(compiler): share identical stylesheets between components in the same file (#38213) Prior to this commit, duplicated styles defined in multiple components in the same file were not shared between components, thus causing extra payload size. This commit updates compiler logic to use `ConstantPool` for the styles (while generating the `styles` array on component def), which enables styles sharing when needed (when duplicates styles are present). Resolves #38204. PR Close #38213 --- goldens/size-tracking/aio-payloads.json | 2 +- .../src/ngtsc/transform/src/transform.ts | 8 ++- .../compiler-cli/test/ngtsc/ngtsc_spec.ts | 62 +++++++++++++++++++ packages/compiler/src/constant_pool.ts | 2 +- .../compiler/src/render3/view/compiler.ts | 2 +- 5 files changed, 70 insertions(+), 6 deletions(-) diff --git a/goldens/size-tracking/aio-payloads.json b/goldens/size-tracking/aio-payloads.json index 9d240aea2fcb..b91c2891d62d 100755 --- a/goldens/size-tracking/aio-payloads.json +++ b/goldens/size-tracking/aio-payloads.json @@ -12,7 +12,7 @@ "master": { "uncompressed": { "runtime-es2015": 2987, - "main-es2015": 450596, + "main-es2015": 448419, "polyfills-es2015": 52630 } } diff --git a/packages/compiler-cli/src/ngtsc/transform/src/transform.ts b/packages/compiler-cli/src/ngtsc/transform/src/transform.ts index c587ebcc1525..99933680d06b 100644 --- a/packages/compiler-cli/src/ngtsc/transform/src/transform.ts +++ b/packages/compiler-cli/src/ngtsc/transform/src/transform.ts @@ -86,13 +86,15 @@ class IvyTransformationVisitor extends Visitor { VisitListEntryResult { // If this class is not registered in the map, it means that it doesn't have Angular decorators, // thus no further processing is required. - if (!this.classCompilationMap.has(node)) return {node}; + if (!this.classCompilationMap.has(node)) { + return {node}; + } // There is at least one field to add. const statements: ts.Statement[] = []; const members = [...node.members]; - this.classCompilationMap.get(node)!.forEach(field => { + for (const field of this.classCompilationMap.get(node)!) { // Translate the initializer for the field into TS nodes. const exprNode = translateExpression( field.initializer, this.importManager, this.defaultImportRecorder, @@ -120,7 +122,7 @@ class IvyTransformationVisitor extends Visitor { .forEach(stmt => statements.push(stmt)); members.push(property); - }); + } // Replace the class declaration with an updated version. node = ts.updateClassDeclaration( diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 9ad1a3a6786c..e5fac6559cb5 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -6623,6 +6623,68 @@ export const Foo = Foo__PRE_R3__; const jsContents = env.getContents('test.js'); expect(jsContents).toContain('styles: ["h1[_ngcontent-%COMP%] {font-size: larger}"]'); }); + + it('should share same styles declared in different components in the same file', () => { + env.write('test.ts', ` + import {Component} from '@angular/core'; + + @Component({ + selector: 'comp-a', + template: 'Comp A', + styles: [ + 'span { font-size: larger; }', + 'div { background: url(/some-very-very-long-path.png); }', + 'img { background: url(/a/some-very-very-long-path.png); }' + ] + }) + export class CompA {} + + @Component({ + selector: 'comp-b', + template: 'Comp B', + styles: [ + 'span { font-size: larger; }', + 'div { background: url(/some-very-very-long-path.png); }', + 'img { background: url(/b/some-very-very-long-path.png); }' + ] + }) + export class CompB {} + `); + + env.driveMain(); + const jsContents = env.getContents('test.js'); + + // Verify that long styles present in both components are extracted to a separate var. + expect(jsContents) + .toContain( + '_c0 = "div[_ngcontent-%COMP%] { background: url(/some-very-very-long-path.png); }";'); + + expect(jsContents) + .toContain( + 'styles: [' + + // This style is present in both components, but was not extracted into a separate + // var since it doesn't reach length threshold (50 chars) in `ConstantPool`. + '"span[_ngcontent-%COMP%] { font-size: larger; }", ' + + // Style that is present in both components, but reaches length threshold - + // extracted to a separate var. + '_c0, ' + + // Style that is unique to this component, but that reaches length threshold - + // remains a string in the `styles` array. + '"img[_ngcontent-%COMP%] { background: url(/a/some-very-very-long-path.png); }"]'); + + expect(jsContents) + .toContain( + 'styles: [' + + // This style is present in both components, but was not extracted into a separate + // var since it doesn't reach length threshold (50 chars) in `ConstantPool`. + '"span[_ngcontent-%COMP%] { font-size: larger; }", ' + + // Style that is present in both components, but reaches length threshold - + // extracted to a separate var. + '_c0, ' + + // Style that is unique to this component, but that reaches length threshold - + // remains a string in the `styles` array. + '"img[_ngcontent-%COMP%] { background: url(/b/some-very-very-long-path.png); }"]'); + }); }); describe('non-exported classes', () => { diff --git a/packages/compiler/src/constant_pool.ts b/packages/compiler/src/constant_pool.ts index 24e800c95d15..b083a2c1edea 100644 --- a/packages/compiler/src/constant_pool.ts +++ b/packages/compiler/src/constant_pool.ts @@ -316,5 +316,5 @@ function isVariable(e: o.Expression): e is o.ReadVarExpr { function isLongStringExpr(expr: o.LiteralExpr): boolean { return typeof expr.value === 'string' && - expr.value.length > POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS; + expr.value.length >= POOL_INCLUSION_LENGTH_THRESHOLD_FOR_STRINGS; } \ No newline at end of file diff --git a/packages/compiler/src/render3/view/compiler.ts b/packages/compiler/src/render3/view/compiler.ts index f0c305fe1903..7adf55fb4389 100644 --- a/packages/compiler/src/render3/view/compiler.ts +++ b/packages/compiler/src/render3/view/compiler.ts @@ -231,7 +231,7 @@ export function compileComponentFromMetadata( const styleValues = meta.encapsulation == core.ViewEncapsulation.Emulated ? compileStyles(meta.styles, CONTENT_ATTR, HOST_ATTR) : meta.styles; - const strings = styleValues.map(str => o.literal(str)); + const strings = styleValues.map(str => constantPool.getConstLiteral(o.literal(str))); definitionMap.set('styles', o.literalArr(strings)); } else if (meta.encapsulation === core.ViewEncapsulation.Emulated) { // If there is no style, don't generate css selectors on elements From a57119761bee503d440bb57efc8557b2bc194f14 Mon Sep 17 00:00:00 2001 From: Changyu Geng Date: Tue, 7 Jul 2020 09:15:44 +0800 Subject: [PATCH 058/253] docs: clarify the description of pipes (#37950) This commit clarifies some of the language regarding pipes in the pipes guide. This commit also specifies the term transforming rather than formatting. PR Close #37950 --- aio/content/guide/pipes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/aio/content/guide/pipes.md b/aio/content/guide/pipes.md index a28f0dd6468f..0d28ab4aa462 100644 --- a/aio/content/guide/pipes.md +++ b/aio/content/guide/pipes.md @@ -1,7 +1,7 @@ # Transforming Data Using Pipes -Use [pipes](guide/glossary#pipe "Definition of a pipe") to transform and format strings, currency amounts, dates, and other display data. -Pipes are simple functions you can use in [template expressions](/guide/glossary#template-expression "Definition of template expression") to accept an input value and return a transformed value. +Use [pipes](guide/glossary#pipe "Definition of a pipe") to transform strings, currency amounts, dates, and other data for display. +Pipes are simple functions you can use in [template expressions](/guide/glossary#template-expression "Definition of template expression") to accept an input value and return a transformed value. Pipes are useful because you can use them throughout your application, while only declaring each pipe once. For example, you would use a pipe to show a date as **April 15, 1988** rather than the raw string format.
@@ -63,7 +63,7 @@ function. {@a parameterizing-a-pipe} -## Formatting data with parameters and chained pipes +## Transforming data with parameters and chained pipes Use optional parameters to fine-tune a pipe's output. For example, you can use the [`CurrencyPipe`](api/common/CurrencyPipe "API reference") with a country code such as EUR as a parameter. From 686f9ae4b2dde82601c677c49a56ef62258a7368 Mon Sep 17 00:00:00 2001 From: Omar Hasan Date: Sun, 26 Jul 2020 17:12:36 +0200 Subject: [PATCH 059/253] docs: fix breaking URL for RxJS marble testing (#38209) When checking this URL for the `RxJS marble testing` Ive found it pointing to `Page not found` PR Close #38209 --- aio/content/guide/testing-components-scenarios.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aio/content/guide/testing-components-scenarios.md b/aio/content/guide/testing-components-scenarios.md index cdd66ad27e6d..7ddb1af0979f 100644 --- a/aio/content/guide/testing-components-scenarios.md +++ b/aio/content/guide/testing-components-scenarios.md @@ -779,7 +779,7 @@ which reports router activity, is a _hot_ observable. RxJS marble testing is a rich subject, beyond the scope of this guide. Learn about it on the web, starting with the -[official documentation](https://github.com/ReactiveX/rxjs/blob/master/doc/writing-marble-tests.md). +[official documentation](https://rxjs.dev/guide/testing/marble-testing).
From 28ef4bc44194808bf0799837258c844f09f93187 Mon Sep 17 00:00:00 2001 From: Kapunahele Wong Date: Tue, 9 Jun 2020 14:33:02 -0400 Subject: [PATCH 060/253] docs: add template ref var to glossary (#36743) There is not an entry in the glossary for template reference variable. To clarify for site visitors, we are adding one here. PR Close #36743 --- aio/content/guide/glossary.md | 13 +++++++++++++ aio/content/guide/template-reference-variables.md | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/aio/content/guide/glossary.md b/aio/content/guide/glossary.md index 38b9a732073c..e2ad149975b2 100644 --- a/aio/content/guide/glossary.md +++ b/aio/content/guide/glossary.md @@ -939,6 +939,19 @@ A TypeScript-like syntax that Angular evaluates within a [data binding](#data-bi Read about how to write template expressions in the [template expressions](guide/interpolation#template-expressions) section of the [Interpolation](guide/interpolation) guide. +{@a template-reference-variable} + +## template reference variable + +A variable defined in a template that references an instance associated with an element, such as a directive instance, component instance, template as in `TemplateRef`, or DOM element. +After declaring a template reference variable on an element in a template, +you can access values from that variable elsewhere within the same template. +The following example defines a template reference variable named `#phone`. + + + +For more information, see the [Template reference variable](guide/template-reference-variables) guide. + {@a token} ## token diff --git a/aio/content/guide/template-reference-variables.md b/aio/content/guide/template-reference-variables.md index 144bbfcf1e40..1f3fd5db2844 100644 --- a/aio/content/guide/template-reference-variables.md +++ b/aio/content/guide/template-reference-variables.md @@ -19,6 +19,13 @@ Here, a ` `, - host: { - '[@state]': 'state', - }, animations: [ trigger('state', [ state('opened', style({transform: 'translateY(0%)'})), @@ -41,6 +38,7 @@ import { animate, state, style, transition, trigger } from '@angular/animations' `] }) export class PopupComponent { + @HostBinding('@state') state: 'opened' | 'closed' = 'closed'; @Input() diff --git a/aio/content/examples/event-binding/src/app/click.directive.ts b/aio/content/examples/event-binding/src/app/click.directive.ts index 4e9e9085b17e..a04863fac81e 100644 --- a/aio/content/examples/event-binding/src/app/click.directive.ts +++ b/aio/content/examples/event-binding/src/app/click.directive.ts @@ -1,4 +1,4 @@ -/* tslint:disable use-output-property-decorator directive-class-suffix */ +// tslint:disable: directive-selector import { Directive, ElementRef, EventEmitter, Output } from '@angular/core'; @Directive({selector: '[myClick]'}) diff --git a/aio/content/examples/hierarchical-dependency-injection/src/app/hero-tax-return.component.ts b/aio/content/examples/hierarchical-dependency-injection/src/app/hero-tax-return.component.ts index cbca85946a45..9ee6325b2eab 100644 --- a/aio/content/examples/hierarchical-dependency-injection/src/app/hero-tax-return.component.ts +++ b/aio/content/examples/hierarchical-dependency-injection/src/app/hero-tax-return.component.ts @@ -1,3 +1,4 @@ +// tslint:disable: no-output-native // #docregion import { Component, EventEmitter, Input, Output } from '@angular/core'; import { HeroTaxReturn } from './hero'; diff --git a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts index 8eed8bddbd7b..c150bcc21444 100644 --- a/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts +++ b/aio/content/examples/inputs-outputs/src/app/aliasing/aliasing.component.ts @@ -1,9 +1,4 @@ -/* tslint:disable:use-input-property-decorator */ -/* tslint:disable:use-output-property-decorator */ - -/* tslint:disable:no-input-rename */ - - +// tslint:disable: no-input-rename no-output-rename use-input-property-decorator use-output-property-decorator import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ diff --git a/aio/content/examples/lifecycle-hooks/e2e/src/app.e2e-spec.ts b/aio/content/examples/lifecycle-hooks/e2e/src/app.e2e-spec.ts index 8aa8ee9f290e..6ec9eb2e63d9 100644 --- a/aio/content/examples/lifecycle-hooks/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/lifecycle-hooks/e2e/src/app.e2e-spec.ts @@ -135,7 +135,7 @@ describe('Lifecycle hooks', () => { const inputEle = element(by.css('spy-parent input')); const addHeroButtonEle = element(by.cssContainingText('spy-parent button', 'Add Hero')); const resetHeroesButtonEle = element(by.cssContainingText('spy-parent button', 'Reset Heroes')); - const heroEles = element.all(by.css('spy-parent div[mySpy')); + const heroEles = element.all(by.css('spy-parent div[appSpy')); const logEles = element.all(by.css('spy-parent h4 ~ div')); expect(heroEles.count()).toBe(2, 'should have two heroes displayed'); diff --git a/aio/content/examples/lifecycle-hooks/src/app/counter.component.ts b/aio/content/examples/lifecycle-hooks/src/app/counter.component.ts index cddc8471360c..a2d7b5fd9b21 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/counter.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/counter.component.ts @@ -13,7 +13,7 @@ import { LoggerService } from './logger.service'; Counter = {{counter}}
-- Counter Change Log --
-
{{chg}}
+
{{chg}}
`, styles: ['.counter {background: LightYellow; padding: 8px; margin-top: 8px}'] diff --git a/aio/content/examples/lifecycle-hooks/src/app/peek-a-boo.component.ts b/aio/content/examples/lifecycle-hooks/src/app/peek-a-boo.component.ts index a597a5ca73bb..c66e41a6c93e 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/peek-a-boo.component.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/peek-a-boo.component.ts @@ -1,3 +1,5 @@ +// tslint:disable: no-conflicting-lifecycle +// #docregion import { AfterContentChecked, AfterContentInit, diff --git a/aio/content/examples/lifecycle-hooks/src/app/spy.component.html b/aio/content/examples/lifecycle-hooks/src/app/spy.component.html index f7deae9448e8..96ca78194a0f 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/spy.component.html +++ b/aio/content/examples/lifecycle-hooks/src/app/spy.component.html @@ -7,7 +7,7 @@

Spy Directive

-
+
{{hero}}
diff --git a/aio/content/examples/lifecycle-hooks/src/app/spy.directive.ts b/aio/content/examples/lifecycle-hooks/src/app/spy.directive.ts index 01f3f9588061..c14f4e645507 100644 --- a/aio/content/examples/lifecycle-hooks/src/app/spy.directive.ts +++ b/aio/content/examples/lifecycle-hooks/src/app/spy.directive.ts @@ -7,8 +7,8 @@ let nextId = 1; // #docregion spy-directive // Spy on any element to which it is applied. -// Usage:
...
-@Directive({selector: '[mySpy]'}) +// Usage:
...
+@Directive({selector: '[appSpy]'}) export class SpyDirective implements OnInit, OnDestroy { constructor(private logger: LoggerService) { } diff --git a/aio/content/examples/observables-in-angular/src/main.ts b/aio/content/examples/observables-in-angular/src/main.ts index 0ba6e38f5476..0eaca6bc625e 100644 --- a/aio/content/examples/observables-in-angular/src/main.ts +++ b/aio/content/examples/observables-in-angular/src/main.ts @@ -1,11 +1,12 @@ - +// tslint:disable: no-output-native +// #docregion import { Component, Output, OnInit, EventEmitter, NgModule } from '@angular/core'; import { Observable } from 'rxjs'; // #docregion eventemitter @Component({ - selector: 'zippy', + selector: 'app-zippy', template: `
Toggle
diff --git a/aio/content/examples/styleguide/src/02-08/app/shared/input-highlight.directive.ts b/aio/content/examples/styleguide/src/02-08/app/shared/input-highlight.directive.ts index fd747719812b..13f8bc1e9857 100644 --- a/aio/content/examples/styleguide/src/02-08/app/shared/input-highlight.directive.ts +++ b/aio/content/examples/styleguide/src/02-08/app/shared/input-highlight.directive.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion import { Directive, ElementRef } from '@angular/core'; diff --git a/aio/content/examples/styleguide/src/05-13/app/heroes/shared/hero-highlight.directive.ts b/aio/content/examples/styleguide/src/05-13/app/heroes/shared/hero-highlight.directive.ts index 737af31f4fe5..3af48d241e44 100644 --- a/aio/content/examples/styleguide/src/05-13/app/heroes/shared/hero-highlight.directive.ts +++ b/aio/content/examples/styleguide/src/05-13/app/heroes/shared/hero-highlight.directive.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion import { Directive, ElementRef, Input, OnChanges } from '@angular/core'; diff --git a/aio/content/examples/styleguide/src/06-03/app/shared/validator2.directive.ts b/aio/content/examples/styleguide/src/06-03/app/shared/validator2.directive.ts index 05a0f9f07ffd..dc61f4e50484 100644 --- a/aio/content/examples/styleguide/src/06-03/app/shared/validator2.directive.ts +++ b/aio/content/examples/styleguide/src/06-03/app/shared/validator2.directive.ts @@ -1,3 +1,4 @@ +// tslint:disable: no-host-metadata-property // #docregion import { Directive } from '@angular/core'; diff --git a/aio/content/examples/testing/src/app/demo/demo.ts b/aio/content/examples/testing/src/app/demo/demo.ts index e97ccb387c87..5c02167ea361 100644 --- a/aio/content/examples/testing/src/app/demo/demo.ts +++ b/aio/content/examples/testing/src/app/demo/demo.ts @@ -1,4 +1,4 @@ -/* tslint:disable:forin */ +// tslint:disable: directive-selector forin no-input-rename import { Component, ContentChildren, Directive, EventEmitter, Injectable, Input, Output, Optional, HostBinding, HostListener, diff --git a/aio/content/examples/testing/src/app/shared/highlight.directive.ts b/aio/content/examples/testing/src/app/shared/highlight.directive.ts index ce851d70d02e..465c39cd09eb 100644 --- a/aio/content/examples/testing/src/app/shared/highlight.directive.ts +++ b/aio/content/examples/testing/src/app/shared/highlight.directive.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion import { Directive, ElementRef, Input, OnChanges } from '@angular/core'; diff --git a/aio/content/examples/testing/src/testing/router-link-directive-stub.ts b/aio/content/examples/testing/src/testing/router-link-directive-stub.ts index 4da6f8fd04df..ea89f67ab957 100644 --- a/aio/content/examples/testing/src/testing/router-link-directive-stub.ts +++ b/aio/content/examples/testing/src/testing/router-link-directive-stub.ts @@ -3,7 +3,7 @@ import { Directive, Input, HostListener } from '@angular/core'; // export for convenience. export { RouterLink} from '@angular/router'; -/* tslint:disable:directive-class-suffix */ +// tslint:disable: directive-class-suffix directive-selector // #docregion router-link @Directive({ selector: '[routerLink]' diff --git a/aio/content/examples/upgrade-module/src/app/a-to-ajs-transclusion/hero-detail.component.ts b/aio/content/examples/upgrade-module/src/app/a-to-ajs-transclusion/hero-detail.component.ts index 9d467a5411fd..f8292434f290 100644 --- a/aio/content/examples/upgrade-module/src/app/a-to-ajs-transclusion/hero-detail.component.ts +++ b/aio/content/examples/upgrade-module/src/app/a-to-ajs-transclusion/hero-detail.component.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion export const heroDetail = { bindings: { diff --git a/aio/content/examples/upgrade-module/src/app/upgrade-io/hero-detail.component.ts b/aio/content/examples/upgrade-module/src/app/upgrade-io/hero-detail.component.ts index 4d74a1bea147..451507dda816 100644 --- a/aio/content/examples/upgrade-module/src/app/upgrade-io/hero-detail.component.ts +++ b/aio/content/examples/upgrade-module/src/app/upgrade-io/hero-detail.component.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion // #docregion hero-detail-io export const heroDetail = { diff --git a/aio/content/examples/upgrade-module/src/app/upgrade-static/hero-detail.component.ts b/aio/content/examples/upgrade-module/src/app/upgrade-static/hero-detail.component.ts index 959ff16b0137..3b81dc6be277 100644 --- a/aio/content/examples/upgrade-module/src/app/upgrade-static/hero-detail.component.ts +++ b/aio/content/examples/upgrade-module/src/app/upgrade-static/hero-detail.component.ts @@ -1,3 +1,4 @@ +// tslint:disable: directive-selector // #docregion // #docregion hero-detail export const heroDetail = { diff --git a/aio/content/guide/dynamic-component-loader.md b/aio/content/guide/dynamic-component-loader.md index 37a693f43cf1..94ec37fbc47b 100644 --- a/aio/content/guide/dynamic-component-loader.md +++ b/aio/content/guide/dynamic-component-loader.md @@ -42,7 +42,7 @@ mark valid insertion points in the template. `AdDirective` injects `ViewContainerRef` to gain access to the view container of the element that will host the dynamically added component. -In the `@Directive` decorator, notice the selector name, `ad-host`; +In the `@Directive` decorator, notice the selector name, `adHost`; that's what you use to apply the directive to the element. The next section shows you how. @@ -56,7 +56,7 @@ decorator's `template` property as a template string. The `` element is where you apply the directive you just made. To apply the `AdDirective`, recall the selector from `ad.directive.ts`, -`ad-host`. Apply that to `` without the square brackets. Now Angular knows +`[adHost]`. Apply that to `` without the square brackets. Now Angular knows where to dynamically load components. diff --git a/aio/content/guide/observables-in-angular.md b/aio/content/guide/observables-in-angular.md index d4f31ab32d5b..a12030410ef0 100644 --- a/aio/content/guide/observables-in-angular.md +++ b/aio/content/guide/observables-in-angular.md @@ -14,7 +14,7 @@ When you call `emit()`, it passes the emitted value to the `next()` method of an A good example of usage can be found in the [EventEmitter](api/core/EventEmitter) documentation. Here is the example component that listens for open and close events: -`` +`` Here is the component definition: From 5d32a199a96dda102333c0d006d5497be9a3d7d0 Mon Sep 17 00:00:00 2001 From: George Kalpakas Date: Thu, 30 Jul 2020 13:03:23 +0300 Subject: [PATCH 120/253] refactor(docs-infra): update docs examples `tslint.json` to match CLI and fix failures (#38143) This commit updates the `tslint.json` configuration file, that is used to lint the docs examples, to match the one generated for new Angular CLI apps. There are some minimal differences (marked with `TODO` comments) for things, such as component selector prefix, that would require extensive and/or difficult to validate changes in guides. This commit also includes the final adjustments to make the docs examples code compatible with the new tslint rules. (The bulk of the work has been done in previous commits.) PR Close #38143 --- .../e2e/src/app.e2e-spec.ts | 3 +- .../src/app/app.component.ts | 6 +- .../src/app/parent-finder.component.ts | 2 +- .../src/app/car/car.component.ts | 4 +- .../app/dashboard/dashboard.component.spec.ts | 2 +- .../testing/src/app/demo/async-helper.spec.ts | 2 +- .../testing/src/testing/jasmine-matchers.d.ts | 1 + .../testing/src/testing/jasmine-matchers.ts | 1 + aio/content/examples/tslint.json | 180 ++++++++++++------ .../examples/universal/src/app/app.module.ts | 2 +- .../shared/boilerplate/cli/tslint.json | 86 +++++++-- .../shared/boilerplate/systemjs/tslint.json | 177 +++++++++++------ 12 files changed, 317 insertions(+), 149 deletions(-) diff --git a/aio/content/examples/ajs-quick-reference/e2e/src/app.e2e-spec.ts b/aio/content/examples/ajs-quick-reference/e2e/src/app.e2e-spec.ts index ae38d15d8f6f..cc4c47c127b1 100644 --- a/aio/content/examples/ajs-quick-reference/e2e/src/app.e2e-spec.ts +++ b/aio/content/examples/ajs-quick-reference/e2e/src/app.e2e-spec.ts @@ -24,8 +24,7 @@ describe('AngularJS to Angular Quick Reference Tests', () => { // Go through the samples const movieRows = getMovieRows(); - for (let i = 0; i < expectedSamples.length; i++) { - const sample = expectedSamples[i]; + for (const sample of expectedSamples) { const tableCell = movieRows.get(sample.row) .all(by.tagName('td')).get(sample.column); // Check the cell or its nested element diff --git a/aio/content/examples/built-in-directives/src/app/app.component.ts b/aio/content/examples/built-in-directives/src/app/app.component.ts index 10a37ee371c4..a2035effa567 100644 --- a/aio/content/examples/built-in-directives/src/app/app.component.ts +++ b/aio/content/examples/built-in-directives/src/app/app.component.ts @@ -76,11 +76,7 @@ export class AppComponent implements OnInit { } giveNullCustomerValue() { - !(this.nullCustomer = null) ? (this.nullCustomer = 'Kelly') : (this.nullCustomer = null); - } - - resetNullItem() { - this.nullCustomer = null; + this.nullCustomer = 'Kelly'; } resetItems() { diff --git a/aio/content/examples/dependency-injection-in-action/src/app/parent-finder.component.ts b/aio/content/examples/dependency-injection-in-action/src/app/parent-finder.component.ts index 18df7ddae098..cf25406ed582 100644 --- a/aio/content/examples/dependency-injection-in-action/src/app/parent-finder.component.ts +++ b/aio/content/examples/dependency-injection-in-action/src/app/parent-finder.component.ts @@ -1,4 +1,4 @@ -/* tslint:disable: no-unused-variable component-selector one-line space-before-function-paren */ +// tslint:disable: component-selector space-before-function-paren // #docplaster // #docregion import { Component, forwardRef, Optional, SkipSelf } from '@angular/core'; diff --git a/aio/content/examples/dependency-injection/src/app/car/car.component.ts b/aio/content/examples/dependency-injection/src/app/car/car.component.ts index d4f418e058f7..3463c5225005 100644 --- a/aio/content/examples/dependency-injection/src/app/car/car.component.ts +++ b/aio/content/examples/dependency-injection/src/app/car/car.component.ts @@ -27,9 +27,9 @@ import { useInjector } from './car-injector'; providers: [Car, Engine, Tires] }) export class CarComponent { - factoryCar = (new CarFactory).createCar(); + factoryCar = (new CarFactory()).createCar(); injectorCar = useInjector(); - noDiCar = new CarNoDi; + noDiCar = new CarNoDi(); simpleCar = simpleCar(); superCar = superCar(); testCar = testCar(); diff --git a/aio/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts b/aio/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts index 1a9a695cc486..e60e4cc313fb 100644 --- a/aio/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts +++ b/aio/content/examples/testing/src/app/dashboard/dashboard.component.spec.ts @@ -90,7 +90,7 @@ function compileAndCreate() { * The (almost) same tests for both. * Only change: the way that the first hero is clicked */ -function tests(heroClick: Function) { +function tests(heroClick: () => void) { it('should NOT have heroes before ngOnInit', () => { expect(comp.heroes.length).toBe(0, diff --git a/aio/content/examples/testing/src/app/demo/async-helper.spec.ts b/aio/content/examples/testing/src/app/demo/async-helper.spec.ts index 8f6d340ffb9c..c96954d04299 100644 --- a/aio/content/examples/testing/src/app/demo/async-helper.spec.ts +++ b/aio/content/examples/testing/src/app/demo/async-helper.spec.ts @@ -147,7 +147,7 @@ describe('Angular async helper', () => { // #docregion async-test-promise-then describe('test jsonp', () => { - function jsonp(url: string, callback: Function) { + function jsonp(url: string, callback: () => void) { // do a jsonp call which is not zone aware } // need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag diff --git a/aio/content/examples/testing/src/testing/jasmine-matchers.d.ts b/aio/content/examples/testing/src/testing/jasmine-matchers.d.ts index cafce642f9ae..62063b8dfa39 100644 --- a/aio/content/examples/testing/src/testing/jasmine-matchers.d.ts +++ b/aio/content/examples/testing/src/testing/jasmine-matchers.d.ts @@ -1,3 +1,4 @@ +// tslint:disable-next-line: no-namespace declare namespace jasmine { interface Matchers { toHaveText(actual: any, expectationFailOutput?: any): jasmine.CustomMatcher; diff --git a/aio/content/examples/testing/src/testing/jasmine-matchers.ts b/aio/content/examples/testing/src/testing/jasmine-matchers.ts index 0c127e0977ce..6f2ff3c250f2 100644 --- a/aio/content/examples/testing/src/testing/jasmine-matchers.ts +++ b/aio/content/examples/testing/src/testing/jasmine-matchers.ts @@ -1,3 +1,4 @@ +// tslint:disable-next-line: no-reference /// //// Jasmine Custom Matchers //// diff --git a/aio/content/examples/tslint.json b/aio/content/examples/tslint.json index 45be76dec48d..bf1abc0372d7 100644 --- a/aio/content/examples/tslint.json +++ b/aio/content/examples/tslint.json @@ -1,28 +1,61 @@ { - "rulesDirectory": [ - "../../node_modules/codelyzer" - ], + "extends": "tslint:recommended", "rules": { - "class-name": true, - "comment-format": [ + "align": { + "options": [ + "parameters", + "statements" + ] + }, + "array-type": false, + "arrow-return-shorthand": true, + "curly": true, + "deprecation": { + "severity": "warning" + }, + "component-class-suffix": true, + "component-selector": [ true, - "check-space" + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ], + "contextual-lifecycle": true, + "directive-class-suffix": true, + "directive-selector": [ + true, + "attribute", + ["app", "toh"], + "camelCase" ], - "curly": true, "eofline": true, - "forin": true, - "indent": [ + "import-blacklist": [ true, - "spaces" + "rxjs/Rx" ], - "label-position": true, + "import-spacing": true, + "indent": { + "options": [ + "spaces" + ] + }, + "max-classes-per-file": false, "max-line-length": [ true, 140 ], - "member-access": false, - "no-arg": true, - "no-bitwise": true, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], "no-console": [ true, "debug", @@ -31,63 +64,86 @@ "timeEnd", "trace" ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-variable": true, "no-empty": false, - "no-eval": true, - "no-inferrable-types": true, - "no-string-literal": false, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, - "no-trailing-whitespace": true, - "no-unused-expression": true, - "no-var-keyword": true, - "object-literal-sort-keys": false, - "one-line": [ + "no-var-requires": false, + "object-literal-key-quotes": [ true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" + "as-needed" ], "quotemark": [ true, "single" ], - "radix": true, - "semicolon": [ - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" + "semicolon": { + "options": [ + "always" + ] + }, + "space-before-function-paren": { + "options": { + "anonymous": "never", + "asyncArrow": "always", + "constructor": "never", + "method": "never", + "named": "never" } - ], - "variable-name": false, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ], - + }, + "typedef-whitespace": { + "options": [ + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ] + }, + "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-pascal-case" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + }, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, "no-outputs-metadata-property": true, - "use-life-cycle-interface": true, - "use-pipe-transform-interface": true, - "component-class-suffix": true, - "directive-class-suffix": true, - "import-destructuring-spacing": true - } + "template-banana-in-box": true, + "template-no-negated-async": true, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true + }, + "rulesDirectory": [ + "codelyzer" + ] } diff --git a/aio/content/examples/universal/src/app/app.module.ts b/aio/content/examples/universal/src/app/app.module.ts index a843e4d77418..b27d8223563c 100644 --- a/aio/content/examples/universal/src/app/app.module.ts +++ b/aio/content/examples/universal/src/app/app.module.ts @@ -51,7 +51,7 @@ import { isPlatformBrowser } from '@angular/common'; export class AppModule { // #docregion platform-detection constructor( - @Inject(PLATFORM_ID) private platformId: Object, + @Inject(PLATFORM_ID) private platformId: object, @Inject(APP_ID) private appId: string) { const platform = isPlatformBrowser(platformId) ? 'in the browser' : 'on the server'; diff --git a/aio/tools/examples/shared/boilerplate/cli/tslint.json b/aio/tools/examples/shared/boilerplate/cli/tslint.json index f85fc68d9e65..bf1abc0372d7 100644 --- a/aio/tools/examples/shared/boilerplate/cli/tslint.json +++ b/aio/tools/examples/shared/boilerplate/cli/tslint.json @@ -1,37 +1,50 @@ { "extends": "tslint:recommended", "rules": { + "align": { + "options": [ + "parameters", + "statements" + ] + }, "array-type": false, - "arrow-parens": false, + "arrow-return-shorthand": true, + "curly": true, "deprecation": { "severity": "warning" }, "component-class-suffix": true, + "component-selector": [ + true, + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ], "contextual-lifecycle": true, "directive-class-suffix": true, "directive-selector": [ true, "attribute", - "app", + ["app", "toh"], "camelCase" ], - "component-selector": [ - true, - "element", - "app", - "kebab-case" - ], + "eofline": true, "import-blacklist": [ true, "rxjs/Rx" ], - "interface-name": false, + "import-spacing": true, + "indent": { + "options": [ + "spaces" + ] + }, "max-classes-per-file": false, "max-line-length": [ true, 140 ], - "member-access": false, "member-ordering": [ true, { @@ -43,7 +56,6 @@ ] } ], - "no-consecutive-blank-lines": false, "no-console": [ true, "debug", @@ -65,13 +77,59 @@ true, "as-needed" ], - "object-literal-sort-keys": false, - "ordered-imports": false, "quotemark": [ true, "single" ], - "trailing-comma": false, + "semicolon": { + "options": [ + "always" + ] + }, + "space-before-function-paren": { + "options": { + "anonymous": "never", + "asyncArrow": "always", + "constructor": "never", + "method": "never", + "named": "never" + } + }, + "typedef-whitespace": { + "options": [ + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ] + }, + "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-pascal-case" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + }, "no-conflicting-lifecycle": true, "no-host-metadata-property": true, "no-input-rename": true, diff --git a/aio/tools/examples/shared/boilerplate/systemjs/tslint.json b/aio/tools/examples/shared/boilerplate/systemjs/tslint.json index a766b0154e88..bf1abc0372d7 100644 --- a/aio/tools/examples/shared/boilerplate/systemjs/tslint.json +++ b/aio/tools/examples/shared/boilerplate/systemjs/tslint.json @@ -1,31 +1,61 @@ { + "extends": "tslint:recommended", "rules": { - "class-name": true, - "comment-format": [ + "align": { + "options": [ + "parameters", + "statements" + ] + }, + "array-type": false, + "arrow-return-shorthand": true, + "curly": true, + "deprecation": { + "severity": "warning" + }, + "component-class-suffix": true, + "component-selector": [ true, - "check-space" + "element", + // TODO: Fix the code and change the prefix to `"app"` (or whatever makes sense). + "", + "kebab-case" + ], + "contextual-lifecycle": true, + "directive-class-suffix": true, + "directive-selector": [ + true, + "attribute", + ["app", "toh"], + "camelCase" ], - "curly": true, "eofline": true, - "forin": true, - "indent": [ + "import-blacklist": [ true, - "spaces" + "rxjs/Rx" ], - "label-position": true, - "label-undefined": true, + "import-spacing": true, + "indent": { + "options": [ + "spaces" + ] + }, + "max-classes-per-file": false, "max-line-length": [ true, 140 ], - "member-access": false, "member-ordering": [ true, - "static-before-instance", - "variables-before-functions" + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } ], - "no-arg": true, - "no-bitwise": true, "no-console": [ true, "debug", @@ -34,59 +64,86 @@ "timeEnd", "trace" ], - "no-construct": true, - "no-debugger": true, - "no-duplicate-key": true, - "no-duplicate-variable": true, "no-empty": false, - "no-eval": true, - "no-inferrable-types": true, - "no-shadowed-variable": true, - "no-string-literal": false, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-non-null-assertion": true, + "no-redundant-jsdoc": true, "no-switch-case-fall-through": true, - "no-trailing-whitespace": true, - "no-unused-expression": true, - "no-unused-variable": true, - "no-unreachable": true, - "no-var-keyword": true, - "object-literal-sort-keys": false, - "one-line": [ + "no-var-requires": false, + "object-literal-key-quotes": [ true, - "check-open-brace", - "check-catch", - "check-else", - "check-whitespace" + "as-needed" ], "quotemark": [ true, "single" ], - "radix": true, - "semicolon": [ - "always" - ], - "triple-equals": [ - true, - "allow-null-check" - ], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" + "semicolon": { + "options": [ + "always" + ] + }, + "space-before-function-paren": { + "options": { + "anonymous": "never", + "asyncArrow": "always", + "constructor": "never", + "method": "never", + "named": "never" } - ], - "variable-name": false, - "whitespace": [ - true, - "check-branch", - "check-decl", - "check-operator", - "check-separator", - "check-type" - ] - } + }, + "typedef-whitespace": { + "options": [ + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ] + }, + "variable-name": { + "options": [ + "ban-keywords", + "check-format", + "allow-pascal-case" + ] + }, + "whitespace": { + "options": [ + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type", + "check-typecast" + ] + }, + "no-conflicting-lifecycle": true, + "no-host-metadata-property": true, + "no-input-rename": true, + "no-inputs-metadata-property": true, + "no-output-native": true, + "no-output-on-prefix": true, + "no-output-rename": true, + "no-outputs-metadata-property": true, + "template-banana-in-box": true, + "template-no-negated-async": true, + "use-lifecycle-interface": true, + "use-pipe-transform-interface": true + }, + "rulesDirectory": [ + "codelyzer" + ] } From 0b2f134680139ad8824c6339d3e968c67cfce611 Mon Sep 17 00:00:00 2001 From: Joey Perrott Date: Fri, 31 Jul 2020 12:26:39 -0700 Subject: [PATCH 121/253] fix(compiler): update unparsable character reference entity error messages (#38319) Within an angular template, when a character entity is unable to be parsed, previously a generic unexpected character error was thrown. This does not properly express the issue that was discovered as the issue is actually caused by the discovered character making the whole of the entity unparsable. The compiler will now instead inform via the error message what string was attempted to be parsed and what it was attempted to be parsed as. Example, for this template: ```

ģp

``` Before this change: `Unexpected character "p"` After this change: `Unable to parse entity "ģp" - hexadecimal character reference entities must end with ";"` Fixes #26067 PR Close #38319 --- packages/compiler/src/ml_parser/lexer.ts | 17 ++++++++++++++++- packages/compiler/test/ml_parser/lexer_spec.ts | 16 ++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/packages/compiler/src/ml_parser/lexer.ts b/packages/compiler/src/ml_parser/lexer.ts index ffe386537e18..38a82a7d23f6 100644 --- a/packages/compiler/src/ml_parser/lexer.ts +++ b/packages/compiler/src/ml_parser/lexer.ts @@ -138,6 +138,16 @@ function _unknownEntityErrorMsg(entitySrc: string): string { return `Unknown entity "${entitySrc}" - use the "&#;" or "&#x;" syntax`; } +function _unparsableEntityErrorMsg(type: CharacterReferenceType, entityStr: string): string { + return `Unable to parse entity "${entityStr}" - ${ + type} character reference entities must end with ";"`; +} + +enum CharacterReferenceType { + HEX = 'hexadecimal', + DEC = 'decimal', +} + class _ControlFlowError { constructor(public error: TokenError) {} } @@ -400,8 +410,13 @@ class _Tokenizer { const codeStart = this._cursor.clone(); this._attemptCharCodeUntilFn(isDigitEntityEnd); if (this._cursor.peek() != chars.$SEMICOLON) { + // Advance cursor to include the peeked character in the string provided to the error + // message. + this._cursor.advance(); + const entityType = isHex ? CharacterReferenceType.HEX : CharacterReferenceType.DEC; throw this._createError( - _unexpectedCharacterErrorMsg(this._cursor.peek()), this._cursor.getSpan()); + _unparsableEntityErrorMsg(entityType, this._cursor.getChars(start)), + this._cursor.getSpan()); } const strNum = this._cursor.getChars(codeStart); this._cursor.advance(); diff --git a/packages/compiler/test/ml_parser/lexer_spec.ts b/packages/compiler/test/ml_parser/lexer_spec.ts index 79b387e86fda..32895b12eabd 100644 --- a/packages/compiler/test/ml_parser/lexer_spec.ts +++ b/packages/compiler/test/ml_parser/lexer_spec.ts @@ -477,12 +477,16 @@ import {ParseLocation, ParseSourceFile, ParseSourceSpan} from '../../src/parse_u lex.TokenType.TEXT, 'Unknown entity "tbo" - use the "&#;" or "&#x;" syntax', '0:0' ]]); - expect(tokenizeAndHumanizeErrors('sdf;')).toEqual([ - [lex.TokenType.TEXT, 'Unexpected character "s"', '0:3'] - ]); - expect(tokenizeAndHumanizeErrors(' sdf;')).toEqual([ - [lex.TokenType.TEXT, 'Unexpected character "s"', '0:4'] - ]); + expect(tokenizeAndHumanizeErrors('sdf;')).toEqual([[ + lex.TokenType.TEXT, + 'Unable to parse entity "s" - decimal character reference entities must end with ";"', + '0:4' + ]]); + expect(tokenizeAndHumanizeErrors(' sdf;')).toEqual([[ + lex.TokenType.TEXT, + 'Unable to parse entity " s" - hexadecimal character reference entities must end with ";"', + '0:5' + ]]); expect(tokenizeAndHumanizeErrors('઼')).toEqual([ [lex.TokenType.TEXT, 'Unexpected character "EOF"', '0:6'] From 2da56a70a2d7d895b23aeabdb0d6c54ceea3c9ff Mon Sep 17 00:00:00 2001 From: Christian Morante Date: Sat, 15 Aug 2020 18:31:09 -0500 Subject: [PATCH 122/253] docs: traducida la guia Intro (#60) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: traducida la guia Intro Se traduce la guia de Introduccion a la documentacion de Angular * docs: Correecciones de la 1era revisión --- aio/content/marketing/docs.en.md | 58 ++++++++++++++++++++++++++++++ aio/content/marketing/docs.md | 61 ++++++++++++++++---------------- 2 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 aio/content/marketing/docs.en.md diff --git a/aio/content/marketing/docs.en.md b/aio/content/marketing/docs.en.md new file mode 100644 index 000000000000..f2d4a44c60e5 --- /dev/null +++ b/aio/content/marketing/docs.en.md @@ -0,0 +1,58 @@ +

Introduction to the Angular Docs

+ +Angular is an application design framework and development platform for creating efficient and sophisticated single-page apps. + +These Angular docs help you learn and use the Angular framework and development platform, from your first application to optimizing complex single-page apps for enterprises. +Tutorials and guides include downloadable examples to accelerate your projects. + + + + + +## Assumptions + + +These docs assume that you are already familiar with [HTML](https://developer.mozilla.org/docs/Learn/HTML/Introduction_to_HTML "Learn HTML"), [CSS](https://developer.mozilla.org/docs/Learn/CSS/First_steps "Learn CSS"), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript "Learn JavaScript"), +and some of the tools from the [latest standards](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources "Latest JavaScript standards"), such as [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes "ES2015 Classes") and [modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import "ES2015 Modules"). +The code samples are written using [TypeScript](https://www.typescriptlang.org/ "TypeScript"). +Most Angular code can be written with just the latest JavaScript, using [types](https://www.typescriptlang.org/docs/handbook/classes.html "TypeScript Types") for dependency injection, and using [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html "Decorators") for metadata. + + +## Feedback + +

You can sit with us!

+ +We want to hear from you. [Report problems or submit suggestions for future docs.](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form") + +Contribute to Angular docs by creating +[pull requests](https://github.com/angular/angular/pulls "Angular Github pull requests") +on the Angular Github repository. +See [Contributing to Angular](https://github.com/angular/angular/blob/master/CONTRIBUTING.md "Contributing guide") +for information about submission guidelines. + +Our community values respectful, supportive communication. +Please consult and adhere to the [Code of Conduct](https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md "Contributor code of conduct"). diff --git a/aio/content/marketing/docs.md b/aio/content/marketing/docs.md index f2d4a44c60e5..0d9248498d4d 100644 --- a/aio/content/marketing/docs.md +++ b/aio/content/marketing/docs.md @@ -1,58 +1,57 @@ -

Introduction to the Angular Docs

+

Introducción a la Documentación de Angular

-Angular is an application design framework and development platform for creating efficient and sophisticated single-page apps. +Angular es un framework de diseño de aplicaciones y plataforma de desarrollo para crear aplicaciones de una sola página eficientes y sofisticadas -These Angular docs help you learn and use the Angular framework and development platform, from your first application to optimizing complex single-page apps for enterprises. -Tutorials and guides include downloadable examples to accelerate your projects. +Esta documentación de Angular te ayuda a aprender y usar el framework y la plataforma de desarrollo, desde su primera aplicación hasta la optimización de aplicaciones complejas de una sola página, para empresas. +Los tutoriales y guías incluyen ejemplos descargables para acelerar tus proyectos. -## Assumptions +## Supuestos -These docs assume that you are already familiar with [HTML](https://developer.mozilla.org/docs/Learn/HTML/Introduction_to_HTML "Learn HTML"), [CSS](https://developer.mozilla.org/docs/Learn/CSS/First_steps "Learn CSS"), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript "Learn JavaScript"), -and some of the tools from the [latest standards](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources "Latest JavaScript standards"), such as [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes "ES2015 Classes") and [modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import "ES2015 Modules"). -The code samples are written using [TypeScript](https://www.typescriptlang.org/ "TypeScript"). -Most Angular code can be written with just the latest JavaScript, using [types](https://www.typescriptlang.org/docs/handbook/classes.html "TypeScript Types") for dependency injection, and using [decorators](https://www.typescriptlang.org/docs/handbook/decorators.html "Decorators") for metadata. +Esta documentación asume que estas familiarizado con [HTML](https://developer.mozilla.org/docs/Learn/HTML/Introduction_to_HTML "Aprende HTML"), [CSS](https://developer.mozilla.org/docs/Learn/CSS/First_steps "Aprende CSS"), [JavaScript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript "Aprende JavaScript"), +y algunas herramientas de los [últimos estándares javascript](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Language_Resources "Últimos estándares JavaScript"), como son las [clases](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes "Clases ES2015") y [modulos](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import "Modulos ES2015"). +Los ejemplos de código son escritos usando [TypeScript](https://www.typescriptlang.org/ "TypeScript"). +La mayor parte del código Angular se puede escribir tan solo con la versión más reciente de JavaScript, usando [tipos](https://www.typescriptlang.org/docs/handbook/classes.html "Tipos TypeScript") para inyección de dependencia, y usando [decoradores](https://www.typescriptlang.org/docs/handbook/decorators.html "Decoradores") para metadatos. -## Feedback +## Retrolimentación -

You can sit with us!

+

Puedes sentarte con nosotros!

-We want to hear from you. [Report problems or submit suggestions for future docs.](https://github.com/angular/angular/issues/new/choose "Angular GitHub repository new issue form") +Queremos saber de ti. [Informa problemas o envía sugerencias para nueva documentación.](https://github.com/angular-hispano/angular/issues/new/choose "Repositorio GitHub de Angular, form para nuevo issue") -Contribute to Angular docs by creating -[pull requests](https://github.com/angular/angular/pulls "Angular Github pull requests") -on the Angular Github repository. -See [Contributing to Angular](https://github.com/angular/angular/blob/master/CONTRIBUTING.md "Contributing guide") -for information about submission guidelines. +Colabora con la documentación de Angular creando [pull requests](https://github.com/angular-hispano/angular/pulls "Angular Github pull requests") +en el repositorio Github de Angular en español. +Mira [Colaborando a Angular](https://github.com/angular-hispano/angular/blob/master/CONTRIBUTING.md "Guía de Colaboración") +para obtener información sobre las pautas de envío de nuevas colaboraciones. -Our community values respectful, supportive communication. -Please consult and adhere to the [Code of Conduct](https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md "Contributor code of conduct"). +Nuestra comunidad valora la comunicación respetuosa y solidaria. +Consulta y adhierete al [Código de Conducta](https://github.com/angular-hispano/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md "Código de Conducta del Colaborador"). From d870e5c30959ed159b01e61bdd8bae8d31de1eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20D=C3=ADaz?= <36966980+dalejodc@users.noreply.github.com> Date: Sat, 15 Aug 2020 18:27:22 -0600 Subject: [PATCH 123/253] docs: translate CONTRIBUTING.md to spanish (#58) * docs: translate CONTRIBUTING.md to spanish Translate CONTRIBUTING.md to spanish Fix #48 * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md * Update CONTRIBUTING.md Co-authored-by: Pato <11162114+devpato@users.noreply.github.com> --- CONTRIBUTING.en.md | 359 +++++++++++++++++++++++++++++++++++++++++++++ CONTRIBUTING.md | 305 +++++++++++++++++++------------------- 2 files changed, 511 insertions(+), 153 deletions(-) create mode 100644 CONTRIBUTING.en.md diff --git a/CONTRIBUTING.en.md b/CONTRIBUTING.en.md new file mode 100644 index 000000000000..3ec3a41f0af1 --- /dev/null +++ b/CONTRIBUTING.en.md @@ -0,0 +1,359 @@ +# Contributing to Angular + +We would love for you to contribute to Angular and help make it even better than it is today! +As a contributor, here are the guidelines we would like you to follow: + + - [Code of Conduct](#coc) + - [Question or Problem?](#question) + - [Issues and Bugs](#issue) + - [Feature Requests](#feature) + - [Submission Guidelines](#submit) + - [Coding Rules](#rules) + - [Commit Message Guidelines](#commit) + - [Signing the CLA](#cla) + + +## Code of Conduct + +Help us keep Angular open and inclusive. +Please read and follow our [Code of Conduct][coc]. + + +## Got a Question or Problem? + +Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. +Instead, we recommend using [Stack Overflow](https://stackoverflow.com/questions/tagged/angular) to ask support-related questions. When creating a new question on Stack Overflow, make sure to add the `angular` tag. + +Stack Overflow is a much better place to ask questions since: + +- there are thousands of people willing to help on Stack Overflow +- questions and answers stay available for public viewing so your question/answer might help someone else +- Stack Overflow's voting system assures that the best answers are prominently visible. + +To save your and our time, we will systematically close all issues that are requests for general support and redirect people to Stack Overflow. + +If you would like to chat about the question in real-time, you can reach out via [our gitter channel][gitter]. + + +## Found a Bug? + +If you find a bug in the source code, you can help us by [submitting an issue](#submit-issue) to our [GitHub Repository][github]. +Even better, you can [submit a Pull Request](#submit-pr) with a fix. + + +## Missing a Feature? +You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub Repository. +If you would like to *implement* a new feature, please consider the size of the change in order to determine the right steps to proceed: + +* For a **Major Feature**, first open an issue and outline your proposal so that it can be discussed. + This process allows us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project. + + **Note**: Adding a new topic to the documentation, or significantly re-writing a topic, counts as a major feature. + +* **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). + + +## Submission Guidelines + + +### Submitting an Issue + +Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available. + +We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. +In order to reproduce bugs, we require that you provide a minimal reproduction. +Having a minimal reproducible scenario gives us a wealth of important information without going back and forth to you with additional questions. + +A minimal reproduction allows us to quickly confirm a bug (or point out a coding problem) as well as confirm that we are fixing the right problem. + +We require a minimal reproduction to save maintainers' time and ultimately be able to fix more bugs. +Often, developers find coding problems themselves while preparing a minimal reproduction. +We understand that sometimes it might be hard to extract essential bits of code from a larger codebase but we really need to isolate the problem before we can fix it. + +Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you, we are going to close an issue that doesn't have enough info to be reproduced. + +You can file new issues by selecting from our [new issue templates](https://github.com/angular/angular/issues/new/choose) and filling out the issue template. + + +### Submitting a Pull Request (PR) + +Before you submit your Pull Request (PR) consider the following guidelines: + +1. Search [GitHub](https://github.com/angular/angular/pulls) for an open or closed PR that relates to your submission. + You don't want to duplicate existing efforts. + +2. Be sure that an issue describes the problem you're fixing, or documents the design for the feature you'd like to add. + Discussing the design upfront helps to ensure that we're ready to accept your work. + +3. Please sign our [Contributor License Agreement (CLA)](#cla) before sending PRs. + We cannot accept code without a signed CLA. + Make sure you author all contributed Git commits with email address associated with your CLA signature. + +4. Fork the angular/angular repo. + +5. Make your changes in a new git branch: + + ```shell + git checkout -b my-fix-branch master + ``` + +6. Create your patch, **including appropriate test cases**. + +7. Follow our [Coding Rules](#rules). + +8. Run the full Angular test suite, as described in the [developer documentation][dev-doc], and ensure that all tests pass. + +9. Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). + Adherence to these conventions is necessary because release notes are automatically generated from these messages. + + ```shell + git commit -a + ``` + Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. + +10. Push your branch to GitHub: + + ```shell + git push origin my-fix-branch + ``` + +11. In GitHub, send a pull request to `angular:master`. + + If we ask for changes via code reviews then: + + * Make the required updates. + * Re-run the Angular test suites to ensure tests are still passing. + * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): + + ```shell + git rebase master -i + git push -f + ``` + +That's it! Thank you for your contribution! + + +#### After your pull request is merged + +After your pull request is merged, you can safely delete your branch and pull the changes from the main (upstream) repository: + +* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows: + + ```shell + git push origin --delete my-fix-branch + ``` + +* Check out the master branch: + + ```shell + git checkout master -f + ``` + +* Delete the local branch: + + ```shell + git branch -D my-fix-branch + ``` + +* Update your master with the latest upstream version: + + ```shell + git pull --ff upstream master + ``` + + +## Coding Rules +To ensure consistency throughout the source code, keep these rules in mind as you are working: + +* All features or bug fixes **must be tested** by one or more specs (unit-tests). +* All public API methods **must be documented**. +* We follow [Google's JavaScript Style Guide][js-style-guide], but wrap all code at **100 characters**. + + An automated formatter is available, see [DEVELOPER.md](docs/DEVELOPER.md#clang-format). + + +## Commit Message Format + +*This specification is inspired and supersedes the [AngularJS commit message format][commit-message-format].* + +We have very precise rules over how our Git commit messages must be formatted. +This format leads to **easier to read commit history**. + +Each commit message consists of a **header**, a **body**, and a **footer**. + + +``` +
+ + + +