From e14e798af83661467f04433e50c209a6130ea307 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Fri, 21 Nov 2025 14:32:55 +0100 Subject: [PATCH 1/3] wip --- astro.config.mjs | 2 + .../foundamentals/components/_default.mdx | 1 + .../foundamentals/components/card.mdx | 15 ++ .../getting-started/getting-started.mdx | 3 + .../content/card-group/card-group.astro | 7 + .../components/content/card-group/card.astro | 6 + src/lib/components/content/codeblock.astro | 10 ++ src/lib/plugins/parser/block-renderer.astro | 72 ++++++++++ src/lib/plugins/parser/dynamic-block.astro | 23 +++ src/lib/plugins/parser/plugin.ts | 135 ++++++++++++++++++ src/lib/plugins/parser/selectors.ts | 25 ++++ src/pages/docs/[...slug].astro | 5 +- 12 files changed, 303 insertions(+), 1 deletion(-) create mode 100644 content/docs/documentation/foundamentals/components/card.mdx create mode 100644 src/lib/components/content/card-group/card-group.astro create mode 100644 src/lib/components/content/card-group/card.astro create mode 100644 src/lib/components/content/codeblock.astro create mode 100644 src/lib/plugins/parser/block-renderer.astro create mode 100644 src/lib/plugins/parser/dynamic-block.astro create mode 100644 src/lib/plugins/parser/plugin.ts create mode 100644 src/lib/plugins/parser/selectors.ts diff --git a/astro.config.mjs b/astro.config.mjs index e063390..ff1d61c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -18,6 +18,7 @@ import rehypeMermaid from "rehype-mermaid"; import rehypeCodeGroupReact from "./src/lib/plugins/code-group/plugin"; import rehypeReadMoreReact from "./src/lib/plugins/read-more/plugin"; import rehypeBlogListReact from "./src/lib/plugins/blog-list/plugin"; +import rehypeBlock from "./src/lib/plugins/parser/plugin"; import { default as remarkDirective, default as remarkReadMoreDirective, @@ -51,6 +52,7 @@ export default defineConfig({ }, remarkPlugins: [remarkDirective, remarkReadMoreDirective], rehypePlugins: [ + rehypeBlock, rehypeMermaid, [ rehypeCallouts, diff --git a/content/docs/documentation/foundamentals/components/_default.mdx b/content/docs/documentation/foundamentals/components/_default.mdx index 5fe6643..ef423f2 100644 --- a/content/docs/documentation/foundamentals/components/_default.mdx +++ b/content/docs/documentation/foundamentals/components/_default.mdx @@ -9,4 +9,5 @@ collection: - code-block - markdown - text + - card --- diff --git a/content/docs/documentation/foundamentals/components/card.mdx b/content/docs/documentation/foundamentals/components/card.mdx new file mode 100644 index 0000000..316400f --- /dev/null +++ b/content/docs/documentation/foundamentals/components/card.mdx @@ -0,0 +1,15 @@ +--- +title: Card +description: Lorem ipsum dolor sit amet, consectetur adipiscing elit. +permalink: card +icon: lucide:bell +--- + +:::card-group{col="2"} +:::card{label="Test", icon="lucide:bell"} +test +::: +:::card{label="Test", icon="lucide:bell"} +d +::: +::: diff --git a/content/docs/documentation/getting-started/getting-started.mdx b/content/docs/documentation/getting-started/getting-started.mdx index 3895dcd..af3f875 100644 --- a/content/docs/documentation/getting-started/getting-started.mdx +++ b/content/docs/documentation/getting-started/getting-started.mdx @@ -10,3 +10,6 @@ icon: lucide:info ## Introduction Explainer provides a rich set of components that can be used directly in your Markdown files. This documentation outlines the various markdown components available for creating beautiful, interactive documentation. + +:::card-group{cols=2} +::: diff --git a/src/lib/components/content/card-group/card-group.astro b/src/lib/components/content/card-group/card-group.astro new file mode 100644 index 0000000..d533d95 --- /dev/null +++ b/src/lib/components/content/card-group/card-group.astro @@ -0,0 +1,7 @@ +--- +const props = Astro.props; +--- + +
+ +
diff --git a/src/lib/components/content/card-group/card.astro b/src/lib/components/content/card-group/card.astro new file mode 100644 index 0000000..c021185 --- /dev/null +++ b/src/lib/components/content/card-group/card.astro @@ -0,0 +1,6 @@ +--- +const props = Astro.props; +console.log("Card", props); +--- + +
Card
diff --git a/src/lib/components/content/codeblock.astro b/src/lib/components/content/codeblock.astro new file mode 100644 index 0000000..b36dac6 --- /dev/null +++ b/src/lib/components/content/codeblock.astro @@ -0,0 +1,10 @@ +--- +const props = Astro.props; +--- + +

+

+

diff --git a/src/lib/plugins/parser/block-renderer.astro b/src/lib/plugins/parser/block-renderer.astro new file mode 100644 index 0000000..ac1d1dc --- /dev/null +++ b/src/lib/plugins/parser/block-renderer.astro @@ -0,0 +1,72 @@ +--- +import CardGroup from "@/components/content/card-group/card-group.astro"; +import Card from "@/components/content/card-group/card.astro"; +import BlockDynamic from "./dynamic-block.astro"; + +interface ASTNode { + delimiter?: string; + startTag?: string; + attributes?: Record; + children?: Array; + type?: string; +} + +const mdx: Record = { + "card-group": CardGroup, + card: Card, +}; + +const { ast } = Astro.props as { ast: string | undefined }; +if (!ast) return null; + +const node: ASTNode | ASTNode[] = JSON.parse(ast); + +const renderNodeData = ( + block: ASTNode | { type: "text"; value: string } | undefined, +): any => { + if (!block) return null; + + if (Array.isArray(block)) { + return block.flatMap(renderNodeData).filter(Boolean); + } + + if (typeof block !== "object") return block; + + if ("type" in block && block.type === "text") return block.value; + + const Component = mdx[block.startTag || ""]; + + // Si aucun composant trouvé, on rend les enfants directement (raw / code / span) + const childrenRendered = + block.children?.flatMap(renderNodeData).filter(Boolean) || []; + + if (!Component) { + // Rendu direct des enfants + return childrenRendered; + } + + return { + component: Component, + props: block.attributes || {}, + children: childrenRendered, + }; +}; + +const treeData = Array.isArray(node) + ? node.flatMap(renderNodeData).filter(Boolean) + : renderNodeData(node); +--- + +{ + treeData.map((node: any, i: number) => { + if (typeof node === "string") return node; + return ( + + ); + }) +} diff --git a/src/lib/plugins/parser/dynamic-block.astro b/src/lib/plugins/parser/dynamic-block.astro new file mode 100644 index 0000000..1ef7a83 --- /dev/null +++ b/src/lib/plugins/parser/dynamic-block.astro @@ -0,0 +1,23 @@ +--- +import DynamicBlockRenderer from "./dynamic-block.astro"; +const { component: Component, props, children } = Astro.props; + +const childrenArray = Array.isArray(children) + ? children + : [children].filter(Boolean); +--- + + + { + childrenArray.map((child: any) => { + if (typeof child === "string") return child; + return ( + + ); + }) + } + diff --git a/src/lib/plugins/parser/plugin.ts b/src/lib/plugins/parser/plugin.ts new file mode 100644 index 0000000..d983d03 --- /dev/null +++ b/src/lib/plugins/parser/plugin.ts @@ -0,0 +1,135 @@ +import type { Element, Root } from "unist"; +import { visit } from "unist-util-visit"; + +// Exemple de mapping startTag -> composant Astro +const mdx: Record = { + "card-group": "CardGroup", + card: "Card", +}; + +interface Block { + delimiter: string; + startTag: string; + attributes: Record; + children: Array; +} + +// Parse les attributs de la ligne :::tag key="value" +const parseAttributes = (str: string): Record => { + const regex = /(\w+)\s*=\s*(?:"([^"]*)"|(\S+))/g; + const attrs: Record = {}; + let match: RegExpExecArray | null; + + while ((match = regex.exec(str)) !== null) { + const key = match[1]; + let value: any; + + if (match[2] !== undefined) { + // Valeur entre guillemets + const raw = match[2]; + try { + value = JSON.parse(raw); // Essayer de parser JSON + } catch { + value = raw; // fallback string + } + } else if (match[3] !== undefined) { + // Valeur non-quoted (true, false, number, etc.) + const raw = match[3]; + if (raw === "true") value = true; + else if (raw === "false") value = false; + else if (!isNaN(Number(raw))) value = Number(raw); + else value = raw; + } + + attrs[key] = value; + } + + return attrs; +}; + +// Fonction principale : parse un node et retourne un Block[] +const parseSingleNode = (node: Element): Block[] => { + // On combine le node text + mdxTextExpression éventuel en un seul texte + let combinedText = ""; + + for (const child of node.children || []) { + if (child.type === "text") { + combinedText += child.value; + } else if ((child as any).type === "mdxTextExpression") { + combinedText += " " + (child as any).value; + } + } + + // Fonction récursive interne pour parser un texte complet + const parseBlockText = (text: string): Block[] => { + const blocks: Block[] = []; + const lines = text.split(/\r?\n/); + const stack: Block[] = []; + + for (const line of lines) { + const startMatch = line.match(/^:::(\w[\w-]*)\s*(.*)$/); + const endMatch = line.match(/^:::/); + + if (startMatch) { + const block: Block = { + delimiter: ":::", + startTag: startMatch[1], + attributes: parseAttributes(startMatch[2] || ""), + children: [], + }; + + if (stack.length > 0) { + // Ajoute comme enfant du dernier parent + stack[stack.length - 1].children.push(block); + } else { + // Bloc racine + blocks.push(block); + } + + stack.push(block); // push pour gérer la fermeture + } else if (endMatch) { + stack.pop(); // on ferme le bloc courant + } else { + if (stack.length > 0) { + stack[stack.length - 1].children.push({ type: "text", value: line }); + } + } + } + + // Pousser tout bloc restant dans stack (blocs non fermés) + while (stack.length > 0) { + const remaining = stack.pop()!; + if (stack.length > 0) { + stack[stack.length - 1].children.push(remaining); + } else if (!blocks.includes(remaining)) { + blocks.push(remaining); + } + } + + return blocks; + }; + + return parseBlockText(combinedText); +}; + +// Plugin rehype +export default function rehypeComponents() { + return (tree: Root) => { + visit(tree, "element", (node: Element, index, parent) => { + if (!parent) return; + + const parsedBlocks = parseSingleNode(node); + + console.log(JSON.stringify(parsedBlocks, null, 2)); + + parent.children[index] = { + type: "element", + tagName: "BlockRenderer", + properties: { + ast: JSON.stringify(parsedBlocks), + }, + children: [], + } as Element; + }); + }; +} diff --git a/src/lib/plugins/parser/selectors.ts b/src/lib/plugins/parser/selectors.ts new file mode 100644 index 0000000..960aba7 --- /dev/null +++ b/src/lib/plugins/parser/selectors.ts @@ -0,0 +1,25 @@ +import { toHtml } from "hast-util-to-html"; + +export const codeblockSelector = { + filter: (child: any) => { + return child.tagName === "code" && child.children[0].type !== "text"; + }, + metadata: (child: any) => ({ + delimiter: "", + startTag: "codeblock", + attributes: { html: toHtml(child) }, + children: [], + }), +}; + +export const cardGroupSelector = { + filter: (child: any) => { + return child.tagName === "card-group"; + }, + metadata: (child: any) => ({ + delimiter: "", + startTag: "card-group", + attributes: child.attributes, + children: child.children, + }), +}; diff --git a/src/pages/docs/[...slug].astro b/src/pages/docs/[...slug].astro index 8daab4a..de5a81e 100644 --- a/src/pages/docs/[...slug].astro +++ b/src/pages/docs/[...slug].astro @@ -16,6 +16,7 @@ import * as astroContent from "astro:content"; import DocNavigationWrapper from "@/components/elements/DocNavigationWrapper.astro"; import { Icon } from "@iconify/react"; import BlogListWrapper from "@/plugins/blog-list/BlogListWrapper.astro"; +import BlockRenderer from "@/plugins/parser/block-renderer.astro"; interface Props { element: CollectionEntry<"blog">; } @@ -97,7 +98,9 @@ function pascalCase(str: string) {
- +
Date: Fri, 21 Nov 2025 15:00:31 +0100 Subject: [PATCH 2/3] feat: implement card-group mdx renderer --- .../foundamentals/components/card.mdx | 4 +- .../content/card-group/card-group.astro | 22 ++- .../components/content/card-group/card.astro | 27 +++- src/lib/plugins/card-group/plugin.ts | 126 ++++++++++++++++++ src/lib/plugins/parser/block-renderer.astro | 8 +- src/lib/plugins/parser/plugin.ts | 44 +++--- 6 files changed, 195 insertions(+), 36 deletions(-) create mode 100644 src/lib/plugins/card-group/plugin.ts diff --git a/content/docs/documentation/foundamentals/components/card.mdx b/content/docs/documentation/foundamentals/components/card.mdx index 316400f..f8147c5 100644 --- a/content/docs/documentation/foundamentals/components/card.mdx +++ b/content/docs/documentation/foundamentals/components/card.mdx @@ -5,7 +5,9 @@ permalink: card icon: lucide:bell --- -:::card-group{col="2"} +# Card + +:::card-group{cols=4, test="test"} :::card{label="Test", icon="lucide:bell"} test ::: diff --git a/src/lib/components/content/card-group/card-group.astro b/src/lib/components/content/card-group/card-group.astro index d533d95..83253a0 100644 --- a/src/lib/components/content/card-group/card-group.astro +++ b/src/lib/components/content/card-group/card-group.astro @@ -1,7 +1,25 @@ --- -const props = Astro.props; +type Props = { + cols?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; +}; + +const { cols } = Astro.props; +const gridCols = { + 1: "grid-cols-1", + 2: "grid-cols-2", + 3: "grid-cols-3", + 4: "grid-cols-4", + 5: "grid-cols-5", + 6: "grid-cols-6", + 7: "grid-cols-7", + 8: "grid-cols-8", + 9: "grid-cols-9", + 10: "grid-cols-10", + 11: "grid-cols-11", + 12: "grid-cols-12", +}; --- -
+
diff --git a/src/lib/components/content/card-group/card.astro b/src/lib/components/content/card-group/card.astro index c021185..de7fdaf 100644 --- a/src/lib/components/content/card-group/card.astro +++ b/src/lib/components/content/card-group/card.astro @@ -1,6 +1,31 @@ --- +import { Icon } from "@iconify/react"; + +type props = { + label: string; + icon?: string; +}; + const props = Astro.props; console.log("Card", props); --- -
Card
+
+
+ +
+
+

{props.label}

+

+ +

+
+
diff --git a/src/lib/plugins/card-group/plugin.ts b/src/lib/plugins/card-group/plugin.ts new file mode 100644 index 0000000..b472f15 --- /dev/null +++ b/src/lib/plugins/card-group/plugin.ts @@ -0,0 +1,126 @@ +import type { Root } from "unist"; +import { visit } from "unist-util-visit"; +import { CodeBlockSelector } from "./selector"; + +// Exemple de mapping startTag -> composant Astro +const mdx: Record = { + "card-group": "CardGroup", + card: "Card", + codeblock: "Codeblock", +}; + +interface Block { + delimiter: string; + startTag: string; + attributes: Record; + children: Array; +} + +const parseAttributes = (str: string): Record => { + const regex = /(\w+)\s*=\s*(?:"([^"]*)"|(\S+))/g; + const attrs: Record = {}; + let match; + + while ((match = regex.exec(str)) !== null) { + const key = match[1]; + let value: any; + + // Valeur entre guillemets + if (match[2] !== undefined) { + const raw = match[2]; + + // Essayer de parser JSON (array, object, number, boolean) + try { + value = JSON.parse(raw); + } catch { + value = raw; // fallback string + } + } else if (match[3] !== undefined) { + // Valeur non-quoted (true, false, number, etc.) + const raw = match[3]; + if (raw === "true") value = true; + else if (raw === "false") value = false; + else if (!isNaN(Number(raw))) value = Number(raw); + else value = raw; + } + + attrs[key] = value; + } + + return attrs; +}; + +const parseSingleNode = (node: { type: string; children?: any[] }): Block[] => { + const parseChildren = (children: any[]): Block[] => { + const blocks: Block[] = []; + const stack: Block[] = []; + + for (const child of children) { + if (child.type === "text" || child.type === "mdxTextExpression") { + const lines = child.value.split(/\r?\n/); + for (const line of lines) { + const startMatch = line.match(/^:::(\w[\w-]*)\s*(.*)$/); + const endMatch = line.match(/^:::/); + + if (startMatch) { + const block: Block = { + delimiter: ":::", + startTag: startMatch[1], + attributes: parseAttributes(startMatch[2] || ""), + children: [], + }; + stack.push(block); + } else if (endMatch) { + const finished = stack.pop(); + if (!finished) continue; + if (stack.length > 0) { + stack[stack.length - 1].children.push(finished); + } else { + blocks.push(finished); + } + } else { + if (stack.length > 0) { + stack[stack.length - 1].children.push({ + type: "text", + value: line, + }); + } + } + } + } else if (child.type === "element") { + const availableBlock = [CodeBlockSelector]; + const selector = availableBlock.find((selector) => + selector.filter(child), + ); + + if (selector) { + if (stack.length > 0) { + stack[stack.length - 1].children.push(selector.render(child)); + } else { + blocks.push(selector.render(child)); + } + } + } + } + + return blocks; + }; + + return parseChildren(node.children || []); +}; + +// Usage dans rehypeComponents +export default function rehypeComponents(): Plugin<[], Root> { + return (tree: Root) => { + visit(tree, "element", (node, index, parent) => { + const parsedBlocks = parseSingleNode(node); + + parent.children[index] = { + type: "element", + tagName: "BlockRenderer", + properties: { ast: JSON.stringify(parsedBlocks) }, + children: [], // ou des enfants si nécessaire + }; + }); + }; +} diff --git a/src/lib/plugins/parser/block-renderer.astro b/src/lib/plugins/parser/block-renderer.astro index ac1d1dc..3259e8a 100644 --- a/src/lib/plugins/parser/block-renderer.astro +++ b/src/lib/plugins/parser/block-renderer.astro @@ -21,9 +21,7 @@ if (!ast) return null; const node: ASTNode | ASTNode[] = JSON.parse(ast); -const renderNodeData = ( - block: ASTNode | { type: "text"; value: string } | undefined, -): any => { +const renderNodeData = (block: any): any => { if (!block) return null; if (Array.isArray(block)) { @@ -34,14 +32,12 @@ const renderNodeData = ( if ("type" in block && block.type === "text") return block.value; - const Component = mdx[block.startTag || ""]; + const Component = mdx[block.startTag ?? ""]; - // Si aucun composant trouvé, on rend les enfants directement (raw / code / span) const childrenRendered = block.children?.flatMap(renderNodeData).filter(Boolean) || []; if (!Component) { - // Rendu direct des enfants return childrenRendered; } diff --git a/src/lib/plugins/parser/plugin.ts b/src/lib/plugins/parser/plugin.ts index d983d03..3f42efd 100644 --- a/src/lib/plugins/parser/plugin.ts +++ b/src/lib/plugins/parser/plugin.ts @@ -1,7 +1,6 @@ import type { Element, Root } from "unist"; import { visit } from "unist-util-visit"; -// Exemple de mapping startTag -> composant Astro const mdx: Record = { "card-group": "CardGroup", card: "Card", @@ -14,27 +13,24 @@ interface Block { children: Array; } -// Parse les attributs de la ligne :::tag key="value" const parseAttributes = (str: string): Record => { - const regex = /(\w+)\s*=\s*(?:"([^"]*)"|(\S+))/g; + const regex = /(\w+)\s*=\s*(?:"([^"]*)"|([^,\s]+))/g; const attrs: Record = {}; let match: RegExpExecArray | null; while ((match = regex.exec(str)) !== null) { const key = match[1]; let value: any; - if (match[2] !== undefined) { - // Valeur entre guillemets const raw = match[2]; try { - value = JSON.parse(raw); // Essayer de parser JSON + value = JSON.parse(raw); } catch { - value = raw; // fallback string + value = raw; } } else if (match[3] !== undefined) { - // Valeur non-quoted (true, false, number, etc.) const raw = match[3]; + if (raw === "true") value = true; else if (raw === "false") value = false; else if (!isNaN(Number(raw))) value = Number(raw); @@ -47,9 +43,7 @@ const parseAttributes = (str: string): Record => { return attrs; }; -// Fonction principale : parse un node et retourne un Block[] const parseSingleNode = (node: Element): Block[] => { - // On combine le node text + mdxTextExpression éventuel en un seul texte let combinedText = ""; for (const child of node.children || []) { @@ -60,7 +54,6 @@ const parseSingleNode = (node: Element): Block[] => { } } - // Fonction récursive interne pour parser un texte complet const parseBlockText = (text: string): Block[] => { const blocks: Block[] = []; const lines = text.split(/\r?\n/); @@ -79,16 +72,14 @@ const parseSingleNode = (node: Element): Block[] => { }; if (stack.length > 0) { - // Ajoute comme enfant du dernier parent stack[stack.length - 1].children.push(block); } else { - // Bloc racine blocks.push(block); } - stack.push(block); // push pour gérer la fermeture + stack.push(block); } else if (endMatch) { - stack.pop(); // on ferme le bloc courant + stack.pop(); } else { if (stack.length > 0) { stack[stack.length - 1].children.push({ type: "text", value: line }); @@ -96,7 +87,6 @@ const parseSingleNode = (node: Element): Block[] => { } } - // Pousser tout bloc restant dans stack (blocs non fermés) while (stack.length > 0) { const remaining = stack.pop()!; if (stack.length > 0) { @@ -112,24 +102,26 @@ const parseSingleNode = (node: Element): Block[] => { return parseBlockText(combinedText); }; -// Plugin rehype export default function rehypeComponents() { return (tree: Root) => { visit(tree, "element", (node: Element, index, parent) => { if (!parent) return; const parsedBlocks = parseSingleNode(node); + const hasBlock = parsedBlocks.some((block) => block.startTag in mdx); - console.log(JSON.stringify(parsedBlocks, null, 2)); + if (hasBlock) { + console.log(JSON.stringify(parsedBlocks, null, 2)); - parent.children[index] = { - type: "element", - tagName: "BlockRenderer", - properties: { - ast: JSON.stringify(parsedBlocks), - }, - children: [], - } as Element; + parent.children[index] = { + type: "element", + tagName: "BlockRenderer", + properties: { + ast: JSON.stringify(parsedBlocks), + }, + children: [], + } as Element; + } }); }; } From d6958fa958568820a0b8e296e784c55d32028af3 Mon Sep 17 00:00:00 2001 From: Baptiste Parmantier Date: Fri, 21 Nov 2025 15:18:45 +0100 Subject: [PATCH 3/3] docs: create card documentation --- .../foundamentals/components/card.mdx | 123 +++++++++++++++++- .../content/card-group/card-group.astro | 2 +- .../components/content/card-group/card.astro | 1 - src/lib/plugins/parser/plugin.ts | 4 +- 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/content/docs/documentation/foundamentals/components/card.mdx b/content/docs/documentation/foundamentals/components/card.mdx index f8147c5..5fe8a14 100644 --- a/content/docs/documentation/foundamentals/components/card.mdx +++ b/content/docs/documentation/foundamentals/components/card.mdx @@ -5,13 +5,124 @@ permalink: card icon: lucide:bell --- -# Card +# Cards -:::card-group{cols=4, test="test"} -:::card{label="Test", icon="lucide:bell"} -test +This component allows you to group text elements while providing visual impact. + +``` +:::card-group + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: +::: +``` + +:::card-group {cols=2} +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +::: + +--- + +## Configuration + +### Card per line + +You can customize the number of elements per line by setting the `cols` prop. + +> [!note] +> Default card per line was fixed to 2 + +``` +:::card-group {cols=4} + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: +::: +``` + +:::card-group {cols=4} +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +::: + +If the elements cannot be aligned horizontally, they will be moved to the next line. + +``` +:::card-group {cols=2} + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: +::: +``` + +:::card-group {cols=2} +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. +::: +::: + +### Card item + +Vous pouvez personaliser chacune de vos cartes en utilisant les props suivantes : + +- `label`: Le texte à afficher en haut de la carte. (required) +- `icon`: L'icône à afficher en haut de la carte. + +> [!note] +> The cards use the [`iconify`](https://icon-sets.iconify.design/) library to display icons. + +``` +:::card-group + :::card {label="Test", icon="lucide:bell"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: + :::card {label="Test", icon="lucide:user"} + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + ::: +::: +``` + +:::card-group {cols=2} +:::card {label="Test", icon="lucide:bell"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ::: -:::card{label="Test", icon="lucide:bell"} -d +:::card {label="Test", icon="lucide:user"} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ::: ::: diff --git a/src/lib/components/content/card-group/card-group.astro b/src/lib/components/content/card-group/card-group.astro index 83253a0..8cff351 100644 --- a/src/lib/components/content/card-group/card-group.astro +++ b/src/lib/components/content/card-group/card-group.astro @@ -20,6 +20,6 @@ const gridCols = { }; --- -
+
diff --git a/src/lib/components/content/card-group/card.astro b/src/lib/components/content/card-group/card.astro index de7fdaf..2f453d2 100644 --- a/src/lib/components/content/card-group/card.astro +++ b/src/lib/components/content/card-group/card.astro @@ -7,7 +7,6 @@ type props = { }; const props = Astro.props; -console.log("Card", props); ---
block.startTag in mdx); - if (hasBlock) { - console.log(JSON.stringify(parsedBlocks, null, 2)); - + if (parent.type === "root" && hasBlock) { parent.children[index] = { type: "element", tagName: "BlockRenderer",