Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions build/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "@microsoft/fast-build",
"description": "Build utilities for FAST monorepo",
"version": "0.0.0",
"private": true
}
15 changes: 9 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"license": "MIT",
"private": true,
"workspaces": [
"build",
"packages/*",
"sites/website",
"examples/todo-app",
Expand Down
8 changes: 8 additions & 0 deletions sites/website/eleventy.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import eleventyNavigationPlugin from "@11ty/eleventy-navigation";
import syntaxHighlight from "@11ty/eleventy-plugin-syntaxhighlight";
import { IdAttributePlugin } from "@11ty/eleventy";
import { admonitionPlugin } from "./plugins/admonitions.js";

export default function(eleventyConfig) {
/**
Expand Down Expand Up @@ -29,6 +30,13 @@ export default function(eleventyConfig) {
eleventyConfig.addPlugin(syntaxHighlight);
eleventyConfig.addPlugin(IdAttributePlugin);

/**
* Markdown
*/
eleventyConfig.amendLibrary("md", (md) => {
md.use(admonitionPlugin);
});

/**
* Filters
*/
Expand Down
162 changes: 162 additions & 0 deletions sites/website/plugins/admonitions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/**
* Custom markdown-it plugin for Docusaurus-style admonition blocks.
*
* Parses fenced blocks like:
* :::tip
* Content here (supports inline markdown).
* :::
*
* Renders them as styled alert divs using the existing Docusaurus CSS classes.
*/

const admonitionTypes = {
tip: "alert--success",
note: "alert--secondary",
warning: "alert--warning",
important: "alert--info",
};

const admonitionOpen = /^:::(\w+)\s*$/;
const admonitionClose = /^:::\s*$/;

function buildAdmonitionTokens(state, type, bodyContent) {
const cssClass = admonitionTypes[type];
const heading = type.charAt(0).toUpperCase() + type.slice(1);

const open = new state.Token("html_block", "", 0);
open.content = `<div class="alert ${cssClass}">\n<div class="alert__heading">${heading}</div>\n`;

const tokens = [open];

if (bodyContent) {
const bodyOpen = new state.Token("paragraph_open", "p", 1);
const bodyInline = new state.Token("inline", "", 0);
bodyInline.content = bodyContent;
bodyInline.children = [];
const bodyClose = new state.Token("paragraph_close", "p", -1);
tokens.push(bodyOpen, bodyInline, bodyClose);
}

const close = new state.Token("html_block", "", 0);
close.content = "</div>\n";
tokens.push(close);

return tokens;
}

export function admonitionPlugin(md) {
md.core.ruler.after("block", "admonition", (state) => {
const tokens = state.tokens;

for (let i = tokens.length - 1; i >= 0; i--) {
const token = tokens[i];

if (token.type !== "paragraph_open") {
continue;
}

const inline = tokens[i + 1];
if (!inline || inline.type !== "inline") {
continue;
}

const lines = inline.content.split("\n");
const openMatch = lines[0].match(admonitionOpen);

if (!openMatch) {
continue;
}

const type = openMatch[1];
if (!(type in admonitionTypes)) {
continue;
}

// Find the closing ::: β€” could be in this same inline token or a later one.
let closeLineIndex = lines.findIndex((l, idx) => idx > 0 && admonitionClose.test(l));

if (closeLineIndex !== -1) {
// Opening and closing are in the same paragraph block.
const body = lines.slice(1, closeLineIndex).join("\n").trim();
const after = lines.slice(closeLineIndex + 1).join("\n").trim();

const replacements = buildAdmonitionTokens(state, type, body);

if (after) {
// Leftover content after the closing ::: stays as a paragraph.
const pOpen = new state.Token("paragraph_open", "p", 1);
const pInline = new state.Token("inline", "", 0);
pInline.content = after;
pInline.children = [];
const pClose = new state.Token("paragraph_close", "p", -1);
replacements.push(pOpen, pInline, pClose);
}

// Replace paragraph_open + inline + paragraph_close
tokens.splice(i, 3, ...replacements);
continue;
}

// The closing ::: is in a subsequent token β€” scan forward.
let found = false;

for (let j = i + 3; j < tokens.length; j++) {
if (tokens[j].type !== "inline") {
continue;
}

const jLines = tokens[j].content.split("\n");
closeLineIndex = jLines.findIndex((l) => admonitionClose.test(l));

if (closeLineIndex === -1) {
continue;
}

// Collect body: remainder of the opening paragraph + all paragraphs in between + content before :::
const bodyParts = [];

const openRemainder = lines.slice(1).join("\n").trim();
if (openRemainder) {
bodyParts.push(openRemainder);
}

// Gather inline content from paragraphs between the opener and this closer.
for (let k = i + 3; k < j; k++) {
if (tokens[k].type === "inline") {
bodyParts.push(tokens[k].content);
}
}

const closeRemainder = jLines.slice(0, closeLineIndex).join("\n").trim();
if (closeRemainder) {
bodyParts.push(closeRemainder);
}

const body = bodyParts.join("\n\n");
const after = jLines.slice(closeLineIndex + 1).join("\n").trim();

const replacements = buildAdmonitionTokens(state, type, body);

if (after) {
const pOpen = new state.Token("paragraph_open", "p", 1);
const pInline = new state.Token("inline", "", 0);
pInline.content = after;
pInline.children = [];
const pClose = new state.Token("paragraph_close", "p", -1);
replacements.push(pOpen, pInline, pClose);
}

// Replace from opening paragraph_open through the closer's paragraph_close.
const closeParaClose = j + 1; // paragraph_close after the inline containing :::
tokens.splice(i, closeParaClose - i + 1, ...replacements);
found = true;
break;
}

if (!found) {
// No closing ::: found β€” leave content as-is.
continue;
}
}
});
}
2 changes: 1 addition & 1 deletion sites/website/scripts/generate-docs.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const path = require("path");
const { createInterface } = require("readline");
const { execFile } = require("child_process");
const fs = require("fs-extra");
const { getPackageJsonDir } = require("../../../build/get-package-json");
const { getPackageJsonDir } = require("@microsoft/fast-build/get-package-json.js");

// sites/website
const projectRoot = path.resolve(__dirname, "../");
Expand Down
7 changes: 6 additions & 1 deletion sites/website/src/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,12 @@ hr {
border-left-width: var(--ifm-alert-border-left-width);
border-radius: var(--ifm-alert-border-radius);
box-shadow: var(--ifm-alert-shadow);
padding: var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)
padding: var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal);
margin-bottom: 1em;

*:last-child {
margin-bottom: 0;
}
}

.alert__heading {
Expand Down