diff --git a/src/components/ComponentUsage.astro b/src/components/ComponentUsage.astro
index fb4cf15c63c7b33..c61b5a83b52400d 100644
--- a/src/components/ComponentUsage.astro
+++ b/src/components/ComponentUsage.astro
@@ -1,8 +1,8 @@
---
import { z } from "astro:schema";
import { getComponentsUsage } from "~/util/components";
-import { slug } from "github-slugger";
+import UsageList from "./UsageList.astro";
import Details from "./Details.astro";
type Props = z.infer;
@@ -22,70 +22,6 @@ const usage = await getComponentsUsage(component);
{usage.pages.size} pages.
- Pages
-
- {
- [...usage.pages]
- .filter((path) => path.startsWith("src/content/docs/"))
- .sort()
- .map((path) => {
- const slugified =
- "/" +
- path
- .replace("src/content/docs/", "")
- .replace(".mdx", "")
- .split("/")
- .map((segment) => slug(segment))
- .join("/") +
- "/";
-
- return (
- -
-
- {slugified}
-
-
- -
-
- Source
-
-
-
- );
- })
- }
-
- Partials
-
- {
- [...usage.pages]
- .filter((path) => path.startsWith("src/content/partials/"))
- .sort()
- .map((path) => {
- return (
- -
-
- {path}
-
-
- );
- })
- }
-
+
>
diff --git a/src/components/Details.astro b/src/components/Details.astro
index 2ac10fee8c83bb3..94be66c3bd4ece4 100644
--- a/src/components/Details.astro
+++ b/src/components/Details.astro
@@ -7,12 +7,13 @@ type Props = z.infer;
const props = z.object({
header: z.string(),
open: z.boolean().optional(),
+ id: z.string().optional(),
});
-const { header, open } = props.parse(Astro.props);
+const { header, open, id } = props.parse(Astro.props);
---
-
+
diff --git a/src/components/PartialsUsage.astro b/src/components/PartialsUsage.astro
new file mode 100644
index 000000000000000..c4d6d4435eacba9
--- /dev/null
+++ b/src/components/PartialsUsage.astro
@@ -0,0 +1,41 @@
+---
+import { getPartialsUsage } from "~/util/components";
+
+import Details from "./Details.astro";
+import UsageList from "./UsageList.astro";
+
+const partials = await getPartialsUsage();
+---
+
+
+ {
+ [...Object.entries(partials)]
+ .sort((a, b) => a[0].localeCompare(b[0]))
+ .map(([name, usage]) => (
+
+
+
+ ))
+ }
+
+
+
diff --git a/src/components/UsageList.astro b/src/components/UsageList.astro
new file mode 100644
index 000000000000000..4fb06cb78e45205
--- /dev/null
+++ b/src/components/UsageList.astro
@@ -0,0 +1,93 @@
+---
+import { z } from "astro:schema";
+import { slug } from "github-slugger";
+
+const props = z.object({
+ usage: z.object({
+ count: z.number(),
+ pages: z.set(z.string()),
+ }),
+});
+
+const { usage } = props.parse(Astro.props);
+---
+
+<>
+
+ Used {usage.count} times.
+
+
+ Pages
+
+
+ {
+ [...usage.pages]
+ .filter((path) => path.startsWith("src/content/docs/"))
+ .sort()
+ .map((path) => {
+ const slugified =
+ "/" +
+ path
+ .replace("src/content/docs/", "")
+ .replace(".mdx", "")
+ .split("/")
+ .map((segment) => {
+ if (segment === "1.1.1.1") {
+ return segment;
+ }
+ return slug(segment);
+ })
+ .join("/") +
+ "/";
+
+ return (
+ -
+
+ {slugified}
+
+
+ -
+
+ Source
+
+
+
+ );
+ })
+ }
+
+
+ Partials
+
+
+ {
+ [...usage.pages]
+ .filter((path) => path.startsWith("src/content/partials/"))
+ .sort()
+ .map((path) => {
+ return (
+ -
+
+ {path}
+
+
+ );
+ })
+ }
+
+>
diff --git a/src/components/index.ts b/src/components/index.ts
index f401e399bbc8e96..ce408887cbbcf14 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -41,6 +41,7 @@ export { default as PagesBuildEnvironmentTools } from "./PagesBuildEnvironmentTo
export { default as PagesBuildPreset } from "./PagesBuildPreset.astro";
export { default as PagesBuildPresetsTable } from "./PagesBuildPresetsTable.astro";
export { default as PagesLanguageSupport } from "./PagesLanguageSupport.astro";
+export { default as PartialsUsage } from "./PartialsUsage.astro";
export { default as Plan } from "./Plan.astro";
export { default as PlanInfo } from "./PlanInfo.astro";
export { default as ProductChangelog } from "./ProductChangelog.astro";
diff --git a/src/content/docs/style-guide/components/render.mdx b/src/content/docs/style-guide/components/render.mdx
index 7cdb26fcce192cc..c3bbfc04e602ad0 100644
--- a/src/content/docs/style-guide/components/render.mdx
+++ b/src/content/docs/style-guide/components/render.mdx
@@ -4,7 +4,7 @@ styleGuide:
component: Render
---
-import { Code, Details, Type, MetaInfo } from "~/components";
+import { Code, Details, Type, MetaInfo, PartialsUsage } from "~/components";
The `Render` component allows us to include a "partial", a reusable Markdown snippet, onto a page.
@@ -15,40 +15,43 @@ It also accepts parameters that can be used as variables within the partial, so
```mdx live
import { Render } from "~/components";
-
+
```
### Inputs
- `file`
- This should be the name of the partial, without the containing directory or file extension. For example, `/partials/style-guide/hello.mdx` would be `file="hello"`.
+ This should be the name of the partial, without the containing directory or file extension. For example, `/partials/style-guide/hello.mdx` would be `file="hello"`.
- `product`
- By default, it will look for partials in the same product folder as the current page. You can use this to specify a different product.
+ By default, it will look for partials in the same product folder as the current page. You can use this to specify a different product.
- :::caution
+ :::caution
- When using the `Render` component inside partials, the original `product` is lost.
+ When using the `Render` component inside partials, the original `product` is lost.
- For example, if there are three files:
+ For example, if there are three files:
- 1. `docs/fundamentals/index.mdx`
- 2. `partials/dns/thing.mdx`
- 3. `partials/dns/thing2.mdx`
+ 1. `docs/fundamentals/index.mdx`
+ 2. `partials/dns/thing.mdx`
+ 3. `partials/dns/thing2.mdx`
- `docs/fundamentals/index.mdx` uses ``
+ `docs/fundamentals/index.mdx` uses ``
- `partials/dns/thing.mdx` must use `` as `product` cannot be inferred.
+ `partials/dns/thing.mdx` must use `` as `product` cannot be inferred.
- :::
+ :::
- `params`
- If you wish to substitute values inside your partial, you can use pass params which can be referenced in your partial. Refer to [properties](#properties).
+ If you wish to substitute values inside your partial, you can use pass params which can be referenced in your partial. Refer to [properties](#properties).
## Properties
@@ -128,9 +131,12 @@ import linkRaw from "~/content/partials/style-guide/link-in-props.mdx?raw";
```mdx live
import { Render } from "~/components";
-
+
```
#### Images
@@ -185,4 +191,8 @@ import { Render } from "~/components";
-```
\ No newline at end of file
+```
+
+## Partials
+
+
diff --git a/src/util/components.ts b/src/util/components.ts
index 7aac65ac48bf345..65d8063f8e06fd5 100644
--- a/src/util/components.ts
+++ b/src/util/components.ts
@@ -12,6 +12,7 @@ import { visit } from "unist-util-visit";
type Usage = { count: number; pages: Set };
let usages: Record;
+let partials: Record;
export function getComponentsUsage(): Promise>;
export function getComponentsUsage(component: string): Promise;
@@ -60,3 +61,60 @@ export async function getComponentsUsage(
return usages;
}
+
+export async function getPartialsUsage(): Promise> {
+ if (!partials) {
+ partials = {};
+
+ const entities = await readdir("./src/content/", {
+ recursive: true,
+ withFileTypes: true,
+ });
+
+ const files = entities.filter(
+ (entity) => entity.isFile() && entity.name.endsWith(".mdx"),
+ );
+
+ for (const file of files) {
+ const fullName = file.parentPath + "/" + file.name;
+ const content = await readFile(fullName, "utf8");
+
+ if (!content.includes("import")) continue;
+
+ const tree = fromMarkdown(content, {
+ extensions: [mdxjs()],
+ mdastExtensions: [mdxFromMarkdown()],
+ });
+
+ visit(tree, ["mdxJsxFlowElement", "mdxJsxTextElement"], function (node) {
+ const typed = node as MdxJsxFlowElement | MdxJsxTextElement;
+
+ if (!typed.name || typed.name[0] === typed.name[0].toLowerCase())
+ return;
+
+ if (typed.name === "Render") {
+ const file = typed.attributes.find(
+ (attr) => attr.type === "mdxJsxAttribute" && attr.name === "file",
+ )?.value;
+
+ let product = typed.attributes.find(
+ (attr) =>
+ attr.type === "mdxJsxAttribute" && attr.name === "product",
+ )?.value;
+
+ if (!product) {
+ product = fullName.split("/")[3];
+ }
+
+ const partialName = `${product}/${file}`;
+
+ partials[partialName] ||= { count: 0, pages: new Set() };
+ partials[partialName].count++;
+ partials[partialName].pages.add(fullName);
+ }
+ });
+ }
+ }
+
+ return partials;
+}