docs: remove/update broken links in resources appearing on aio (#42232)

Remove or update broken links to resources from the resources and
contributors pages on aio.

Closes #39719

PR Close #42232
This commit is contained in:
Joey Perrott 2021-05-21 15:28:04 -07:00 committed by Andrew Kushnir
parent 9193ea20e4
commit 4e9b61aaf9
5 changed files with 118 additions and 24 deletions

View File

@ -609,6 +609,14 @@ jobs:
command: 'openssl aes-256-cbc -d -in .circleci/github_token -md md5 -k "${KEY}" -out ~/.git_credentials'
- run: ./scripts/ci/publish-build-artifacts.sh
aio_misc:
executor: default-executor
steps:
- custom_attach_workspace
- run:
name: Check website provided in contributors.json file
command: yarn node aio/scripts/test-external-urls.js
aio_monitoring_stable:
executor: default-executor
steps:
@ -879,6 +887,9 @@ workflows:
monitoring:
jobs:
- setup
- aio_misc:
requires:
- setup
- aio_monitoring_stable:
requires:
- setup

View File

@ -278,7 +278,6 @@
"name": "Dylan Hunn",
"picture": "dylan-hunn.jpg",
"twitter": "dylhunn",
"website": "https://hunn.io",
"bio": "Dylan is a software engineer at Google on the Angular Core team. He loves board games, the open web, and adorable rabbits.",
"groups": ["Angular"],
"lead": "jelbourn"
@ -309,7 +308,6 @@
"name": "Josue Gutierrez",
"picture": "josue.jpg",
"twitter": "eusoj",
"website": "http://techtam.io",
"bio": "Based in Mexico, Josue has been web developer since the last 10 years, he is part of the Google Developer Expert Program, passionate about teaching and building communities",
"groups": ["GDE"]
},
@ -342,7 +340,6 @@
"name": "Gerard Sans",
"picture": "gerardsans.jpg",
"twitter": "gerardsans",
"website": "https://medium.com/@gerard.sans",
"bio": "Gerard is very excited about the future of the Web and JavaScript. Always happy Computer Science Engineer and humble Google Developer Expert. He loves to share his learnings by giving talks, trainings and writing about cool technologies. He loves running AngularZone and GraphQL London, mentoring students and giving back to the community.",
"groups": ["GDE"]
},
@ -366,7 +363,6 @@
"name": "Igor Minar",
"picture": "igor-minar.jpg",
"twitter": "IgorMinar",
"website": "https://google.com/+IgorMinar",
"bio": "Igor is a software engineer at Google. He is a lead on the Angular project, practitioner of test driven development, open source enthusiast, hacker. In his free time, Igor enjoys spending time with his wife and two kids, doing outdoor activities (including but not limited to sports, gardening and building retaining walls).",
"groups": ["Angular"]
},
@ -405,7 +401,6 @@
"name": "Jeremy Wilken",
"picture": "jeremywilken.jpg",
"twitter": "gnomeontherun",
"website": "https://gnomeontherun.com",
"bio": "Based in Austin Texas, Jeremy is an application architect and homebrewer. He is a Google Developer Expert in Web Technologies and Angular, with a focus on speaking and training and author of Angular in Action and Ionic in Action.",
"groups": ["GDE"]
},
@ -431,7 +426,6 @@
"name": "Joe Eames",
"picture": "joeeames.jpg",
"twitter": "josepheames",
"website": "https://joeeames.me",
"bio": "Joe Eames is a developer and educator. He publishes course on Angular and JavaScript on Pluralsight.com. He is an organizer of ng-conf, a Google Developer Expert in Angular, gives lots of talks & workshops, and loves all things web.",
"groups": ["GDE"]
},
@ -525,7 +519,7 @@
"name": "Kevin Kreuzer",
"picture": "kevin-kreuzer.jpg",
"twitter": "kreuzercode",
"website": "kreuzercode.com",
"website": "http://kreuzercode.com",
"bio": "Kevin is a passionate freelance front-end engineer and Google Developer Expert based in Switzerland. He is a JavaScript enthusiast and fascinated by Angular. Kevin always tries to learn new things, expand his knowledge, and share it with others in the form of blog posts, workshops, podcasts, or presentations. He is a writer for various publications and the most active writer on Angular in-depth in 2019. Contributing to multiple projects and maintaining 7 npm packages, Kevin is also a big believer in open source. Furthermore, Kevin is a big football fan. Since his childhood, he has supported Real Madrid, which you might notice in a lot of his blog posts and tutorials.",
"groups": ["GDE"]
},
@ -593,14 +587,12 @@
"website": "https://www.softwarearchitekt.at",
"bio": "Trainer and Consultant with focus on Angular. Writes for O'Reilly, the German Java Magazine and Heise. Regularly speaks at conferences.",
"mentor": "mgechev",
"groups": ["GDE",
"Collaborators"]
"groups": ["GDE", "Collaborators"]
},
"martinakraus": {
"name": "Martina Kraus",
"picture": "martinakraus.jpg",
"twitter": "MartinaKraus11",
"website": "http://martina-kraus.io",
"bio": "Martina is a software engineer and an Angular enthusiast. As a trainer, mentor and speaker she loves sharing knowledge about Web Technologies and Angular. She is Organizer of ngGirls and the local Angular Meetup",
"groups": ["GDE"]
},
@ -689,7 +681,6 @@
"name": "Nir Kaufman",
"picture": "nirkaufman.jpg",
"twitter": "nirkaufman",
"website": "http://ngnir.life/",
"bio": "Nir is a Principal Frontend Consultant & Head of the Angular department at 500Tech, Google Developer Expert and community leader. He organizes the largest Angular meetup group in Israel (Angular-IL), talks and teaches about front-end technologies around the world. He is also the author of two books about Angular and the founder of the 'Frontend Band'.",
"groups": ["GDE"]
},
@ -778,7 +769,6 @@
"name": "Sander Elias",
"picture": "sanderelias.jpg",
"twitter": "esoSanderElias",
"website": "https://sanderelias.nl",
"bio": "Sander is a versed developer with over 4 decades of practice under his belt. He is also an Google Developer Expert for web, specializing in Angular. Organizer of meetups and conferences. Helping out others wherever he can. When he is not breathing code, he is fiddling around with IOT, photography, science and anything that might vaguely is gadget-like! Thinks he a master of the grill, but in reality you probably don't get a food-poisoning ;) Also, and actually the most important thing to him, he is a father of 4, and has the most patient girlfriend in the universe.",
"groups": ["GDE"]
},
@ -810,7 +800,6 @@
"name": "Siddharth Ajmera",
"picture": "sidd-ajmera.jpg",
"twitter": "SiddAjmera",
"website": "https://webstackup.com/",
"bio": "Siddharth is a Full Stack JavaScript Developer and a GDE in Angular. He's passionate about sharing his knowledge on Angular, Firebase and the Web in general. He's the organizer of WebStack, a local community of developers focused on Web, Mobile, Voice and Server related technologies in general. WebStack hosts free monthly meetups every 2nd or 3rd Saturday of the month. Siddharth is also an avid photographer and loves traveling. Find him anywhere on the Web with `SiddAjmera`.",
"groups": ["GDE"]
},
@ -895,7 +884,6 @@
"name": "Emma Twersky",
"picture": "twerske.jpg",
"twitter": "twerske",
"website": "https://twerske.github.io/",
"bio": "Emma is a Developer Advocate at Google. She is passionate about good user experiences and design.",
"groups": ["Angular"],
"lead": "mgechev"

View File

@ -156,13 +156,13 @@
},
"ab2": {
"desc": "Use Angular and Meteor to build full-stack JavaScript apps for Mobile and Desktop.",
"logo": "http://www.angular-meteor.com/images/logo.png",
"logo": "https://angular-meteor.com/assets/images/logo-large.png",
"title": "Meteor",
"url": "https://github.com/urigo/angular-meteor"
},
"ab3": {
"desc": "Apollo is a data stack for modern apps, built with GraphQL.",
"logo": "http://docs.apollostack.com/logo/large.png",
"logo": "",
"title": "Apollo",
"url": "https://www.apollographql.com/docs/angular/"
},
@ -341,7 +341,7 @@
},
"a2b": {
"desc": "PrimeNG is a collection of rich UI components for Angular",
"logo": "http://www.primefaces.org/primeng/showcase/resources/images/primeng.svg",
"logo": "https://www.primefaces.org/primeng/resources/images/logo-primeng.svg",
"title": "Prime Faces",
"url": "https://www.primefaces.org/primeng/"
},
@ -353,7 +353,7 @@
},
"a5b": {
"desc": "High-performance UI controls with the most complete Angular support available. Wijmos controls are all written in TypeScript and have zero dependencies. FlexGrid control includes full declarative markup, including cell templates.",
"logo": "http://wijmocdn.azureedge.net/wijmositeblob/wijmo-theme/logos/wijmo-55.png",
"logo": "",
"title": "Wijmo",
"url": "https://www.grapecity.com/wijmo"
},
@ -438,7 +438,7 @@
"desc": "Amexio is a rich set of Angular components powered by HTML5 & CSS3 for Responsive Web Design and 80+ built-in Material Design Themes. Amexio has 3 Editions, Standard, Enterprise and Creative. Std Edition consists of basic UI Components which include Grid, Tabs, Form Inputs and so on. While Enterprise Edition consists of components like Calendar, Tree Tabs, Social Media Logins (Facebook, GitHub, Twitter and so on) and Creative Edition is focused building elegant and beautiful websites. With more than 200+ components/features. All the editions are open-sourced and free, based on Apache 2 License.",
"title": "Amexio - Angular Extensions",
"url": "https://amexio.tech/",
"logo": "http://www.amexio.org/amexio-logo.png"
"logo": ""
},
"bm": {
"desc": "A lightweight Material Design library for Angular, based upon Google's Material Components for the Web",
@ -765,7 +765,7 @@
"500tech": {
"desc": "Learn from 500Tech, an Angular consultancy in Israel. This course was built by an expert developer, who lives and breathes Angular, and has practical experience with real world large scale Angular apps.",
"title": "Angular Hands-on Course (Israel)",
"url": "http://angular2.courses.500tech.com/"
"url": "https://500tech.com/courses/angular/"
},
"9ab": {
"desc": "OnSite Training From the Authors of \"Become A Ninja with Angular\"",

View File

@ -0,0 +1,99 @@
/**
* @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
*/
const {green, red} = require('chalk');
const fetch = require('node-fetch');
const {join} = require('path');
/** The full path to the contributons.json fie. */
const contributorsFilePath = join(__dirname, '../content/marketing/contributors.json');
/** Verify the provided contributor websites are reachable via http(s). */
(async () => {
/** The json object from the contributors.json file. */
const contributorsJson = require(contributorsFilePath);
/** The contributors flattened into an array containing the object key as a property. */
const contributors = Object.entries(contributorsJson).map(([key, entry]) => ({key, ...entry}));
/** Discovered contributor entries with failures loading the provided website. */
const failures = [];
/** The longest discovered length of a value in the key, website or message property. */
let padding = {key: 0, website: 0, message: 0};
/** Adds a provided failure to the list, updating the paddings as appropriate. */
const addFailure = (failure) => {
padding.key = Math.max(padding.key, failure.key.length);
padding.website = Math.max(padding.website, failure.website.length);
padding.message = Math.max(padding.message, failure.message.length);
failures.push(failure);
};
// By creating an array of Promises resolving for each attempt at checking if a contributors
// website is reachable, these checks can be done in parallel.
await Promise.allSettled(contributors.map(async entry => {
// If no website is provided no check is needed.
if (entry.website === undefined) {
return;
}
// Ensure the provided website value is a valid external url serves via http or https.
let url;
try {
url = new URL(entry.website);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
// Throw a generic error here to have the more specific error rethrown by the catch block.
throw Error;
}
} catch {
addFailure({...entry, message: 'Not a valid http(s) URL'});
return;
}
// Check validated websites to confirm they can be reached via fetch.
try {
const result = await fetch(url, {method: 'HEAD'});
if (!result.ok) {
// If the url is for linkedin.com and the status returned is a `999`, we can assume that
// the page is working as expected as linkedin.com returns a `999` status for
// non-browser based requests. Other pages returning a `999` may still indicate an
// error in the request for the page.
if (result.status === 999 && url.hostname.includes('linkedin.com')) {
return;
}
// If the page returns a 429 for too many requests, we will assume it works and continue
// checking in the future.
if (result.status === 429) {
return;
}
// Throw the error status a `code` to be used in the catch block.
throw {code: result.status};
}
} catch (err) {
if (err.code !== undefined) {
addFailure({...entry, message: err.code});
} else {
addFailure({...entry, message: err})
}
}
}));
if (failures.length === 0) {
console.info(green(' ✓ All websites defined in the contributors.json passed loading check.'));
} else {
console.group(red(`${failures.length} url(s) were unable to load:`));
failures.forEach((failure) => {
const key = failure.key.padEnd(padding.key);
const website = failure.website.padEnd(padding.website);
const message = failure.message;
console.log(`${key} ${website} Error: ${message}`);
});
console.groupEnd();
}
})();

View File

@ -167,10 +167,6 @@ Additionally, the [MessageBroker](#messagebroker) sits on top of the [MessageBus
MessageBus is a low level abstraction that provides a language agnostic API for communicating with angular components across any runtime boundary such as `WebWorker <--> UI` communication, `UI <--> Server` communication,
or `Window <--> Window` communication.
See the diagram below for a high level overview of how this code is structured:
![WebWorker Diagram](http://stanford.edu/~jteplitz/ng_2_worker.png)
## Running Code on the UI
If your application needs to run code on the UI, there are a few options. The easiest way is to use a
CustomElement in your view. You can then register this custom element from your html file and run code in response