diff --git a/packages/linter/src/index.ts b/packages/linter/src/index.ts index 8b2de9de3..bfc8fd685 100644 --- a/packages/linter/src/index.ts +++ b/packages/linter/src/index.ts @@ -27,6 +27,7 @@ import { ModuleRuntimeUsed } from "./rules/ModuleRuntimeUsed"; import { BlockingExtensionsPreloaded } from "./rules/BlockingExtensionsPreloaded"; import { FontsArePreloaded } from "./rules/FontsArePreloaded"; import { HeroImageIsDefined } from "./rules/HeroImageIsDefined"; +import { FastGoogleFontsDisplay } from "./rules/FastGoogleFontsDisplay"; import { RuleConstructor } from "./rule"; import { isArray } from "util"; @@ -133,6 +134,7 @@ function testsForMode(type: LintMode) { RuntimeIsPreloaded, BlockingExtensionsPreloaded, FontsArePreloaded, + FastGoogleFontsDisplay, IsTransformedAmp, ModuleRuntimeUsed, HeroImageIsDefined, diff --git a/packages/linter/src/rules/FastGoogleFontsDisplay.ts b/packages/linter/src/rules/FastGoogleFontsDisplay.ts new file mode 100644 index 000000000..9957976f2 --- /dev/null +++ b/packages/linter/src/rules/FastGoogleFontsDisplay.ts @@ -0,0 +1,40 @@ +import { Context } from "../index"; +import { Rule } from "../rule"; + +const GOOGLE_FONT_URL_PATTERN = /https?:\/\/fonts.googleapis.com\/css\?(?!(?:[\s\S]+&)?display=(?:swap|fallback|optional)(?:&|$))/i; + +/** + * This test will return an info when font-face definitions with a url + * but no fonts are preloaded. + * Font definitions with url but an additional font-display setting are ignored. + */ +export class FastGoogleFontsDisplay extends Rule { + run({ $ }: Context) { + const fonts = $( + "link[rel='stylesheet'][href^='https://fonts.googleapis.com/css']" + ); + if (!fonts.length) { + return this.pass(); + } + const results = []; + fonts.each((i, linkNode) => { + const href = $(linkNode).attr("href"); + const match = GOOGLE_FONT_URL_PATTERN.exec(href); + if (match) { + results.push( + this.warn( + `Use &display=swap|fallback|optional in Google Font stylesheet URL: ${href}` + ) + ); + } + }); + return Promise.all(results); + } + meta() { + return { + url: "https://web.dev/font-display/", + title: "Use fast font-display for Google Fonts", + info: "", + }; + } +} diff --git a/packages/linter/tests/local.test.ts b/packages/linter/tests/local.test.ts index d9d180f26..c1be65ede 100644 --- a/packages/linter/tests/local.test.ts +++ b/packages/linter/tests/local.test.ts @@ -20,7 +20,8 @@ import { IsTransformedAmp } from "../src/rules/IsTransformedAmp"; import { ModuleRuntimeUsed } from "../src/rules/ModuleRuntimeUsed"; import { BlockingExtensionsPreloaded } from "../src/rules/BlockingExtensionsPreloaded"; import { FontsArePreloaded } from "../src/rules/FontsArePreloaded"; -import { HeroImageIsDefined } from '../src/rules/HeroImageIsDefined'; +import { HeroImageIsDefined } from "../src/rules/HeroImageIsDefined"; +import { FastGoogleFontsDisplay } from "../src/rules/FastGoogleFontsDisplay"; describe(AmpImgAmpPixelPreferred.name, () => { it(`${AmpImgAmpPixelPreferred.name} - `, async () => { @@ -100,6 +101,28 @@ describe(BlockingExtensionsPreloaded.name, () => { }); }); +describe(FastGoogleFontsDisplay.name, () => { + it(`${FastGoogleFontsDisplay.name} - all fonts have display param`, async () => { + return assertPass( + runLocalTest( + FastGoogleFontsDisplay, + `${__dirname}/local/FastGoogleFontsDisplay-1/source.html` + ) + ); + }); + it(`${FastGoogleFontsDisplay.name} - no or wrong display param`, async () => { + const results = await runLocalTest( + FastGoogleFontsDisplay, + `${__dirname}/local/FastGoogleFontsDisplay-2/source.html` + ); + expect(results).toHaveLength(4); + await assertWarn(results[0]); + await assertWarn(results[1]); + await assertWarn(results[2]); + await assertWarn(results[3]); + }); +}); + describe(FontsArePreloaded.name, () => { it(`${FontsArePreloaded.name} - preload for font exists`, async () => { return assertPass( diff --git a/packages/linter/tests/local/FastGoogleFontsDisplay-1/source.html b/packages/linter/tests/local/FastGoogleFontsDisplay-1/source.html new file mode 100644 index 000000000..39f934af1 --- /dev/null +++ b/packages/linter/tests/local/FastGoogleFontsDisplay-1/source.html @@ -0,0 +1,34 @@ + + + + + + Hello, AMPs + + + + + + + + + + + + + + +

Hello, AMP!

+ + diff --git a/packages/linter/tests/local/FastGoogleFontsDisplay-2/source.html b/packages/linter/tests/local/FastGoogleFontsDisplay-2/source.html new file mode 100644 index 000000000..c4675ed0c --- /dev/null +++ b/packages/linter/tests/local/FastGoogleFontsDisplay-2/source.html @@ -0,0 +1,32 @@ + + + + + + Hello, AMPs + + + + + + + + + + + + +

Hello, AMP!

+ +