Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
docs: Static further reading links (#15890)
* docs: Static further reading links

* Move script to top level

* Address feedback

* Update docs readme

* Update docs/README.md

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>

Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
  • Loading branch information
nzakas and mdjermanovic committed May 20, 2022
1 parent cab0c22 commit 050d5f4
Show file tree
Hide file tree
Showing 9 changed files with 858 additions and 45 deletions.
6 changes: 6 additions & 0 deletions .eslintrc.js
Expand Up @@ -74,6 +74,12 @@ module.exports = {
"internal-rules/multiline-comment-style": "error"
},
overrides: [
{
files: ["tools/*.js"],
rules: {
"no-console": "off"
}
},
{
files: ["lib/rules/*", "tools/internal-rules/*"],
excludedFiles: ["index.js"],
Expand Down
34 changes: 16 additions & 18 deletions docs/.eleventy.js
Expand Up @@ -6,16 +6,6 @@ const slugify = require("slugify");
const markdownIt = require("markdown-it");
const markdownItAnchor = require('markdown-it-anchor');
const Image = require("@11ty/eleventy-img");
const metascraper = require('metascraper')([
require('metascraper-image')(),
require('metascraper-logo')(),
require('metascraper-logo-favicon')(),
require('metascraper-publisher')(),
require('metascraper-title')(),
require('metascraper-description')(),
require('metascraper-url')()
]);
const got = require('got');
const path = require('path');

const {
Expand Down Expand Up @@ -132,19 +122,27 @@ module.exports = function(eleventyConfig) {
/**********************************************************************
* Shortcodes
* ********************************************************************/
eleventyConfig.addNunjucksAsyncShortcode("link", async function(link) {
const { body: html, url } = await got(link);
const metadata = await metascraper({ html, url });
const the_url = (new URL(link)); // same as url
const domain = the_url.hostname;
eleventyConfig.addNunjucksShortcode("link", function(url) {

const urlData = this.ctx.further_reading_links[url];

if (!urlData) {
throw new Error(`Data missing for ${url}`);
}

const {
domain,
title,
logo
} = urlData;

return `
<article class="resource">
<div class="resource__image">
<img class="resource__img" width="75" height="75" src="${metadata.logo}" alt="Avatar image for ${domain}" />
<img class="resource__img" width="75" height="75" src="${logo}" alt="Avatar image for ${domain}" onerror="this.onerror = null; this.src = '/icon.svg'" />
</div>
<div class="resource__content">
<a href="${metadata.url}" class="resource__title"> ${metadata.title} </a><br>
<a href="${url}" class="resource__title"> ${title} </a><br>
<span class="resource__domain"> ${domain}</span>
</div>
<svg class="c-icon resource__icon" width="13" height="12" viewBox="0 0 13 12" fill="none">
Expand Down Expand Up @@ -306,7 +304,7 @@ module.exports = function(eleventyConfig) {
// START, eleventy-img
function imageShortcode(src, alt, cls, sizes = "(max-width: 768px) 100vw, 50vw") {
const source = src;
// console.log(`Generating image(s) from: ${src}`)

let options = {
widths: [600, 900, 1500],
formats: ["webp", "jpeg"],
Expand Down
15 changes: 15 additions & 0 deletions docs/README.md
@@ -0,0 +1,15 @@
# ESLint Documentation

## Run Locally

```shell
npm start
```

## Scripts

To update the links data file, run this from the root folder (not the `docs` folder):

```shell
npm run docs:update-links
```
13 changes: 1 addition & 12 deletions docs/package.json
@@ -1,5 +1,5 @@
{
"name": "foundation",
"name": "docs-eslint",
"version": "1.0.0",
"description": "",
"main": "index.js",
Expand Down Expand Up @@ -36,16 +36,5 @@
"rimraf": "^3.0.2",
"sass": "^1.38.0",
"slugify": "^1.6.3"
},
"dependencies": {
"got": "^11.8.3",
"metascraper": "^5.25.7",
"metascraper-description": "^5.25.7",
"metascraper-image": "^5.25.7",
"metascraper-logo": "^5.25.7",
"metascraper-logo-favicon": "^5.25.7",
"metascraper-publisher": "^5.25.7",
"metascraper-title": "^5.25.7",
"metascraper-url": "^5.25.7"
}
}
688 changes: 688 additions & 0 deletions docs/src/_data/further_reading_links.json

Large diffs are not rendered by default.

11 changes: 3 additions & 8 deletions docs/src/_includes/layouts/doc.html
Expand Up @@ -27,7 +27,9 @@ <h2 id="related-rules">Related Rules</h2>
{% if further_reading %}
{% set further_reading_content %}
<h2 id="further-reading">Further Reading</h2>
{# async shortcodes don't work here so need to manually insert later #}
{% for url in further_reading %}
{% link url %}
{% endfor %}
{% endset %}

{% set all_content = [all_content, further_reading_content] | join %}
Expand All @@ -40,13 +42,6 @@ <h1>{{ title }}</h1>

{{ all_content | safe }}

{# now insert the async-fetched link data if necessary #}
{% if further_reading %}
{% for url in further_reading %}
{% link url %}
{% endfor %}
{% endif %}

<div class="docs-edit-link">
<a href="{{ edit_link }}" class="c-btn c-btn--secondary">Edit this page</a>
</div>
Expand Down
6 changes: 1 addition & 5 deletions docs/src/library/link-card.md
Expand Up @@ -10,10 +10,6 @@ Links can be rendered as cards by using the `link` shortcode. The only required

## Examples

{% link "https://developer.mozilla.org/en-US/docs/Web/JavaScript" %}

{% link "https://github.com/microlinkhq/metascraper" %}

{% link "https://blog.izs.me/2010/12/an-open-letter-to-javascript-leaders-regarding/" %}

{% link "https://humanwhocodes.com/blog/2021/12/making-open-source-project-sponsor-ready-accepting-sponsorships/" %}
{% link "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get" %}
18 changes: 16 additions & 2 deletions package.json
Expand Up @@ -25,14 +25,19 @@
"publish-release": "node Makefile.js publishRelease",
"gensite": "node Makefile.js gensite",
"webpack": "node Makefile.js webpack",
"perf": "node Makefile.js perf"
"perf": "node Makefile.js perf",
"docs:update-links": "node tools/fetch-docs-links.js"
},
"gitHooks": {
"pre-commit": "lint-staged"
},
"lint-staged": {
"*.js": "eslint --fix",
"*.md": "markdownlint --fix"
"*.md": "markdownlint --fix",
"docs/src/rules/*.md": [
"node tools/fetch-docs-links.js",
"git add docs/src/_data/further_reading_links.json"
]
},
"files": [
"LICENSE",
Expand Down Expand Up @@ -104,8 +109,11 @@
"eslint-release": "^3.2.0",
"eslump": "^3.0.0",
"esprima": "^4.0.1",
"fast-glob": "^3.2.11",
"fs-teardown": "^0.1.3",
"glob": "^7.1.6",
"got": "^11.8.3",
"gray-matter": "^4.0.3",
"jsdoc": "^3.5.5",
"karma": "^6.1.1",
"karma-chrome-launcher": "^3.1.0",
Expand All @@ -118,6 +126,12 @@
"markdownlint-cli": "^0.30.0",
"marked": "^4.0.8",
"memfs": "^3.0.1",
"metascraper": "^5.25.7",
"metascraper-description": "^5.25.7",
"metascraper-image": "^5.29.3",
"metascraper-logo": "^5.25.7",
"metascraper-logo-favicon": "^5.25.7",
"metascraper-title": "^5.25.7",
"mocha": "^8.3.2",
"mocha-junit-reporter": "^2.0.0",
"node-polyfill-webpack-plugin": "^1.0.3",
Expand Down
112 changes: 112 additions & 0 deletions tools/fetch-docs-links.js
@@ -0,0 +1,112 @@
/**
* @fileoverview Script to fetch link data.
*
* To fetch info about all files:
*
* node tools/fetch-docs-links.js
*
* To fetch info for just selected files (for use with lint-staged):
*
* node tools/fetch-docs-links.js docs/src/user-guide/index.md
*
* @author Nicholas C. Zakas
*/

"use strict";

//-----------------------------------------------------------------------------
// Requirements
//-----------------------------------------------------------------------------

const matter = require("gray-matter");
const metascraper = require("metascraper")([
require("metascraper-image")(),
require("metascraper-logo")(),
require("metascraper-logo-favicon")(),
require("metascraper-title")(),
require("metascraper-description")()
]);
const got = require("got");
const path = require("path");
const fs = require("fs/promises");
const glob = require("fast-glob");

//-----------------------------------------------------------------------------
// Data
//-----------------------------------------------------------------------------

const BASE_DIR = path.resolve(__dirname, "../");
const SRC_DIR = path.resolve(BASE_DIR, "docs/src");
const DATA_DIR = path.resolve(SRC_DIR, "_data");
const DATA_FILE_PATH = path.resolve(DATA_DIR, "further_reading_links.json");

// determine which files to check
let filenames = process.argv.slice(2);

if (filenames.length === 0) {
filenames = glob.sync("docs/src/rules/*.md", { cwd: BASE_DIR });
}

filenames = filenames.map(filename => path.resolve(BASE_DIR, filename));

//-----------------------------------------------------------------------------
// Helpers
//-----------------------------------------------------------------------------

/**
* Fetches metadata information for a given URL.
* @param {string} url The URL to fetch data for.
* @returns {Promise<object>} An object with metadata info.
*/
async function fetchLinkMeta(url) {
const { body: html, url: returnedURL } = await got(url);
const metadata = await metascraper({ html, url: returnedURL });
const domain = (new URL(returnedURL)).hostname;

return {
domain,
url,
logo: metadata.logo,
title: metadata.title,
description: metadata.description
};
}


//-----------------------------------------------------------------------------
// Main
//-----------------------------------------------------------------------------

(async () => {

// First read in the current data file
const links = JSON.parse(await fs.readFile(DATA_FILE_PATH, "utf8"));

// check each file
for (const filename of filenames) {

const text = await fs.readFile(filename, "utf8");
const frontmatter = matter(text).data;

if (frontmatter.further_reading) {

for (const url of frontmatter.further_reading) {
if (!links[url]) {
try {
links[url] = await fetchLinkMeta(url);
} catch (ex) {
console.error("Error in ", filename);
console.error("Could not fetch data for", url);
console.error(ex.message);
console.error(ex.stack);
process.exit(1);
}
}
}

}
}

// Last write new data into the current data file
await fs.writeFile(DATA_FILE_PATH, JSON.stringify(links, null, 4), "utf8");
})();

0 comments on commit 050d5f4

Please sign in to comment.