@codearcade/markdown 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,19 +1,19 @@
1
- # @codearcade/mdx
1
+ # @codearcade/markdown
2
2
 
3
3
  A modern, feature-rich Markdown renderer for React applications. Built for **speed**, **customizability**, and **developer experience**.
4
4
 
5
- Packed with **syntax highlighting**, **copy-to-clipboard** functionality, and seamless **dark mode** support out of the box.
5
+ Packed with **dynamic syntax highlighting** (lazy-loaded for zero bloat), **copy-to-clipboard** functionality, and seamless **dark mode** support out of the box.
6
6
 
7
7
  ---
8
8
 
9
9
  ## ✨ Features
10
10
 
11
11
  - ⚡ **Powered by React Markdown**: Robust and reliable rendering.
12
+ - 🚀 **Zero Initial Bloat**: Syntax highlighters and themes are dynamically lazy-loaded only when needed!
12
13
  - 🎨 **Theming Support**: First-class support for Light and Dark modes.
13
- - 💅 **Syntax Highlighting**: Integrated Prism syntax highlighting with **50+ themes** (Dracula, Atom Dark, Night Owl, etc.).
14
+ - 💅 **Dual Engine Syntax Highlighting**: Choose between **Prism** or **Highlight.js** under the hood, with access to over 100+ combined themes.
14
15
  - 📋 **Copy Code**: Automatic "Copy to Clipboard" button for all code blocks.
15
16
  - 🍭 **GFM Support**: GitHub Flavored Markdown (tables, autolinks, strikethrough) enabled by default.
16
- - 🔌 **Plug & Play**: Works instantly with minimal configuration.
17
17
 
18
18
  ---
19
19
 
@@ -22,38 +22,39 @@ Packed with **syntax highlighting**, **copy-to-clipboard** functionality, and se
22
22
  Install the package via your preferred package manager:
23
23
 
24
24
  ```bash
25
- npm install @codearcade/mdx
25
+ npm install @codearcade/markdown
26
26
  # or
27
- yarn add @codearcade/mdx
27
+ yarn add @codearcade/markdown
28
28
  # or
29
- pnpm add @codearcade/mdx
29
+ pnpm add @codearcade/markdown
30
30
  # or
31
- bun add @codearcade/mdx
31
+ bun add @codearcade/markdown
32
32
  ```
33
33
 
34
34
  ## Usage
35
35
 
36
- Using `@codearcade/mdx` is simple. Import the component and pass your markdown string.
36
+ Using `@codearcade/markdown` is simple. Import the component, select your engine (`prism` or `hljs`), and pass your markdown string.
37
37
 
38
38
  ### Basic Usage
39
39
 
40
40
  ```tsx
41
- import { MarkdownComponent } from "@codearcade/mdx";
41
+ import { MarkdownComponent } from "@codearcade/markdown";
42
42
 
43
43
  const markdown = `
44
44
  # Hello World
45
45
 
46
46
  This is a **markdown** component.
47
47
 
48
- \`\`\`javascript
48
+ ```javascript
49
49
  console.log("Hello from CodeArcade!");
50
- \`\`\`
50
+ ```
51
51
  `;
52
52
 
53
53
  export default function App() {
54
54
  return (
55
55
  <div style={{ padding: 20 }}>
56
- <MarkdownComponent markdownText={markdown} />
56
+ {/* The engine prop is required! Choose "prism" or "hljs" */}
57
+ <MarkdownComponent engine="prism" markdownText={markdown} />
57
58
  </div>
58
59
  );
59
60
  }
@@ -61,11 +62,11 @@ export default function App() {
61
62
 
62
63
  ### Dark Mode & Custom Themes
63
64
 
64
- Easily switch between light and dark modes, and customize the syntax highlighting theme for each mode.
65
+ Easily switch between light and dark modes, and customize the syntax highlighting theme. Because this component is fully strongly-typed, your IDE will auto-complete the available themes based on the engine you select!
65
66
 
66
67
  ```tsx
67
68
  import { useState } from "react";
68
- import { MarkdownComponent } from "@codearcade/mdx";
69
+ import { MarkdownComponent } from "@codearcade/markdown";
69
70
 
70
71
  export default function BlogPost() {
71
72
  const [isDarkMode, setIsDarkMode] = useState(false);
@@ -75,9 +76,10 @@ export default function BlogPost() {
75
76
  <button onClick={() => setIsDarkMode(!isDarkMode)}>Toggle Theme</button>
76
77
 
77
78
  <MarkdownComponent
78
- markdownText={content}
79
+ engine="prism"
80
+ markdownText={`console.log('test')`}
79
81
  theme={isDarkMode ? "dark" : "light"}
80
- // Customize syntax highlighting themes
82
+ // These will auto-complete to valid Prism themes!
81
83
  defaultMarkdownThemeLight="atomDark"
82
84
  defaultMarkdownThemeDark="dracula"
83
85
  />
@@ -91,23 +93,35 @@ export default function BlogPost() {
91
93
  ### `<MarkdownComponent />`
92
94
 
93
95
  | Prop | Type | Default | Description |
94
- |Text | | | |
96
+ |---|---|---|---|
97
+ | `engine` | `"prism" \| "hljs"` | **Required** | The syntax highlighting engine to power the code blocks. |
95
98
  | `markdownText` | `string` | **Required** | The raw markdown string to render. |
96
- | `theme` | `"light" \| "dark"` | `"light"` | Controls the rendering mode of the component. |
97
- | `defaultMarkdownThemeLight` | `MarkdownTheme` | `"a11yDark"` | Syntax highlighting theme to use when `theme` is `"light"`. |
98
- | `defaultMarkdownThemeDark` | `MarkdownTheme` | `"twilight"` | Syntax highlighting theme to use when `theme` is `"dark"`. |
99
+ | `theme` | `"light" \| "dark"` | `"light"` | Controls the rendering mode of the surrounding component. |
100
+ | `defaultMarkdownThemeLight` | `string` | `"a11yDark"` | Syntax highlighting theme to use when `theme` is `"light"`. Allowed strings change based on the `engine`. |
101
+ | `defaultMarkdownThemeDark` | `string` | `"twilight"` (Prism) / `"vs2015"` (HLJS) | Syntax highlighting theme to use when `theme` is `"dark"`. Allowed strings change based on the `engine`. |
99
102
 
100
103
  ### Available Themes
101
104
 
102
- We support a wide range of Prism themes. You can import `prismStyleNames` to see the full list or use it to build a theme selector.
105
+ We support a wide range of syntax highlighting themes. You can import the arrays directly if you want to build a theme-selector UI in your app!
106
+
107
+ #### Prism Themes
103
108
 
104
109
  ```tsx
105
- import { prismStyleNames } from "@codearcade/mdx";
110
+ import { prismStyleNames } from "@codearcade/markdown";
106
111
 
107
112
  console.log(prismStyleNames);
108
113
  // ["dracula", "atomDark", "nightOwl", "vs", "monokai", ...]
109
114
  ```
110
115
 
116
+ #### Highlight.js Themes
117
+
118
+ ```tsx
119
+ import { hljsStyleNames } from "@codearcade/markdown";
120
+
121
+ console.log(hljsStyleNames);
122
+ // ["atom-one-dark", "atom-one-light", "base16/darcula", "github-dark", "nord", ...]
123
+ ```
124
+
111
125
  ## License
112
126
 
113
- MIT © [CodeArcade](https://github.com/codearcade-io)
127
+ MIT © [CodeArcade](https://github.com/codearcade-io)
@@ -1,6 +1,6 @@
1
1
  declare const prismStyleNames: readonly ["a11yDark", "atomDark", "base16AteliersulphurpoolLight", "cb", "coldarkCold", "coldarkDark", "coyWithoutShadows", "coy", "darcula", "dark", "dracula", "duotoneDark", "duotoneEarth", "duotoneForest", "duotoneLight", "duotoneSea", "duotoneSpace", "funky", "ghcolors", "gruvboxDark", "gruvboxLight", "holiTheme", "hopscotch", "lucario", "materialDark", "materialLight", "materialOceanic", "nightOwl", "nord", "okaidia", "oneDark", "oneLight", "pojoaque", "prism", "shadesOfPurple", "solarizedDarkAtom", "solarizedlight", "synthwave84", "tomorrow", "twilight", "vs", "vscDarkPlus", "xonokai", "zTouch"];
2
- export declare const hljsStyleNames: readonly ["a11yDark", "a11yLight", "agate", "anOldHope", "androidstudio", "arduinoLight", "arta", "ascetic", "atelierCaveDark", "atelierCaveLight", "atelierDuneDark", "atelierDuneLight", "atelierEstuaryDark", "atelierEstuaryLight", "atelierForestDark", "atelierForestLight", "atelierHeathDark", "atelierHeathLight", "atelierLakesideDark", "atelierLakesideLight", "atelierPlateauDark", "atelierPlateauLight", "atelierSavannaDark", "atelierSavannaLight", "atelierSeasideDark", "atelierSeasideLight", "atelierSulphurpoolDark", "atelierSulphurpoolLight", "atomOneDarkReasonable", "atomOneDark", "atomOneLight", "brownPaper", "codepenEmbed", "colorBrewer", "darcula", "dark", "defaultStyle", "docco", "dracula", "far", "foundation", "githubGist", "github", "gml", "googlecode", "gradientDark", "grayscale", "gruvboxDark", "gruvboxLight", "hopscotch", "hybrid", "idea", "irBlack", "isblEditorDark", "isblEditorLight", "kimbieDark", "kimbieLight", "lightfair", "lioshi", "magula", "monoBlue", "monokaiSublime", "monokai", "nightOwl", "nnfxDark", "nnfx", "nord", "obsidian", "ocean", "paraisoDark", "paraisoLight", "pojoaque", "purebasic", "qtcreatorDark", "qtcreatorLight", "railscasts", "rainbow", "routeros", "schoolBook", "shadesOfPurple", "solarizedDark", "solarizedLight", "srcery", "stackoverflowDark", "stackoverflowLight", "sunburst", "tomorrowNightBlue", "tomorrowNightBright", "tomorrowNightEighties", "tomorrowNight", "tomorrow", "vs", "vs2015", "xcode", "xt256", "zenburn"];
2
+ declare const hljsStyleNames: readonly ["a11yDark", "a11yLight", "agate", "anOldHope", "androidstudio", "arduinoLight", "arta", "ascetic", "atelierCaveDark", "atelierCaveLight", "atelierDuneDark", "atelierDuneLight", "atelierEstuaryDark", "atelierEstuaryLight", "atelierForestDark", "atelierForestLight", "atelierHeathDark", "atelierHeathLight", "atelierLakesideDark", "atelierLakesideLight", "atelierPlateauDark", "atelierPlateauLight", "atelierSavannaDark", "atelierSavannaLight", "atelierSeasideDark", "atelierSeasideLight", "atelierSulphurpoolDark", "atelierSulphurpoolLight", "atomOneDarkReasonable", "atomOneDark", "atomOneLight", "brownPaper", "codepenEmbed", "colorBrewer", "darcula", "dark", "defaultStyle", "docco", "dracula", "far", "foundation", "githubGist", "github", "gml", "googlecode", "gradientDark", "grayscale", "gruvboxDark", "gruvboxLight", "hopscotch", "hybrid", "idea", "irBlack", "isblEditorDark", "isblEditorLight", "kimbieDark", "kimbieLight", "lightfair", "lioshi", "magula", "monoBlue", "monokaiSublime", "monokai", "nightOwl", "nnfxDark", "nnfx", "nord", "obsidian", "ocean", "paraisoDark", "paraisoLight", "pojoaque", "purebasic", "qtcreatorDark", "qtcreatorLight", "railscasts", "rainbow", "routeros", "schoolBook", "shadesOfPurple", "solarizedDark", "solarizedLight", "srcery", "stackoverflowDark", "stackoverflowLight", "sunburst", "tomorrowNightBlue", "tomorrowNightBright", "tomorrowNightEighties", "tomorrowNight", "tomorrow", "vs", "vs2015", "xcode", "xt256", "zenburn"];
3
3
  type PrismTheme = (typeof prismStyleNames)[number];
4
4
  type HljsTheme = (typeof hljsStyleNames)[number];
5
- export { prismStyleNames };
5
+ export { prismStyleNames, hljsStyleNames };
6
6
  export type { PrismTheme, HljsTheme };
package/dist/index.js CHANGED
@@ -21,12 +21,12 @@ var markdown_module_default = {
21
21
  };
22
22
 
23
23
  // src/components/icons.tsx
24
- import { jsxDEV } from "react/jsx-dev-runtime";
24
+ import { jsx } from "react/jsx-runtime";
25
25
  var CheckMarkIcon = () => {
26
- return /* @__PURE__ */ jsxDEV("svg", {
26
+ return /* @__PURE__ */ jsx("svg", {
27
27
  xmlns: "http://www.w3.org/2000/svg",
28
28
  viewBox: "0 0 512 512",
29
- children: /* @__PURE__ */ jsxDEV("path", {
29
+ children: /* @__PURE__ */ jsx("path", {
30
30
  fill: "none",
31
31
  stroke: "currentColor",
32
32
  "stroke-linecap": "round",
@@ -37,11 +37,11 @@ var CheckMarkIcon = () => {
37
37
  }, undefined, false, undefined, this);
38
38
  };
39
39
  var CopyIcon = () => {
40
- return /* @__PURE__ */ jsxDEV("svg", {
40
+ return /* @__PURE__ */ jsx("svg", {
41
41
  xmlns: "http://www.w3.org/2000/svg",
42
42
  viewBox: "0 0 512 512",
43
43
  children: [
44
- /* @__PURE__ */ jsxDEV("rect", {
44
+ /* @__PURE__ */ jsx("rect", {
45
45
  x: "128",
46
46
  y: "128",
47
47
  width: "336",
@@ -53,7 +53,7 @@ var CopyIcon = () => {
53
53
  "stroke-linejoin": "round",
54
54
  "stroke-width": "24"
55
55
  }, undefined, false, undefined, this),
56
- /* @__PURE__ */ jsxDEV("path", {
56
+ /* @__PURE__ */ jsx("path", {
57
57
  d: "M383.5 128l.5-24a56.16 56.16 0 00-56-56H112a64.19 64.19 0 00-64 64v216a56.16 56.16 0 0056 56h24",
58
58
  fill: "none",
59
59
  stroke: "currentColor",
@@ -66,7 +66,7 @@ var CopyIcon = () => {
66
66
  };
67
67
 
68
68
  // src/components/markdown.tsx
69
- import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
69
+ import { jsx as jsx2 } from "react/jsx-runtime";
70
70
  "use client";
71
71
  var CopyToClipboard = ({ text }) => {
72
72
  const [isCopied, setIsCopied] = useState(false);
@@ -84,12 +84,12 @@ var CopyToClipboard = ({ text }) => {
84
84
  }, 2000);
85
85
  }
86
86
  }, [text, isCopied]);
87
- return /* @__PURE__ */ jsxDEV2("button", {
87
+ return /* @__PURE__ */ jsx2("button", {
88
88
  onClick: copyToClipboard,
89
89
  className: markdown_module_default.markdownAction,
90
90
  "aria-label": isCopied ? "Copied to clipboard" : "Copy to clipboard",
91
91
  children: [
92
- isCopied ? /* @__PURE__ */ jsxDEV2(CheckMarkIcon, {}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV2(CopyIcon, {}, undefined, false, undefined, this),
92
+ isCopied ? /* @__PURE__ */ jsx2(CheckMarkIcon, {}, undefined, false, undefined, this) : /* @__PURE__ */ jsx2(CopyIcon, {}, undefined, false, undefined, this),
93
93
  " ",
94
94
  isCopied ? "Copied" : "Copy"
95
95
  ]
@@ -134,19 +134,19 @@ var MarkdownComponent = (props) => {
134
134
  isMounted = false;
135
135
  };
136
136
  }, [engine, theme]);
137
- return /* @__PURE__ */ jsxDEV2("section", {
137
+ return /* @__PURE__ */ jsx2("section", {
138
138
  className: `${markdown_module_default.markdownBody} ${theme}`,
139
- children: /* @__PURE__ */ jsxDEV2(ReactMarkdown, {
139
+ children: /* @__PURE__ */ jsx2(ReactMarkdown, {
140
140
  remarkPlugins: [remarkGfm],
141
141
  components: {
142
142
  code(props2) {
143
143
  const { className, children, ref, ...rest } = props2;
144
144
  const match = /language-(\w+)/.exec(className || "");
145
145
  const codeText = String(children).replace(/\n$/, "");
146
- return match && Highlighter ? /* @__PURE__ */ jsxDEV2("div", {
146
+ return match && Highlighter ? /* @__PURE__ */ jsx2("div", {
147
147
  style: { position: "relative" },
148
148
  children: [
149
- /* @__PURE__ */ jsxDEV2(Highlighter, {
149
+ /* @__PURE__ */ jsx2(Highlighter, {
150
150
  ...rest,
151
151
  PreTag: "div",
152
152
  ref,
@@ -155,11 +155,11 @@ var MarkdownComponent = (props) => {
155
155
  style: markdownTheme,
156
156
  children: codeText
157
157
  }, undefined, false, undefined, this),
158
- /* @__PURE__ */ jsxDEV2(CopyToClipboard, {
158
+ /* @__PURE__ */ jsx2(CopyToClipboard, {
159
159
  text: codeText
160
160
  }, undefined, false, undefined, this)
161
161
  ]
162
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV2("code", {
162
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx2("code", {
163
163
  ...rest,
164
164
  className,
165
165
  children
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codearcade/markdown",
3
3
  "type": "module",
4
- "version": "1.0.2",
4
+ "version": "1.2.0",
5
5
  "module": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  "dist/*.css"
25
25
  ],
26
26
  "scripts": {
27
- "build": "bun ./builder.ts && bun run generate-types",
27
+ "build": "NODE_ENV=production && bun ./builder.ts && bun run generate-types",
28
28
  "prepublishOnly": "bun run build",
29
29
  "generate-types": "bunx tsc --emitDeclarationOnly --declaration --outDir dist",
30
30
  "clear": "rm -rf dist"