diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index d12e957f5..fed473359 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -41,10 +41,7 @@ jobs: urls: | http://localhost:3000 http://localhost:3000/docs - http://localhost:3000/docs/category/javascript http://localhost:3000/courses - http://localhost:3000/courses/category/reactjs - http://localhost:3000/blog http://localhost:3000/showcase http://localhost:3000/community http://localhost:3000/docs/tags diff --git a/docs/guides/markdown-features/example-file.docx b/docs/guides/markdown-features/example-file.docx new file mode 100644 index 000000000..8f3766b21 Binary files /dev/null and b/docs/guides/markdown-features/example-file.docx differ diff --git a/docs/guides/markdown-features/markdown-feature-plugins.mdx b/docs/guides/markdown-features/markdown-feature-plugins.mdx new file mode 100644 index 000000000..1e0b37df0 --- /dev/null +++ b/docs/guides/markdown-features/markdown-feature-plugins.mdx @@ -0,0 +1,227 @@ +--- +id: plugins +description: Using MDX plugins to expand Markdown functionality in CodeHarborHub +slug: /markdown-features/plugins +--- + +# MDX Plugins + +CodeHarborHub uses [MDX](https://mdxjs.com/) to power its documentation. Sometimes, you may want to extend or tweak Markdown syntax. For example: + +- Embed a YouTube video using image-like syntax: `![](https://youtu.be/example)` +- Style standalone links as social cards +- Automatically prepend a copyright notice to every page + +The answer is: **create an MDX plugin!** +MDX supports a powerful [plugin system](https://mdxjs.com/advanced/plugins/) to customize how Markdown is parsed and transformed into JSX. + +There are three common plugin use-cases: + +- Use existing [Remark plugins](https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins) or [Rehype plugins](https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins) +- Transform elements produced by MDX syntax +- Introduce **new syntax** to MDX + + + +## How MDX Plugins Work + +When Markdown is compiled, it goes through two intermediate steps: + +1. **Markdown AST (MDAST)** +2. **Hypertext AST (HAST)** +3. JSX Output + +Plugins operate on these ASTs: + +* **[Remark](https://github.com/remarkjs/remark/)** → processes the Markdown AST +* **[Rehype](https://github.com/rehypejs/rehype/)** → processes the Hypertext AST + +:::tip +Use plugins to introduce shorter syntax for frequently used JSX elements. +For example, CodeHarborHub’s [admonition blocks](./markdown-features-admonitions.mdx) are powered by a Remark plugin. +::: + + + +## Default Plugins + +Docusaurus automatically injects a set of default Remark plugins during Markdown processing. +These handle tasks such as: + +- Generating a **Table of Contents** +- Adding **anchor links** to each heading +- Transforming images and links to `require()` calls + +These built-in plugins are great examples to inspire your own custom plugins. + + + +## Installing Plugins + +An MDX plugin is usually an **npm package**, so install it like any other dependency. + +Example: adding math support: + +```bash npm2yarn +npm install --save remark-math@5 rehype-katex@6 +``` + +
+ Remark vs Rehype in action + +* `remark-math` extracts `$...$` math expressions from Markdown and transforms them into a JSX placeholder. +* `rehype-katex` then takes those placeholders and renders them into KaTeX-powered HTML. +
+ +:::warning +Many official Remark/Rehype plugins are **ES Modules only**. Docusaurus supports ESM, but we recommend using an **ESM config file** for easier imports. +::: + + + +## Adding Plugins to `docusaurus.config.js` + +Once installed, import and add the plugin to your config: + +```js title="docusaurus.config.js" +// highlight-start +import remarkMath from 'remark-math'; +import rehypeKatex from 'rehype-katex'; +// highlight-end + +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + remarkPlugins: [remarkMath], + rehypePlugins: [rehypeKatex], + }, + }, + ], + ], +}; +``` + +Using **CommonJS**? Dynamic imports make it work: + +```js title="docusaurus.config.js" +module.exports = async function createConfigAsync() { + return { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + remarkPlugins: [(await import('remark-math')).default], + rehypePlugins: [(await import('rehype-katex')).default], + }, + }, + ], + ], + }; +}; +``` + +--- + +## Configuring Plugins + +Some plugins accept custom options. Use `[plugin, options]` syntax: + +```js title="docusaurus.config.js" +import rehypeKatex from 'rehype-katex'; + +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + rehypePlugins: [ + [rehypeKatex, {strict: false}], + ], + }, + }, + ], + ], +}; +``` + +Check the plugin’s documentation for available options. + + + +## Creating Your Own Plugin + +If no existing plugin fits your needs, you can create one. A plugin is a function that operates on the AST. + +Example: prefix every `h2` heading with `Section X.` + +```js title="src/remark/section-prefix.js" +import {visit} from 'unist-util-visit'; + +const plugin = () => { + return async (ast) => { + let count = 1; + visit(ast, 'heading', (node) => { + if (node.depth === 2 && node.children.length > 0) { + node.children.unshift({ + type: 'text', + value: `Section ${count}. `, + }); + count++; + } + }); + }; +}; + +export default plugin; +``` + +Import and register it: + +```js title="docusaurus.config.js" +import sectionPrefix from './src/remark/section-prefix'; + +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + remarkPlugins: [sectionPrefix], + }, + }, + ], + ], +}; +``` + +:::tip +The `transformer` function receives a second parameter, [`vfile`](https://github.com/vfile/vfile), which provides metadata like the current Markdown file’s path. +::: + + + +## Processing Order + +By default, Docusaurus runs its internal plugins **before** your custom plugins. If you need to run your plugin first: + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + '@docusaurus/preset-classic', + { + docs: { + beforeDefaultRemarkPlugins: [sectionPrefix], + }, + }, + ], + ], +}; +``` + +This ensures your transformations (like heading prefixes) are included in generated tables of contents. \ No newline at end of file diff --git a/docs/guides/markdown-features/markdown-features-admonitions.mdx b/docs/guides/markdown-features/markdown-features-admonitions.mdx new file mode 100644 index 000000000..f17881d3a --- /dev/null +++ b/docs/guides/markdown-features/markdown-features-admonitions.mdx @@ -0,0 +1,269 @@ +--- +id: admonitions +title: Admonitions +description: Add tips, notes, and warnings to your CodeHarborHub Markdown docs with styled callouts +slug: /guides/markdown-features/admonitions +--- + +Admonitions let you highlight **important information** in your docs using a simple Markdown syntax. + +They render as colorful callout boxes like **Tips**, **Notes**, **Warnings**, etc. + + + +## Basic Syntax + +Wrap your text with 3 colons and specify a type: + +```md +:::note + +This is a note block with **Markdown** support. + +::: +``` + + + +:::note + +This is a note block with **Markdown** support. + +::: + + + +Supported types: `note`, `tip`, `info`, `warning`, `danger` + +--- + +## Examples + +```md +:::tip +Great for best practices or quick advice. +::: + +:::info +Use to provide additional context. +::: + +:::warning +Warn users of potential issues. +::: + +:::danger +Critical alerts or breaking changes. +::: +``` + + + +:::tip +Great for best practices or quick advice. +::: + +:::info +Use to provide additional context. +::: + +:::warning +Warn users of potential issues. +::: + +:::danger +Critical alerts or breaking changes. +::: + + + + + +## Adding a Custom Title + +You can provide a **custom title** (with Markdown too): + +```md +:::note[Your **Custom** _Title_] + +This callout uses a custom title. + +::: +``` + + + +:::note[Your **Custom** _Title_] + +This callout uses a custom title. + +::: + + + + + +## Nested Admonitions + +Admonitions can be nested for layered messages. +Use more colons `:` for each parent level: + +```md +::::info Outer + +Outer content + +:::warning Inner +Inner content +::: + +:::: +``` + + + +::::info Outer + +Outer content + +:::warning Inner +Inner content +::: + +:::: + + + +--- + +## Using MDX Inside + +Admonitions fully support **MDX components**. + +```mdx +:::tip[Tabbed Example] + + + React example 🚀 + Vue example 🌿 + + +::: +``` + + + +:::tip[Tabbed Example] + + + React example 🚀 + Vue example 🌿 + + +::: + + + + + +## Using in JSX + +Outside Markdown, use the React component directly: + +```jsx title="MyPage.jsx" +import Admonition from '@theme/Admonition'; + +export default function MyPage() { + return ( + + You can use Admonitions directly in JSX too! + + ); +} +``` + + + + You can use Admonitions directly in JSX too! + + + +--- + +## Customizing Admonitions + +### Custom Icons or Styling + +You can override default icons by **swizzling** the Admonition theme component: + +```jsx title="src/theme/Admonition.js" +import React from 'react'; +import Admonition from '@theme-original/Admonition'; +import MyIcon from '@site/static/img/custom-icon.svg'; + +export default function AdmonitionWrapper(props) { + if (props.type === 'info') { + return } {...props} />; + } + return ; +} +``` + +### Add New Types + +Add a new keyword in `docusaurus.config.js`: + +```js title="docusaurus.config.js" +export default { + presets: [ + [ + 'classic', + { + docs: { + admonitions: { + keywords: ['my-callout'], + extendDefaults: true, + }, + }, + }, + ], + ], +}; +``` + +Then create a custom renderer: + +```jsx title="src/theme/Admonition/Types.js" +import React from 'react'; +import DefaultTypes from '@theme-original/Admonition/Types'; + +function MyCallout(props) { + return ( +
+

{props.title || '⚡ My Callout'}

+ {props.children} +
+ ); +} + +export default { + ...DefaultTypes, + 'my-callout': MyCallout, +}; +``` + +Now you can use: + +```md +:::my-callout[Custom Callout] +This is a completely custom admonition. +::: +``` + + + +## Best Practices + +* Always leave **blank lines** inside admonitions to avoid Prettier formatting issues. +* Use **icons and concise titles** to improve readability. +* Keep admonitions focused—avoid stuffing too much content. \ No newline at end of file diff --git a/docs/guides/markdown-features/markdown-features-assets.mdx b/docs/guides/markdown-features/markdown-features-assets.mdx new file mode 100644 index 000000000..fb751b30b --- /dev/null +++ b/docs/guides/markdown-features/markdown-features-assets.mdx @@ -0,0 +1,205 @@ +--- +id: assets +description: Handling assets in Markdown for CodeHarborHub docs +slug: /markdown-features/assets +--- + +# Assets in Markdown + +In CodeHarborHub documentation, you may need to include **images**, **files**, or **SVGs** inside Markdown (`.md` / `.mdx`) files. + +Docusaurus provides several ways to handle these assets while keeping everything **organized** and **optimized**. + +A common practice is to **co-locate** assets next to the Markdown file that uses them: + +``` +/docs/guides/markdown-features/markdown-features-assets.mdx +/docs/guides/markdown-features/assets/example-banner.png +/docs/guides/markdown-features/assets/example-file.docx +``` + +This keeps docs self-contained and easy to maintain. + + + +## Images {#images} + +You can display images using **three different methods**: + + + + +### 1. Simple Markdown Syntax + +The easiest way to add an image: + +```md +![Example banner](./assets/example-banner.jpg) +``` + +This works for most cases and Docusaurus will automatically process the file. + + + + +### 2. Using `require()` in JSX + +If you need to use JSX for extra control (like `className` or styles): + +```jsx +Example banner +``` + + + + +### 3. Using ES `import` + +Recommended when importing at the top of the file: + +```jsx +import banner from './assets/example-banner.jpg'; + +Example banner; +``` + + + + +All three methods display the same image: + + + ![Example banner](/img/codeharborhub-social-card.jpg) + + + + +## Downloadable Files {#files} + +You can also link downloadable files (like `.docx`, `.pdf`, `.zip`) directly. + +**Markdown link syntax** (recommended): + +```md +[Download the example doc](./assets/example-file.docx) +``` + +**JSX with `require()`** (for dynamic attributes): + +```jsx + + Download this docx + +``` + + +[Download the example doc](./example-file.docx) + + + + +## Inline SVGs {#inline-svgs} + +Docusaurus supports importing **SVGs as React components**. +This allows you to style or animate parts of the SVG using CSS. + +```jsx +import MyIcon from './assets/logo.svg'; + +; +``` + +For example, you can change the SVG color based on the current theme: + +```css +[data-theme='light'] .customSvg [fill='#000'] { + fill: #1e90ff; +} +[data-theme='dark'] .customSvg [fill='#000'] { + fill: #00fa9a; +} +``` + + + +## Themed Images {#themed-images} + +For sites that support **light/dark mode**, you may want different images per theme. +Use the `ThemedImage` component to automatically swap images. + +```jsx +import useBaseUrl from '@docusaurus/useBaseUrl'; +import ThemedImage from '@theme/ThemedImage'; + + +``` + +This ensures the correct image is loaded depending on the current theme. + +### GitHub-style Theme Switching + +You can also replicate GitHub’s approach using path fragments: + +```md +![Light mode](/img/codeharborhub-light.svg#gh-light-mode-only) +![Dark mode](/img/codeharborhub-dark.svg#gh-dark-mode-only) +``` + +Add this CSS to hide/show based on theme: + +```css title="src/css/custom.css" +[data-theme='light'] img[src$='#gh-dark-mode-only'], +[data-theme='dark'] img[src$='#gh-light-mode-only'] { + display: none; +} +``` + + + +## Static Assets {#static-assets} + +If you use **absolute paths** (`/img/...`), Docusaurus treats them as **static assets**. + +Example: + +```md +![Static asset](/img/nav-logo.jpg) +``` + +Docusaurus will look for this image inside the `static/` directory: + +``` +/static/img/nav-logo.jpg +``` + +Benefits of using static assets: + +1. **Automatic Base URL Handling** – works even when deploying to a subpath. +2. **Cache Optimization** – images are processed by Webpack and get a unique hash for better caching. + +If you need a raw URL (without build processing), +use the `pathname://` protocol: + +```md +![Raw image](pathname:///img/nav-logo.jpg) +``` + +This generates a direct `` tag. + +--- + +## Best Practices {#best-practices} + +* Keep assets **close to the docs** that use them for easier maintenance. +* Prefer **Markdown syntax** for most links/images for cleaner code. +* Use `ThemedImage` or `inline SVGs` when working with **dark/light mode**. +* Use **static assets** for site-wide shared files like logos and large downloads. \ No newline at end of file diff --git a/docs/guides/markdown-features/markdown-features-code-blocks.mdx b/docs/guides/markdown-features/markdown-features-code-blocks.mdx new file mode 100644 index 000000000..6ae22e15a --- /dev/null +++ b/docs/guides/markdown-features/markdown-features-code-blocks.mdx @@ -0,0 +1,344 @@ +--- +id: code-blocks +title: Code Blocks in Markdown +description: "Learn how to use, style, and supercharge code blocks in CodeHarborHub’s Markdown with syntax highlighting, line numbers, live editing, and more." +slug: /guides/markdown-features/code-blocks +--- + +import CodeBlock from "@theme/CodeBlock"; + +Code blocks are the **heart of technical documentation**. + +In CodeHarborHub (powered by Docusaurus & MDX), code blocks are **super-powered**. You can add syntax highlighting, titles, live editors, and even interactive tabs. + +This guide shows you **everything you can do with code blocks**, with real examples. + + + +## Basic Code Block + +Wrap your code with three backticks (\`\`\`) and specify the language for syntax highlighting. + +````md +```js +console.log("Hello CodeHarborHub!"); +``` +```` + + + +```js +console.log("Hello CodeHarborHub!"); +``` + + + +✅ **Tip:** Always specify the language (like `js`, `python`, `html`) for better highlighting. + + + +## Adding a Title + +Give your readers context by adding a title to your code block. + +````md +```jsx title="/src/components/Greeting.js" +export default function Greeting() { + return

Hello World!

; +} +``` +```` + + + +```jsx title="/src/components/Greeting.js" +export default function Greeting() { + return

Hello World!

; +} +``` + +
+ + + +## Syntax Highlighting & Themes + +CodeHarborHub uses [Prism](https://prismjs.com/) for beautiful syntax highlighting. + +You can customize the theme in `docusaurus.config.js`: + +```js title="docusaurus.config.js" +import { themes as prismThemes } from "prism-react-renderer"; + +export default { + themeConfig: { + prism: { + theme: prismThemes.dracula, // Dark & vibrant + }, + }, +}; +``` + +Supported languages include JavaScript, Python, Java, C++, and many more. +To add extra languages (like PowerShell or Rust): + +```js title="docusaurus.config.js" +export default { + themeConfig: { + prism: { + additionalLanguages: ["powershell", "rust"], + }, + }, +}; +``` + +Restart the dev server to see the changes. + + + +## Highlighting Lines + +Highlight key lines to draw attention. + +**With magic comments:** + +````mdx +```js +function importantCode() { + // highlight-next-line + return "⚡ This line is important!"; +} +``` +```` + + + +```js +function importantCode() { + // highlight-next-line + return "⚡ This line is important!"; +} +``` + + + +**With meta string:** + +````md +```js {2} +function importantCode() { + return "⚡ This line is important!"; +} +``` +```` + + + +## Line Numbers + +Add line numbers for easier references. + +````md +```jsx showLineNumbers +function Example() { + return

Line numbers are enabled!

; +} +``` +```` + + + +```jsx showLineNumbers +function Example() { + return

Line numbers are enabled!

; +} +``` + +
+ +You can even start counting from a specific number: + +````md +```jsx showLineNumbers=5 +function Example() { + return

Starts from 5!

; +} +``` +```` + + + +## Live Code Editor + +Want readers to experiment directly? +Turn any code block into a **live playground** using `live`. + +Install the plugin first: + +```bash npm2yarn +npm install --save @docusaurus/theme-live-codeblock +``` + +Enable it in `docusaurus.config.js`: + +```js +export default { + themes: ["@docusaurus/theme-live-codeblock"], +}; +``` + +Now create a live block: + +````md +```jsx live +function Counter() { + const [count, setCount] = React.useState(0); + return ; +} +``` +```` + + + +```jsx live +function Counter() { + const [count, setCount] = React.useState(0); + return ; +} +``` + + + +**Users can edit the code and see instant results!** + +--- + +## Multi-Language Tabs + +Show the same example in multiple languages using `` and ``. + +````mdx +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + + + + +```js +console.log("Hello from JavaScript!"); +``` + + + + +```python +print("Hello from Python!") +``` + + + +```` + + + + + +```js +console.log("Hello from JavaScript!"); +``` + + + + +```python +print("Hello from Python!") +``` + + + + + + + +## Advanced Tricks + +### Custom Magic Comments + +Create your own highlight styles. + +```js title="docusaurus.config.js" +export default { + themeConfig: { + prism: { + magicComments: [ + { + className: "code-block-error-line", + line: "This will error", + }, + ], + }, + }, +}; +``` + +Then style it in CSS: + +```css title="src/css/custom.css" +.code-block-error-line { + background: #ff000020; + border-left: 3px solid #ff000080; +} +``` + +### Interactive Imports + +For live blocks, add custom components to the live scope: + +```bash npm2yarn +npm run swizzle @docusaurus/theme-live-codeblock ReactLiveScope -- --eject +``` + +Then modify `src/theme/ReactLiveScope/index.js`: + +```js +import React from "react"; + +const FancyButton = (props) => ( +