@codearcade/markdown 1.0.1 → 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)
@@ -0,0 +1,3 @@
1
+ declare const CheckMarkIcon: () => import("react/jsx-runtime").JSX.Element;
2
+ declare const CopyIcon: () => import("react/jsx-runtime").JSX.Element;
3
+ export { CheckMarkIcon, CopyIcon };
@@ -1,12 +1,18 @@
1
1
  import React from "react";
2
- 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"];
3
- type MarkdownTheme = (typeof prismStyleNames)[number];
2
+ import { HljsTheme, PrismTheme } from "../constants/theme";
4
3
  type Theme = "dark" | "light";
5
- interface MarkdownComponentProps {
4
+ type MarkdownComponentProps = {
5
+ engine: "prism";
6
+ defaultMarkdownThemeLight?: PrismTheme;
7
+ theme?: Theme;
8
+ markdownText: string;
9
+ defaultMarkdownThemeDark?: PrismTheme;
10
+ } | {
11
+ engine: "hljs";
12
+ defaultMarkdownThemeLight?: HljsTheme;
6
13
  markdownText: string;
7
14
  theme?: Theme;
8
- defaultMarkdownThemeLight?: MarkdownTheme;
9
- defaultMarkdownThemeDark?: MarkdownTheme;
10
- }
15
+ defaultMarkdownThemeDark?: HljsTheme;
16
+ };
11
17
  declare const MarkdownComponent: React.FC<MarkdownComponentProps>;
12
- export { MarkdownComponent, prismStyleNames };
18
+ export { MarkdownComponent };
@@ -0,0 +1,6 @@
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
+ 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
+ type PrismTheme = (typeof prismStyleNames)[number];
4
+ type HljsTheme = (typeof hljsStyleNames)[number];
5
+ export { prismStyleNames, hljsStyleNames };
6
+ export type { PrismTheme, HljsTheme };
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export * from "./components/markdown";
2
+ export * from "./constants/theme";
package/dist/index.js CHANGED
@@ -11,7 +11,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
11
11
  // src/components/markdown.tsx
12
12
  import { useCallback, useEffect, useState } from "react";
13
13
  import ReactMarkdown from "react-markdown";
14
- import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
15
14
  import remarkGfm from "remark-gfm";
16
15
 
17
16
  // src/components/markdown.module.css
@@ -21,60 +20,13 @@ var markdown_module_default = {
21
20
  dark: "dark_A8U9fw"
22
21
  };
23
22
 
24
- // src/components/markdown.tsx
25
- import { jsxDEV } from "react/jsx-dev-runtime";
26
- "use client";
27
- var prismStyleNames = [
28
- "a11yDark",
29
- "atomDark",
30
- "base16AteliersulphurpoolLight",
31
- "cb",
32
- "coldarkCold",
33
- "coldarkDark",
34
- "coyWithoutShadows",
35
- "coy",
36
- "darcula",
37
- "dark",
38
- "dracula",
39
- "duotoneDark",
40
- "duotoneEarth",
41
- "duotoneForest",
42
- "duotoneLight",
43
- "duotoneSea",
44
- "duotoneSpace",
45
- "funky",
46
- "ghcolors",
47
- "gruvboxDark",
48
- "gruvboxLight",
49
- "holiTheme",
50
- "hopscotch",
51
- "lucario",
52
- "materialDark",
53
- "materialLight",
54
- "materialOceanic",
55
- "nightOwl",
56
- "nord",
57
- "okaidia",
58
- "oneDark",
59
- "oneLight",
60
- "pojoaque",
61
- "prism",
62
- "shadesOfPurple",
63
- "solarizedDarkAtom",
64
- "solarizedlight",
65
- "synthwave84",
66
- "tomorrow",
67
- "twilight",
68
- "vs",
69
- "vscDarkPlus",
70
- "xonokai",
71
- "zTouch"
72
- ];
23
+ // src/components/icons.tsx
24
+ import { jsx } from "react/jsx-runtime";
73
25
  var CheckMarkIcon = () => {
74
- return /* @__PURE__ */ jsxDEV("svg", {
26
+ return /* @__PURE__ */ jsx("svg", {
75
27
  xmlns: "http://www.w3.org/2000/svg",
76
28
  viewBox: "0 0 512 512",
77
- children: /* @__PURE__ */ jsxDEV("path", {
29
+ children: /* @__PURE__ */ jsx("path", {
78
30
  fill: "none",
79
31
  stroke: "currentColor",
80
32
  "stroke-linecap": "round",
@@ -85,11 +37,11 @@ var CheckMarkIcon = () => {
85
37
  }, undefined, false, undefined, this);
86
38
  };
87
39
  var CopyIcon = () => {
88
- return /* @__PURE__ */ jsxDEV("svg", {
40
+ return /* @__PURE__ */ jsx("svg", {
89
41
  xmlns: "http://www.w3.org/2000/svg",
90
42
  viewBox: "0 0 512 512",
91
43
  children: [
92
- /* @__PURE__ */ jsxDEV("rect", {
44
+ /* @__PURE__ */ jsx("rect", {
93
45
  x: "128",
94
46
  y: "128",
95
47
  width: "336",
@@ -101,7 +53,7 @@ var CopyIcon = () => {
101
53
  "stroke-linejoin": "round",
102
54
  "stroke-width": "24"
103
55
  }, undefined, false, undefined, this),
104
- /* @__PURE__ */ jsxDEV("path", {
56
+ /* @__PURE__ */ jsx("path", {
105
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",
106
58
  fill: "none",
107
59
  stroke: "currentColor",
@@ -112,6 +64,10 @@ var CopyIcon = () => {
112
64
  ]
113
65
  }, undefined, true, undefined, this);
114
66
  };
67
+
68
+ // src/components/markdown.tsx
69
+ import { jsx as jsx2 } from "react/jsx-runtime";
70
+ "use client";
115
71
  var CopyToClipboard = ({ text }) => {
116
72
  const [isCopied, setIsCopied] = useState(false);
117
73
  const copyToClipboard = useCallback(async () => {
@@ -128,42 +84,69 @@ var CopyToClipboard = ({ text }) => {
128
84
  }, 2000);
129
85
  }
130
86
  }, [text, isCopied]);
131
- return /* @__PURE__ */ jsxDEV("button", {
87
+ return /* @__PURE__ */ jsx2("button", {
132
88
  onClick: copyToClipboard,
133
89
  className: markdown_module_default.markdownAction,
134
90
  "aria-label": isCopied ? "Copied to clipboard" : "Copy to clipboard",
135
91
  children: [
136
- isCopied ? /* @__PURE__ */ jsxDEV(CheckMarkIcon, {}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(CopyIcon, {}, undefined, false, undefined, this),
92
+ isCopied ? /* @__PURE__ */ jsx2(CheckMarkIcon, {}, undefined, false, undefined, this) : /* @__PURE__ */ jsx2(CopyIcon, {}, undefined, false, undefined, this),
137
93
  " ",
138
94
  isCopied ? "Copied" : "Copy"
139
95
  ]
140
96
  }, undefined, true, undefined, this);
141
97
  };
142
- var MarkdownComponent = ({
143
- markdownText,
144
- theme = "light",
145
- defaultMarkdownThemeLight = "a11yDark",
146
- defaultMarkdownThemeDark = "twilight"
147
- }) => {
98
+ var MarkdownComponent = (props) => {
99
+ const { markdownText, theme = "light", engine = "prism" } = props;
148
100
  const [markdownTheme, setMarkdownTheme] = useState();
101
+ const [Highlighter, setHighlighter] = useState();
149
102
  useEffect(() => {
150
- import("react-syntax-highlighter/dist/esm/styles/prism").then((module) => {
151
- setMarkdownTheme(module[theme === "dark" ? defaultMarkdownThemeDark : defaultMarkdownThemeLight]);
152
- });
153
- }, [defaultMarkdownThemeLight, defaultMarkdownThemeDark, theme]);
154
- return /* @__PURE__ */ jsxDEV("section", {
103
+ let isMounted = true;
104
+ const loadDependencies = async () => {
105
+ try {
106
+ let themeModule;
107
+ let highlighterModule;
108
+ let selectedThemeName;
109
+ if (engine === "hljs") {
110
+ const hljsProps = props;
111
+ selectedThemeName = theme === "dark" ? hljsProps.defaultMarkdownThemeDark ?? "vs2015" : hljsProps.defaultMarkdownThemeLight ?? "a11yDark";
112
+ [highlighterModule, themeModule] = await Promise.all([
113
+ import("react-syntax-highlighter"),
114
+ import("react-syntax-highlighter/dist/esm/styles/hljs")
115
+ ]);
116
+ } else {
117
+ const prismProps = props;
118
+ selectedThemeName = theme === "dark" ? prismProps.defaultMarkdownThemeDark ?? "twilight" : prismProps.defaultMarkdownThemeLight ?? "a11yDark";
119
+ [highlighterModule, themeModule] = await Promise.all([
120
+ import("react-syntax-highlighter/dist/esm/prism"),
121
+ import("react-syntax-highlighter/dist/esm/styles/prism")
122
+ ]);
123
+ }
124
+ if (isMounted) {
125
+ setHighlighter(() => highlighterModule.default);
126
+ setMarkdownTheme(themeModule[selectedThemeName]);
127
+ }
128
+ } catch (error) {
129
+ console.error("Failed to load syntax highlighter dependencies:", error);
130
+ }
131
+ };
132
+ loadDependencies();
133
+ return () => {
134
+ isMounted = false;
135
+ };
136
+ }, [engine, theme]);
137
+ return /* @__PURE__ */ jsx2("section", {
155
138
  className: `${markdown_module_default.markdownBody} ${theme}`,
156
- children: /* @__PURE__ */ jsxDEV(ReactMarkdown, {
139
+ children: /* @__PURE__ */ jsx2(ReactMarkdown, {
157
140
  remarkPlugins: [remarkGfm],
158
141
  components: {
159
- code(props) {
160
- const { className, children, ref, ...rest } = props;
142
+ code(props2) {
143
+ const { className, children, ref, ...rest } = props2;
161
144
  const match = /language-(\w+)/.exec(className || "");
162
145
  const codeText = String(children).replace(/\n$/, "");
163
- return match ? /* @__PURE__ */ jsxDEV("div", {
146
+ return match && Highlighter ? /* @__PURE__ */ jsx2("div", {
164
147
  style: { position: "relative" },
165
148
  children: [
166
- /* @__PURE__ */ jsxDEV(SyntaxHighlighter, {
149
+ /* @__PURE__ */ jsx2(Highlighter, {
167
150
  ...rest,
168
151
  PreTag: "div",
169
152
  ref,
@@ -172,11 +155,11 @@ var MarkdownComponent = ({
172
155
  style: markdownTheme,
173
156
  children: codeText
174
157
  }, undefined, false, undefined, this),
175
- /* @__PURE__ */ jsxDEV(CopyToClipboard, {
158
+ /* @__PURE__ */ jsx2(CopyToClipboard, {
176
159
  text: codeText
177
160
  }, undefined, false, undefined, this)
178
161
  ]
179
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV("code", {
162
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsx2("code", {
180
163
  ...rest,
181
164
  className,
182
165
  children
@@ -187,9 +170,153 @@ var MarkdownComponent = ({
187
170
  }, undefined, false, undefined, this)
188
171
  }, undefined, false, undefined, this);
189
172
  };
173
+ // src/constants/theme.ts
174
+ var prismStyleNames = [
175
+ "a11yDark",
176
+ "atomDark",
177
+ "base16AteliersulphurpoolLight",
178
+ "cb",
179
+ "coldarkCold",
180
+ "coldarkDark",
181
+ "coyWithoutShadows",
182
+ "coy",
183
+ "darcula",
184
+ "dark",
185
+ "dracula",
186
+ "duotoneDark",
187
+ "duotoneEarth",
188
+ "duotoneForest",
189
+ "duotoneLight",
190
+ "duotoneSea",
191
+ "duotoneSpace",
192
+ "funky",
193
+ "ghcolors",
194
+ "gruvboxDark",
195
+ "gruvboxLight",
196
+ "holiTheme",
197
+ "hopscotch",
198
+ "lucario",
199
+ "materialDark",
200
+ "materialLight",
201
+ "materialOceanic",
202
+ "nightOwl",
203
+ "nord",
204
+ "okaidia",
205
+ "oneDark",
206
+ "oneLight",
207
+ "pojoaque",
208
+ "prism",
209
+ "shadesOfPurple",
210
+ "solarizedDarkAtom",
211
+ "solarizedlight",
212
+ "synthwave84",
213
+ "tomorrow",
214
+ "twilight",
215
+ "vs",
216
+ "vscDarkPlus",
217
+ "xonokai",
218
+ "zTouch"
219
+ ];
220
+ var hljsStyleNames = [
221
+ "a11yDark",
222
+ "a11yLight",
223
+ "agate",
224
+ "anOldHope",
225
+ "androidstudio",
226
+ "arduinoLight",
227
+ "arta",
228
+ "ascetic",
229
+ "atelierCaveDark",
230
+ "atelierCaveLight",
231
+ "atelierDuneDark",
232
+ "atelierDuneLight",
233
+ "atelierEstuaryDark",
234
+ "atelierEstuaryLight",
235
+ "atelierForestDark",
236
+ "atelierForestLight",
237
+ "atelierHeathDark",
238
+ "atelierHeathLight",
239
+ "atelierLakesideDark",
240
+ "atelierLakesideLight",
241
+ "atelierPlateauDark",
242
+ "atelierPlateauLight",
243
+ "atelierSavannaDark",
244
+ "atelierSavannaLight",
245
+ "atelierSeasideDark",
246
+ "atelierSeasideLight",
247
+ "atelierSulphurpoolDark",
248
+ "atelierSulphurpoolLight",
249
+ "atomOneDarkReasonable",
250
+ "atomOneDark",
251
+ "atomOneLight",
252
+ "brownPaper",
253
+ "codepenEmbed",
254
+ "colorBrewer",
255
+ "darcula",
256
+ "dark",
257
+ "defaultStyle",
258
+ "docco",
259
+ "dracula",
260
+ "far",
261
+ "foundation",
262
+ "githubGist",
263
+ "github",
264
+ "gml",
265
+ "googlecode",
266
+ "gradientDark",
267
+ "grayscale",
268
+ "gruvboxDark",
269
+ "gruvboxLight",
270
+ "hopscotch",
271
+ "hybrid",
272
+ "idea",
273
+ "irBlack",
274
+ "isblEditorDark",
275
+ "isblEditorLight",
276
+ "kimbieDark",
277
+ "kimbieLight",
278
+ "lightfair",
279
+ "lioshi",
280
+ "magula",
281
+ "monoBlue",
282
+ "monokaiSublime",
283
+ "monokai",
284
+ "nightOwl",
285
+ "nnfxDark",
286
+ "nnfx",
287
+ "nord",
288
+ "obsidian",
289
+ "ocean",
290
+ "paraisoDark",
291
+ "paraisoLight",
292
+ "pojoaque",
293
+ "purebasic",
294
+ "qtcreatorDark",
295
+ "qtcreatorLight",
296
+ "railscasts",
297
+ "rainbow",
298
+ "routeros",
299
+ "schoolBook",
300
+ "shadesOfPurple",
301
+ "solarizedDark",
302
+ "solarizedLight",
303
+ "srcery",
304
+ "stackoverflowDark",
305
+ "stackoverflowLight",
306
+ "sunburst",
307
+ "tomorrowNightBlue",
308
+ "tomorrowNightBright",
309
+ "tomorrowNightEighties",
310
+ "tomorrowNight",
311
+ "tomorrow",
312
+ "vs",
313
+ "vs2015",
314
+ "xcode",
315
+ "xt256",
316
+ "zenburn"
317
+ ];
190
318
  export {
191
319
  prismStyleNames,
320
+ hljsStyleNames,
192
321
  MarkdownComponent
193
322
  };
194
-
195
- //# debugId=06022BF521D3780764756E2164756E21
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codearcade/markdown",
3
3
  "type": "module",
4
- "version": "1.0.1",
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"
package/dist/index.js.map DELETED
@@ -1,10 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["..\\src\\components\\markdown.tsx"],
4
- "sourcesContent": [
5
- "\"use client\";\r\n\r\nimport type { Ref } from \"react\";\r\nimport React, { useCallback, useEffect, useState } from \"react\";\r\nimport ReactMarkdown from \"react-markdown\";\r\nimport { Prism as SyntaxHighlighter } from \"react-syntax-highlighter\";\r\nimport remarkGfm from \"remark-gfm\";\r\n\r\n// @ts-ignore\r\nimport styles from \"./markdown.module.css\";\r\n\r\nconst prismStyleNames = [\r\n \"a11yDark\",\r\n \"atomDark\",\r\n \"base16AteliersulphurpoolLight\",\r\n \"cb\",\r\n \"coldarkCold\",\r\n \"coldarkDark\",\r\n \"coyWithoutShadows\",\r\n \"coy\",\r\n \"darcula\",\r\n \"dark\",\r\n \"dracula\",\r\n \"duotoneDark\",\r\n \"duotoneEarth\",\r\n \"duotoneForest\",\r\n \"duotoneLight\",\r\n \"duotoneSea\",\r\n \"duotoneSpace\",\r\n \"funky\",\r\n \"ghcolors\",\r\n \"gruvboxDark\",\r\n \"gruvboxLight\",\r\n \"holiTheme\",\r\n \"hopscotch\",\r\n \"lucario\",\r\n \"materialDark\",\r\n \"materialLight\",\r\n \"materialOceanic\",\r\n \"nightOwl\",\r\n \"nord\",\r\n \"okaidia\",\r\n \"oneDark\",\r\n \"oneLight\",\r\n \"pojoaque\",\r\n \"prism\",\r\n \"shadesOfPurple\",\r\n \"solarizedDarkAtom\",\r\n \"solarizedlight\",\r\n \"synthwave84\",\r\n \"tomorrow\",\r\n \"twilight\",\r\n \"vs\",\r\n \"vscDarkPlus\",\r\n \"xonokai\",\r\n \"zTouch\",\r\n] as const;\r\n\r\ntype MarkdownTheme = (typeof prismStyleNames)[number];\r\n\r\nconst CheckMarkIcon = () => {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <path\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n stroke-width=\"24\"\r\n d=\"M416 128L192 384l-96-96\"\r\n />\r\n </svg>\r\n );\r\n};\r\n\r\nconst CopyIcon = () => {\r\n return (\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\">\r\n <rect\r\n x=\"128\"\r\n y=\"128\"\r\n width=\"336\"\r\n height=\"336\"\r\n rx=\"57\"\r\n ry=\"57\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-linejoin=\"round\"\r\n stroke-width=\"24\"\r\n />\r\n <path\r\n 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\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n stroke-width=\"24\"\r\n />\r\n </svg>\r\n );\r\n};\r\n\r\nconst CopyToClipboard = ({ text }: { text: string }) => {\r\n const [isCopied, setIsCopied] = useState(false);\r\n\r\n const copyToClipboard = useCallback(async () => {\r\n if (isCopied) return;\r\n\r\n try {\r\n await navigator.clipboard.writeText(text);\r\n setIsCopied(true);\r\n } catch (err) {\r\n console.error(\"Failed to copy text: \", err);\r\n // Optionally, show a user-friendly error message\r\n } finally {\r\n setTimeout(() => {\r\n setIsCopied(false);\r\n }, 2000);\r\n }\r\n }, [text, isCopied]);\r\n\r\n return (\r\n <button\r\n onClick={copyToClipboard}\r\n className={styles.markdownAction}\r\n aria-label={isCopied ? \"Copied to clipboard\" : \"Copy to clipboard\"}\r\n >\r\n {isCopied ? <CheckMarkIcon /> : <CopyIcon />}{\" \"}\r\n {isCopied ? \"Copied\" : \"Copy\"}\r\n </button>\r\n );\r\n};\r\n\r\ntype Theme = \"dark\" | \"light\";\r\n\r\ninterface MarkdownComponentProps {\r\n markdownText: string;\r\n theme?: Theme;\r\n defaultMarkdownThemeLight?: MarkdownTheme;\r\n defaultMarkdownThemeDark?: MarkdownTheme;\r\n}\r\n\r\ntype SyntaxHighlighterStyle = { [key: string]: React.CSSProperties };\r\n\r\nconst MarkdownComponent: React.FC<MarkdownComponentProps> = ({\r\n markdownText,\r\n theme = \"light\",\r\n defaultMarkdownThemeLight = \"a11yDark\",\r\n defaultMarkdownThemeDark = \"twilight\",\r\n}) => {\r\n const [markdownTheme, setMarkdownTheme] = useState<SyntaxHighlighterStyle>();\r\n\r\n useEffect(() => {\r\n import(\"react-syntax-highlighter/dist/esm/styles/prism\").then((module) => {\r\n setMarkdownTheme(\r\n module[\r\n theme === \"dark\"\r\n ? defaultMarkdownThemeDark\r\n : defaultMarkdownThemeLight\r\n ],\r\n );\r\n });\r\n }, [defaultMarkdownThemeLight, defaultMarkdownThemeDark, theme]);\r\n\r\n return (\r\n <section className={`${styles.markdownBody} ${theme}`}>\r\n <ReactMarkdown\r\n remarkPlugins={[remarkGfm]}\r\n components={{\r\n code(props) {\r\n const { className, children, ref, ...rest } = props;\r\n const match = /language-(\\w+)/.exec(className || \"\");\r\n const codeText = String(children).replace(/\\n$/, \"\");\r\n return match ? (\r\n <div style={{ position: \"relative\" }}>\r\n <SyntaxHighlighter\r\n {...rest}\r\n PreTag=\"div\"\r\n ref={ref as Ref<SyntaxHighlighter>}\r\n customStyle={{ borderRadius: \"1rem\" }}\r\n language={match[1]}\r\n style={markdownTheme}\r\n >\r\n {codeText}\r\n </SyntaxHighlighter>\r\n <CopyToClipboard text={codeText} />\r\n </div>\r\n ) : (\r\n <code {...rest} className={className}>\r\n {children}\r\n </code>\r\n );\r\n },\r\n }}\r\n >\r\n {markdownText}\r\n </ReactMarkdown>\r\n </section>\r\n );\r\n};\r\n\r\nexport { MarkdownComponent, prismStyleNames };\r\n"
6
- ],
7
- "mappings": "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",
8
- "debugId": "06022BF521D3780764756E2164756E21",
9
- "names": []
10
- }