diff --git a/package-lock.json b/package-lock.json
index 4a63f482..5320a3fc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,4 +1,6 @@
- "version": "2.17.1",
+{
+ "name": "@quintype/amp",
+ "version": "2.17.2-custom-fonts.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
diff --git a/package.json b/package.json
index 9ae34222..08c01a3d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@quintype/amp",
- "version": "2.17.1",
+ "version": "2.17.2-custom-fonts.0",
"description": "Quintype's AMP component library for publisher apps to create amp layouts",
"main": "dist/index.js",
"types": "dist/index.d.ts",
diff --git a/src/__fixtures__/config.fixture.tsx b/src/__fixtures__/config.fixture.tsx
index 8289235b..b2f39567 100644
--- a/src/__fixtures__/config.fixture.tsx
+++ b/src/__fixtures__/config.fixture.tsx
@@ -581,7 +581,8 @@ export const ampConfig: AMPConfig = {
secondary: {
url: "PT+Serif:400,400italic,700,700italic",
family: "'PT Serif', sans-serif"
- }
+ },
+ custom: "https://fonts.googleapis.com/css?family=Tangerine"
},
colors: {
primary: "#294f32",
diff --git a/src/atoms/fonts/__snapshots__/fonts.test.tsx.snap b/src/atoms/fonts/__snapshots__/fonts.test.tsx.snap
index 63998fd7..c8b4ffdf 100644
--- a/src/atoms/fonts/__snapshots__/fonts.test.tsx.snap
+++ b/src/atoms/fonts/__snapshots__/fonts.test.tsx.snap
@@ -22,5 +22,29 @@ exports[`Fonts component Should match snapshot 1`] = `
href="https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap"
rel="preload"
/>
+
+
+
+
`;
diff --git a/src/atoms/fonts/fonts.test.tsx b/src/atoms/fonts/fonts.test.tsx
index 4b73f67f..ef997c5b 100644
--- a/src/atoms/fonts/fonts.test.tsx
+++ b/src/atoms/fonts/fonts.test.tsx
@@ -14,9 +14,20 @@ const dummyConfig = {
family: '"Mukta Malar",sans-serif'
}
}
+ },
+ opts: {
+ render: {
+ customFonts: {
+ primary1: "https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold1.woff2",
+ secondary1: "https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular1.woff2",
+ primary2: "https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold2.woff2",
+ secondary2: "https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular2.woff2"
+ }
+ }
}
};
+
describe("Fonts component", () => {
it("Should match snapshot", () => {
const wrapper = shallow();
@@ -73,4 +84,388 @@ describe("Fonts component", () => {
.prop("href")
).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap");
});
+ it("Should preconnect to fonts provider and preload custom primary 1 font when passed on opts object", () => {
+ const wrapper = shallow();
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("rel")
+ ).toBe("preconnect dns-prefetch");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:300,400,600,700&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold1.woff2");
+ });
+ it("Should preconnect to fonts provider and preload custom secondary 1 font when passed on opts object", () => {
+ const wrapper = shallow();
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("rel")
+ ).toBe("preconnect dns-prefetch");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:300,400,600,700&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold1.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular1.woff2");
+ });
+ it("Should preconnect to fonts provider and preload custom primary 2 font when passed on opts object", () => {
+ const wrapper = shallow();
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("rel")
+ ).toBe("preconnect dns-prefetch");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:300,400,600,700&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold1.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular1.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold2.woff2");
+ });
+ it("Should preconnect to fonts provider and preload custom secondary 2 font when passed on opts object", () => {
+ const wrapper = shallow();
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("rel")
+ ).toBe("preconnect dns-prefetch");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(0)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(1)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:300,400,600,700&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(2)
+ .prop("href")
+ ).toBe("https://fonts.googleapis.com/css?family=Mukta+Malar:400,400italic,700,700italic&display=swap");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(3)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold1.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(4)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular1.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(5)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold2.woff2");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(6)
+ .prop("rel")
+ ).toBe("preload");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(6)
+ .prop("crossorigin")
+ ).toBe("anonymous");
+ expect(
+ wrapper
+ .find(`link`)
+ .at(6)
+ .prop("href")
+ ).toBe("https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular2.woff2");
+ });
});
diff --git a/src/atoms/fonts/fonts.tsx b/src/atoms/fonts/fonts.tsx
index 209458b8..6275a8fe 100644
--- a/src/atoms/fonts/fonts.tsx
+++ b/src/atoms/fonts/fonts.tsx
@@ -1,10 +1,11 @@
import React from "react";
import { Helmet } from "react-helmet";
import { withStoryAndConfig } from "../../context";
+import get from "lodash.get";
export const FontsBase = ({ config }) => {
const { primary, secondary } = config.ampConfig.fonts;
-
+ const customFonts = get(config, ["opts", "render", "customFonts"], null);
return (
@@ -20,8 +21,49 @@ export const FontsBase = ({ config }) => {
crossorigin="anonymous"
href={`https://fonts.googleapis.com/css?family=${secondary.url}&display=swap`}
/>
+
+
+
+
);
};
+/**
+ * Amp library supports google fonts as well as custom fonts. This Fonts component accepts primary and secondary google fonts from BOlD AMP settings `settings > configure > AMP` and four different custom fonts from render props `customFonts`. These custom font urls are passed to the link tags that are preloaded.
+ * In case customFonts is passed in the config, it is rendered along with the fonts mentioned in BOLD.
+ *
+ * Custom fonts can be hosted on allowed origins or can be added in the public folder of your app.
+ * If added in public folder, mention the asset host and path in the url like this "https://fea.assettype.com/malibu/assets/
+ MalibuHeadlineSemiBold.woff2".
+ *
+ * The following origins are allowlisted and allowed for font serving via link tags as per official AMP documentation:
+ *
+ * Typography.com: https://cloud.typography.com
+ * Fonts.com: https://fast.fonts.net
+ * Google Fonts: https://fonts.googleapis.com
+ * Typekit: https://use.typekit.net
+ * Font Awesome: https://maxcdn.bootstrapcdn.com, https://use.fontawesome.com
+ *
+ *
+ * ```javascript
+ * ...
+ * ampRoutes(app, {
+ * render: {
+ * customFonts?: {
+ primary1?: "https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold.woff2";
+ secondary1?: "https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular.woff2";
+ primary2?: "https://fea.assettype.com/malibu/assets/MalibuHeadlineSemiBold2.woff2";
+ secondary2?: "https://fea.assettype.com/malibu/assets/MalibuHeadlineTextRegular2.woff2";
+ };
+ * }
+ * })
+ * ...
+ * ```
+ *
+ * @category Atoms
+ * @module Fonts
+ * @component
+ */
+
export const Fonts = withStoryAndConfig(FontsBase);
diff --git a/src/atoms/subscriptions/subscriptions-paywall/__snapshots__/subscription-paywall.test.tsx.snap b/src/atoms/subscriptions/subscriptions-paywall/__snapshots__/subscription-paywall.test.tsx.snap
index c2d717f2..86902e74 100644
--- a/src/atoms/subscriptions/subscriptions-paywall/__snapshots__/subscription-paywall.test.tsx.snap
+++ b/src/atoms/subscriptions/subscriptions-paywall/__snapshots__/subscription-paywall.test.tsx.snap
@@ -43,6 +43,7 @@ exports[`Subscriptions should render subscriptions 1`] = `
},
},
"fonts": Object {
+ "custom": "https://fonts.googleapis.com/css?family=Tangerine",
"primary": Object {
"family": "\\"Open Sans\\", sans-serif",
"url": "Open+Sans:300,400,600,700",
diff --git a/src/molecules/related-stories/__snapshots__/related-stories.test.tsx.snap b/src/molecules/related-stories/__snapshots__/related-stories.test.tsx.snap
index 7fcac687..468ca1cd 100644
--- a/src/molecules/related-stories/__snapshots__/related-stories.test.tsx.snap
+++ b/src/molecules/related-stories/__snapshots__/related-stories.test.tsx.snap
@@ -44,6 +44,7 @@ exports[`RelatedStories should render default 1`] = `
},
},
"fonts": Object {
+ "custom": "https://fonts.googleapis.com/css?family=Tangerine",
"primary": Object {
"family": "\\"Open Sans\\", sans-serif",
"url": "Open+Sans:300,400,600,700",
diff --git a/src/templates/generic-story/__snapshots__/generic-story.test.tsx.snap b/src/templates/generic-story/__snapshots__/generic-story.test.tsx.snap
index 98e1b81d..25dd46e5 100644
--- a/src/templates/generic-story/__snapshots__/generic-story.test.tsx.snap
+++ b/src/templates/generic-story/__snapshots__/generic-story.test.tsx.snap
@@ -43,6 +43,7 @@ exports[`GenericStory Template should render 1`] = `
},
},
"fonts": Object {
+ "custom": "https://fonts.googleapis.com/css?family=Tangerine",
"primary": Object {
"family": "\\"Open Sans\\", sans-serif",
"url": "Open+Sans:300,400,600,700",
diff --git a/src/templates/live-blog/__snapshots__/live-blog.validation.test.tsx.snap b/src/templates/live-blog/__snapshots__/live-blog.validation.test.tsx.snap
index f8a62320..0e24c11e 100644
--- a/src/templates/live-blog/__snapshots__/live-blog.validation.test.tsx.snap
+++ b/src/templates/live-blog/__snapshots__/live-blog.validation.test.tsx.snap
@@ -43,6 +43,7 @@ exports[`The LiveBlog Default Template should match snapshot 1`] = `
},
},
"fonts": Object {
+ "custom": "https://fonts.googleapis.com/css?family=Tangerine",
"primary": Object {
"family": "\\"Open Sans\\", sans-serif",
"url": "Open+Sans:300,400,600,700",
diff --git a/src/templates/visual-story/__snapshots__/visual-story.test.tsx.snap b/src/templates/visual-story/__snapshots__/visual-story.test.tsx.snap
index 869629e1..731c2286 100644
--- a/src/templates/visual-story/__snapshots__/visual-story.test.tsx.snap
+++ b/src/templates/visual-story/__snapshots__/visual-story.test.tsx.snap
@@ -43,6 +43,7 @@ exports[`visual story template should match snapshot 1`] = `
},
},
"fonts": Object {
+ "custom": "https://fonts.googleapis.com/css?family=Tangerine",
"primary": Object {
"family": "\\"Open Sans\\", sans-serif",
"url": "Open+Sans:300,400,600,700",
diff --git a/src/types/config.ts b/src/types/config.ts
index 15ae703f..4d95ac31 100644
--- a/src/types/config.ts
+++ b/src/types/config.ts
@@ -73,6 +73,7 @@ export interface AMPConfig {
url: string;
family: string;
};
+ custom: string;
};
colors: Colors;
"logo-url": string;
@@ -151,6 +152,12 @@ export interface ConfigOpts {
templates?: object;
slots?: SlotsTypes;
render?: {
+ customFonts?: {
+ primary1?: string | null;
+ secondary1?: string | null;
+ primary2?: string | null;
+ secondary2?: string | null;
+ };
headerCardRender?: (props: Config) => any;
navbarRender?: (props: NavbarTypes) => any;
relatedStoriesRender?: (props: RelatedStoriesRenderPropTypes) => any;