From cd2443bd09a7cf072e9b64f95301004f871acd77 Mon Sep 17 00:00:00 2001 From: Nathan Totten Date: Fri, 20 Dec 2024 09:25:19 -0800 Subject: [PATCH] Optimize CDN images (#448) * Optimize CDN images * updated cdn path * fix relative urls * use url instead of path * fixed path resolution * updated relative path --- docs/articles/api-key-administration.md | 2 +- src/DocusaurusDocsLicense.tsx | 23 +++++++++++ src/EmbeddedChat.tsx | 1 - src/mdx/static-images.ts | 52 +++++++++++++++++++++++++ zudoku.config.tsx | 6 +++ 5 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/DocusaurusDocsLicense.tsx create mode 100644 src/mdx/static-images.ts diff --git a/docs/articles/api-key-administration.md b/docs/articles/api-key-administration.md index 1a07dabe..8bf008de 100644 --- a/docs/articles/api-key-administration.md +++ b/docs/articles/api-key-administration.md @@ -31,7 +31,7 @@ the form. Once a consumer is created, you can view or copy the API Key by clicking the icons shown. -![Copy or View](/media/api-key-administration/image-5.png) +![Copy or View](../../public/media/api-key-administration/image-5.png) If you're using the Zuplo [Developer Portal](./developer-portal.md), we have an integration with the API Key API that allows developers to access their API diff --git a/src/DocusaurusDocsLicense.tsx b/src/DocusaurusDocsLicense.tsx new file mode 100644 index 00000000..a97bee6c --- /dev/null +++ b/src/DocusaurusDocsLicense.tsx @@ -0,0 +1,23 @@ +/** + * Zudoku takes inspiration from some of the great features os Docusaurus. + * As such we duplicate some of the Docusaurus documentation to provide + * a consistent experience and make migration easier. + * + * Docusaurus Docs are licensed under Creative Commons Attribution 4.0 + * International (CC BY 4.0). This means that any doc we copy content from + * needs to be attributed and linked to the original source. + */ +export function DocusaurusDocsLicense({ sourceUrl }: { sourceUrl: string }) { + return ( +

+ Portions of this document are adapted from from the{" "} + Docusaurus project, created by Meta + Platforms, Inc., and is licensed under the{" "} + + Creative Commons Attribution 4.0 International + + (CC BY 4.0) license. The original document + has been modified. +

+ ); +} diff --git a/src/EmbeddedChat.tsx b/src/EmbeddedChat.tsx index d85e6237..dde5011c 100644 --- a/src/EmbeddedChat.tsx +++ b/src/EmbeddedChat.tsx @@ -3,7 +3,6 @@ import { InkeepEmbeddedChat, type InkeepWidgetBaseSettings, } from "@inkeep/widgets"; -import React from "react"; const baseSettings: InkeepWidgetBaseSettings = { apiKey: "499c156cf7a9798343949c8bb5665ac95e48132c6d68c42e", diff --git a/src/mdx/static-images.ts b/src/mdx/static-images.ts new file mode 100644 index 00000000..ae6d01dd --- /dev/null +++ b/src/mdx/static-images.ts @@ -0,0 +1,52 @@ +import { Root } from "mdast"; +import { Plugin } from "unified"; +import { visit } from "unist-util-visit"; +import type { VFile } from "vfile"; + +/** + * Copies images from the /static folder to /public if they are referenced by a + * @returns + */ +const rehypeStaticImages: Plugin<[], Root, Root> = + () => async (root, vfile: VFile) => { + const promises: Promise[] = []; + visit(root, ["element"], (node: any, index, parent) => { + promises.push( + (async () => { + if ( + node.type === "element" && + node.tagName === "img" && + node.properties + ) { + if (!node.properties.src.startsWith("http")) { + let url = node.properties.src; + const relativePath = url.startsWith("/public/") + ? `/docs${url.substring("/public".length)}` + : url; + if (process.env.USE_IMAGE_CDN) { + node.properties.src = `https://cdn.zuplo.com${relativePath}`; + } else { + node.properties.src = relativePath; + } + } + + if ( + node.properties.src.startsWith("https://cdn.zuplo.com/") && + !node.properties.src.endsWith(".svg") && + !node.properties.src.endsWith(".gif") + ) { + const url = new URL(node.properties.src); + node.properties.srcSet = [ + `https://cdn.zuplo.com/cdn-cgi/image/fit=contain,width=640,format=auto${url.pathname} 640w`, + `https://cdn.zuplo.com/cdn-cgi/image/fit=contain,width=960,format=auto${url.pathname} 960w`, + `https://cdn.zuplo.com/cdn-cgi/image/fit=contain,width=1280,format=auto${url.pathname} 1280w`, + `https://cdn.zuplo.com/cdn-cgi/image/fit=contain,width=2560,format=auto${url.pathname} 2560w`, + ].join(", "); + } + } + })(), + ); + }); + await Promise.all(promises); + }; +export default rehypeStaticImages; diff --git a/zudoku.config.tsx b/zudoku.config.tsx index ef0d27b7..1b21c4d8 100644 --- a/zudoku.config.tsx +++ b/zudoku.config.tsx @@ -3,11 +3,13 @@ import type { ZudokuConfig } from "zudoku"; import { CogIcon, CopyIcon, FileTextIcon, ListEndIcon } from "zudoku/icons"; import { devPortal, docs, policies, programming } from "./sidebar.js"; import { BundlesTable } from "./src/BundlesTable"; +import { DocusaurusDocsLicense } from "./src/DocusaurusDocsLicense"; import { EnterpriseFeature } from "./src/EnterpriseFeature"; import { GithubButton } from "./src/GithubButton"; import { HeadNavigation } from "./src/HeadNavigation"; import { PolicyOverview } from "./src/PolicyOverview"; import ZupIt from "./src/ZupIt.js"; +import rehypeStaticImages from "./src/mdx/static-images.js"; const iconStyle = { display: "inline", verticalAlign: "-0.125em" }; @@ -15,6 +17,7 @@ const EmbeddedChat = lazy(() => import("./src/EmbeddedChat")); const mdxComponents = { Screenshot: (props: any) => , + DocusaurusDocsLicense, GithubButton, ZupIt: (props: any) => , CodeEditorTabIcon: () => , @@ -120,6 +123,9 @@ const config: ZudokuConfig = { sitemap: { siteUrl: "https://zuplo.com/docs", }, + build: { + rehypePlugins: [rehypeStaticImages], + }, }; export default config;