├── .eslintrc.cjs
├── .github
└── FUNDING.yml
├── .gitignore
├── .storybook
├── main.ts
└── preview.ts
├── LICENSE
├── README.md
├── README_CN.md
├── example
├── .eslintrc.json
├── .gitignore
├── README.md
├── components.json
├── next.config.mjs
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── postcss.config.mjs
├── public
│ ├── logo.png
│ ├── next.svg
│ └── vercel.svg
├── src
│ ├── app
│ │ ├── docs
│ │ │ ├── editProps.tsx
│ │ │ └── page.tsx
│ │ ├── favicon.ico
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components
│ │ ├── Editor.tsx
│ │ ├── Footer.tsx
│ │ ├── Header.tsx
│ │ ├── Section.tsx
│ │ └── ui
│ │ │ ├── button.tsx
│ │ │ ├── card.tsx
│ │ │ ├── label.tsx
│ │ │ ├── radio-group.tsx
│ │ │ ├── scroll-area.tsx
│ │ │ ├── select.tsx
│ │ │ ├── switch.tsx
│ │ │ └── textarea.tsx
│ ├── lib
│ │ ├── useMounted.tsx
│ │ └── utils.ts
│ ├── markdown
│ │ ├── docs.mdx
│ │ └── home.mdx
│ └── mdx-components.tsx
├── tailwind.config.ts
└── tsconfig.json
├── index.html
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── postcss.config.js
├── public
├── banner.jpg
├── banner2.jpg
├── favicon.ico
├── favicon.png
├── logo.png
├── logo.svg
└── vite.svg
├── src
├── App.css
├── App.d.ts
├── App.tsx
├── assets
│ ├── bg
│ │ └── SpringGradientWave.jpg
│ ├── fonts
│ │ └── Inter.ttf
│ └── react.svg
├── index.css
├── lib
│ ├── utils.d.ts
│ └── utils.ts
├── main.d.ts
├── main.tsx
├── packages
│ ├── Md2Poster
│ │ └── index.tsx
│ ├── Md2PosterContent
│ │ └── index.tsx
│ ├── Md2PosterFooter
│ │ └── index.tsx
│ ├── Md2PosterHeader
│ │ └── index.tsx
│ ├── index.css
│ └── index.tsx
├── stories
│ ├── Configure.mdx
│ ├── MdToPoster.stories.d.ts
│ ├── MdToPoster.stories.tsx
│ └── assets
│ │ ├── accessibility.png
│ │ ├── accessibility.svg
│ │ ├── addon-library.png
│ │ ├── assets.png
│ │ ├── avif-test-image.avif
│ │ ├── context.png
│ │ ├── discord.svg
│ │ ├── docs.png
│ │ ├── figma-plugin.png
│ │ ├── github.svg
│ │ ├── share.png
│ │ ├── styling.png
│ │ ├── testing.png
│ │ ├── theming.png
│ │ ├── tutorials.svg
│ │ └── youtube.svg
└── vite-env.d.ts
├── tailwind.config.js
├── tsconfig-build.json
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: { browser: true, es2020: true },
4 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended', 'plugin:storybook/recommended'],
5 | ignorePatterns: ['dist', '.eslintrc.cjs'],
6 | parser: '@typescript-eslint/parser',
7 | plugins: ['react-refresh'],
8 | rules: {
9 | 'react-refresh/only-export-components': [
10 | 'warn',
11 | { allowConstantExport: true },
12 | ],
13 | "@typescript-eslint/no-explicit-any": ''
14 | },
15 | }
16 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12 | polar: # Replace with a single Polar username
13 | buy_me_a_coffee: gcui # Replace with a single Buy Me a Coffee username
14 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
15 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
26 | *storybook.log
27 |
28 |
29 | example/node_modules
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import type { StorybookConfig } from "@storybook/react-vite";
2 |
3 | const config: StorybookConfig = {
4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
5 | addons: [
6 | "@storybook/addon-onboarding",
7 | "@storybook/addon-links",
8 | "@storybook/addon-essentials",
9 | "@chromatic-com/storybook",
10 | "@storybook/addon-interactions",
11 | ],
12 | framework: {
13 | name: "@storybook/react-vite",
14 | options: {},
15 | },
16 | docs: {
17 | autodocs: "tag",
18 | },
19 | };
20 | export default config;
21 |
--------------------------------------------------------------------------------
/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Preview } from "@storybook/react";
2 |
3 | const preview: Preview = {
4 | parameters: {
5 | controls: {
6 | matchers: {
7 | color: /(background|color)$/i,
8 | date: /Date$/i,
9 | },
10 | },
11 | },
12 | };
13 |
14 | export default preview;
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Markdown To Image / Markdown Poster
2 |
3 | This React component renders Markdown as visually appealing social media images. The project also includes a built-in web editor that can be used as an online Markdown-to-poster editor with a simple one-click deployment.
4 |
5 | 
6 |
7 | - [English](./README.md) | [中文](./README_CN.md)
8 | - [DEMO & Web Editor](https://readpo.com/en/poster)
9 | - [Deploy Editor with Vercel](https://vercel.com/new/clone?repository-url=https://github.com/gcui-art/markdown-to-image&root-directory=example&project-name=markdown-to-image&repository-name=markdown-to-image)
10 | - [NPM:markdown-to-image](https://www.npmjs.com/package/markdown-to-image)
11 |
12 | ⭐ Click the Star and Watch buttons to stay updated on our latest developments.
13 |
14 | ## Features
15 |
16 | - [x] Render Markdown as poster images optimized for social sharing
17 | - [x] One built-in templates with support for custom templates
18 | - [x] Customizable themes with 9 pre-built options
19 | - [x] Copy output as an image
20 | - [x] One-click deployment to platforms like Vercel
21 | - [x] Integrated image CORS proxy for easy insertion of online images into posters
22 | - [x] Copy output as HTML code for pasting into emails and editors
23 | - [ ] More built-in templates
24 |
25 | ## Getting Started
26 |
27 | There are two ways to use markdown-to-poster:
28 |
29 | 1. Integration: markdown-to-poster is exported as a React component that can be seamlessly integrated into your projects.
30 | 2. Using Web Editor: The example path includes a web editor that can be deployed and used as an online editor.
31 |
32 | ### Integration
33 |
34 | `markdown-to-poster` exports a component called Md2Poster and three subcomponents, which can be installed via npm or other package managers.
35 |
36 | #### Installation
37 |
38 | Install with npm:
39 |
40 | ```bash
41 | npm i markdown-to-image
42 | ```
43 |
44 | Install with pnpm:
45 |
46 | ```bash
47 | pnpm install markdown-to-image
48 | ```
49 |
50 | yarn add markdown-to-image:
51 |
52 | ```bash
53 | yarn add markdown-to-image
54 | ```
55 |
56 | #### Usage
57 |
58 | Basic example:
59 |
60 | ```javascript
61 | import 'markdown-to-image/dist/style.css'
62 | import { Md2Poster, Md2PosterContent, Md2PosterHeader, Md2PosterFooter } from 'markdown-to-image'
63 |
64 | // ...
65 |
66 | const markdown = `
67 | # AI Morning Updates
68 | > On April 29th, what's the latest in the AI field that should be on your radar?
69 | ...
70 | `
71 |
72 | // ...
73 |
74 | return (
75 | // ...
76 |
77 | Poster Header
78 | {markdown}
79 | Powered by ReadPo.com
80 |
81 | // ...
82 | )
83 | ```
84 |
85 | ### Using the Web Editor
86 |
87 | #### Official Web Editor
88 |
89 | 👉 Visit: [readpo.com](https://readpo.com/en/poster)
90 |
91 | #### Deploying Your Own Web Editor
92 |
93 | [Deploy Editor with Vercel](https://vercel.com/new/clone?repository-url=https://github.com/gcui-art/markdown-to-image&root-directory=example&project-name=markdown-to-image&repository-name=markdown-to-image)
94 |
95 | ## Contributing
96 |
97 | There are four ways you can support this project:
98 |
99 | 1. Fork and Submit Pull Requests: We welcome any PRs that enhance the component or editor.
100 | 2. Open Issues: We appreciate reasonable suggestions and bug reports.
101 | 3. Donate: If this project has helped you, consider buying us a coffee using the Sponsor button at the top of the project. Cheers! ☕
102 | 4. Spread the Word: Recommend this project to others, star the repo, or add a backlink after using the project.
103 |
104 | ## License
105 |
106 | This project is licensed under the permissive Apache 2.0 open source license.
107 |
108 | ## Questions, Suggestions, Issues, or Bugs?
109 |
110 | We use GitHub Issues to manage feedback. Feel free to open an issue, and we'll address it promptly.
111 |
112 | ## Related Links
113 |
114 | - Our other open source projects: [Suno AI API](https://github.com/gcui-art/suno-api)
115 | - Demo site: [https://readpo.com/poster](https://readpo.com/en/poster)
116 | - NPM Package: [npm:markdown-to-image](https://www.npmjs.com/package/markdown-to-image)
117 |
118 | ## FQA
119 |
120 | 1. When utilizing frameworks like Next.js for server-side rendering (SSR), you may encounter the error `ReferenceError: document is not defined`. To address this issue, you can employ dynamic components with `next/dynamic`.
121 |
122 | ```javascript
123 | // page.ts
124 | import dynamic from 'next/dynamic'
125 | const Editor = dynamic(() => import('@/components/Editor'), {
126 | ssr: false,
127 | })
128 | ```
129 |
130 | ```javascript
131 | // Editor.tsx
132 | import React from 'react'
133 | import { Md2Poster, Md2PosterContent, Md2PosterHeader, Md2PosterFooter } from 'markdown-to-image'
134 |
135 | function Editor() {
136 | const markdown = `
137 | # AI Morning Updates
138 | > On April 29th, what's the latest in the AI field that should be on your radar?
139 |
140 | 
141 | 1. **Tech hiccups in AI car race: NTU team misses final** : Collaboration with UAE tech group faces technical challenges in international AI car race.
142 | 2. **AI complicates kids' online safety: Parents take charge** : Rapid AI evolution poses challenges, prompting parents to take active measures for children's safety.
143 | 3. **AI boom's secret winners: Companies fueling growth** : Investors find unique opportunities in stock market's AI boom, with certain companies driving progress.
144 | 4. **AI redefining automation in competitive market** : AI is no longer just a buzzword, as companies across industries deploy it for competitive edge.
145 | 5. **London private school introduces AI classes for children** : Leading school in London introduces AI lessons to help children adapt to evolving technology landscape.
146 | 6. **China utilizes supercomputer for AI training amid chip constraints** : Progress in leveraging supercomputers and domestic AI chips for training large language models in China.
147 | 7. **AI-Driven Age of New Media: Opportunities and Challenges** : CGTN panel discusses opportunities and challenges in the AI-driven age of new media.
148 | 8. **Apple rumored to resume OpenAI discussions for generative AI features** : Speculations suggest Apple may collaborate with OpenAI for generative AI features on upcoming iPhones.
149 | 9. **Tech tycoon's family office invests in AI for $10 billion fund** : Premji Invest to inject more funds into AI initiatives, supporting a $10 billion fund managed by Azim Premji.
150 | 10. **Banks embrace Cloud and AI for innovation and partnerships** : Banking industry shifts towards innovation, collaboration, and customer-centricity through adoption of Cloud and AI technologies.
151 | `
152 |
153 | return (
154 |
155 |
156 | @Nickname
157 | {new Date().toISOString().slice(0, 10)}
158 |
159 | {markdown}
160 | any children
161 |
162 | )
163 | }
164 |
165 | export default Editor
166 | ```
167 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # Markdown To Poster
2 |
3 | 这个 React 组件用于将 Markdown 渲染为漂亮的社交媒体图片。此外,该项目还包括一个内置的 WEB Editor,一键部署后,可以当做 Markdown 转海报图片在线编辑器使用。
4 |
5 | 
6 |
7 | - [English](./README.md) | [中文](./README_CN.md)
8 | - [DEMO & WEB Editor](https://readpo.com/zh/poster)
9 | - [Deploy Editor with Vercel](https://vercel.com/new/clone?repository-url=https://github.com/gcui-art/markdown-to-image&root-directory=example&project-name=markdown-to-image&repository-name=markdown-to-image)
10 | - [NPM:markdown-to-image](https://www.npmjs.com/package/markdown-to-image)
11 |
12 | ⭐ 点击 Star 和 Watch 按钮,跟踪我们的最新进展。
13 |
14 | ## 功能
15 |
16 | - [x] 将 Markdown 渲染为适合社交分享的海报图片
17 | - [x] 内置一个模板,支持模板扩展
18 | - [x] 支持自定义主题,并且已内置9个主题
19 | - [x] 支持复制为图像
20 | - [x] 支持一键部署到 Vercel 等
21 | - [x] 已集成图片跨域代理,可以方便的插入在线图片生成图文海报
22 | - [x] 支持复制为HTML 代码,可粘贴到电子邮件和一些编辑器中
23 | - [ ] 更多内置模板
24 |
25 | ## 如何使用
26 |
27 | 有两种使用 markdown-to-image 的方式:
28 |
29 | - 在项目中集成:markdown-to-image 已导出为一个 React 组件,可以直接集成到您自己的项目中。
30 | - 使用WEB UI:example路径中自带了一个 WEB Editor,部署后,可以当做在线编辑器使用。
31 |
32 | ### 在你的项目中集成
33 |
34 | `markdown-to-image`导出了一个叫 Md2Poster 的组件以及其他三个子组件,你可以通过 npm 等安装使用。
35 |
36 | #### 安装
37 |
38 | 用 npm 安装:
39 |
40 | ```bash
41 | npm i markdown-to-image
42 | ```
43 |
44 | 用 pnpm 安装:
45 |
46 | ```bash
47 | pnpm install markdown-to-image
48 | ```
49 |
50 | 用 yarn 安装:
51 |
52 | ```bash
53 | yarn install markdown-to-image
54 | ```
55 |
56 | #### 使用
57 |
58 | 简单开始:
59 |
60 | ```javascript
61 | import 'markdown-to-image/dist/style.css'
62 | import { Md2Poster, Md2PosterContent, Md2PosterHeader, Md2PosterFooter } from 'markdown-to-image'
63 |
64 | ...
65 |
66 | const markdown = `
67 | # AI Morning Updates
68 | > On April 29th, what's the latest in the AI field that should be on your radar?
69 | ...
70 | `
71 |
72 | ...
73 |
74 | return (
75 |
76 | ...
77 |
78 |
79 | Poster Header
80 | {markdown}
81 | Powered by ReadPo.com
82 |
83 |
84 | ...
85 |
86 | )
87 | ```
88 |
89 | ### 使用在线编辑器
90 |
91 | #### 使用官方部署的在线编辑器
92 |
93 | 👉 访问:[ReadPo.com](https://readpo.com/zh/poster)
94 |
95 | #### 部署自己的在线编辑器
96 |
97 | 这里使用Vercel进行部署,点击后一键部署:[部署 Editor 到 Vercel](https://vercel.com/new/clone?repository-url=https://github.com/gcui-art/markdown-to-image&root-directory=example&project-name=markdown-to-image&repository-name=markdown-to-image)
98 |
99 | ## 贡献指南
100 |
101 | 您有四种方式支持本项目:
102 |
103 | 1. **Fork 项目并提交 PR**:我们欢迎任何让这个组件和Editor变的更好的PR。
104 | 2. **提交Issue**:我们欢迎任何合理的建议、bug反馈。
105 | 3. **捐赠**:在项目的顶部我们放置了 Sponsor 按钮,如果这个项目帮助到了您,你可以请我们喝一杯,干杯☕。
106 | 4. **推荐**:向其他人推荐本项目;点击Star;使用本项目后放置外链。
107 |
108 | ## 许可证
109 |
110 | 使用非常宽松的 Apache 2.0开源协议。
111 |
112 | ## 你有一个问题/建议/困难/Bug?
113 |
114 | 我们使用Github的Issue来管理这些反馈,你可以提交一个。我们会经常来处理。
115 |
116 | ## 相关链接
117 |
118 | - 我们的其他开源项目: [Suno AI API](https://github.com/gcui-art/suno-api)
119 | - 演示站点: [https://readpo.com](https://readpo.com/zh/poster)
120 | - NPM Package:[npm:markdown-to-image](https://www.npmjs.com/package/markdown-to-image)
121 |
122 | ## 常见问题
123 |
124 | 1. 在Nextjs这样的SSR框架中使用的时候,可能会遇到`ReferenceError: document is not defined`报错,你可以使用`next/dynamic`动态组件解决这个问题。
125 |
126 | ```javascript
127 | // page.ts
128 | import dynamic from 'next/dynamic'
129 | const Editor = dynamic(() => import('@/components/Editor'), {
130 | ssr: false,
131 | })
132 | ```
133 |
134 | ```javascript
135 | // Editor.tsx
136 | import React from 'react'
137 | import { Md2Poster, Md2PosterContent, Md2PosterHeader, Md2PosterFooter } from 'markdown-to-image'
138 |
139 | function Editor() {
140 | const markdown = `
141 | # AI Morning Updates
142 | > On April 29th, what's the latest in the AI field that should be on your radar?
143 |
144 | 
145 | 1. **Tech hiccups in AI car race: NTU team misses final** : Collaboration with UAE tech group faces technical challenges in international AI car race.
146 | 2. **AI complicates kids' online safety: Parents take charge** : Rapid AI evolution poses challenges, prompting parents to take active measures for children's safety.
147 | 3. **AI boom's secret winners: Companies fueling growth** : Investors find unique opportunities in stock market's AI boom, with certain companies driving progress.
148 | 4. **AI redefining automation in competitive market** : AI is no longer just a buzzword, as companies across industries deploy it for competitive edge.
149 | 5. **London private school introduces AI classes for children** : Leading school in London introduces AI lessons to help children adapt to evolving technology landscape.
150 | 6. **China utilizes supercomputer for AI training amid chip constraints** : Progress in leveraging supercomputers and domestic AI chips for training large language models in China.
151 | 7. **AI-Driven Age of New Media: Opportunities and Challenges** : CGTN panel discusses opportunities and challenges in the AI-driven age of new media.
152 | 8. **Apple rumored to resume OpenAI discussions for generative AI features** : Speculations suggest Apple may collaborate with OpenAI for generative AI features on upcoming iPhones.
153 | 9. **Tech tycoon's family office invests in AI for $10 billion fund** : Premji Invest to inject more funds into AI initiatives, supporting a $10 billion fund managed by Azim Premji.
154 | 10. **Banks embrace Cloud and AI for innovation and partnerships** : Banking industry shifts towards innovation, collaboration, and customer-centricity through adoption of Cloud and AI technologies.
155 | `
156 |
157 | return (
158 |
159 |
160 | @Nickname
161 | {new Date().toISOString().slice(0, 10)}
162 |
163 | {markdown}
164 | any children
165 |
166 | )
167 | }
168 |
169 | export default Editor
170 | ```
171 |
--------------------------------------------------------------------------------
/example/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "next/core-web-vitals"
3 | }
4 |
--------------------------------------------------------------------------------
/example/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 | .yarn/install-state.gz
8 |
9 | # testing
10 | /coverage
11 |
12 | # next.js
13 | /.next/
14 | /out/
15 |
16 | # production
17 | /build
18 |
19 | # misc
20 | .DS_Store
21 | *.pem
22 |
23 | # debug
24 | npm-debug.log*
25 | yarn-debug.log*
26 | yarn-error.log*
27 |
28 | # local env files
29 | .env*.local
30 |
31 | # vercel
32 | .vercel
33 |
34 | # typescript
35 | *.tsbuildinfo
36 | next-env.d.ts
37 |
--------------------------------------------------------------------------------
/example/README.md:
--------------------------------------------------------------------------------
1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
2 |
3 | ## Getting Started
4 |
5 | First, run the development server:
6 |
7 | ```bash
8 | npm run dev
9 | # or
10 | yarn dev
11 | # or
12 | pnpm dev
13 | # or
14 | bun dev
15 | ```
16 |
17 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
18 |
19 | You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
20 |
21 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
22 |
23 | ## Learn More
24 |
25 | To learn more about Next.js, take a look at the following resources:
26 |
27 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
28 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
29 |
30 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
31 |
32 | ## Deploy on Vercel
33 |
34 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
35 |
36 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
37 |
--------------------------------------------------------------------------------
/example/components.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://ui.shadcn.com/schema.json",
3 | "style": "default",
4 | "rsc": true,
5 | "tsx": true,
6 | "tailwind": {
7 | "config": "tailwind.config.ts",
8 | "css": "src/app/globals.css",
9 | "baseColor": "gray",
10 | "cssVariables": true,
11 | "prefix": ""
12 | },
13 | "aliases": {
14 | "components": "@/components",
15 | "utils": "@/lib/utils"
16 | }
17 | }
--------------------------------------------------------------------------------
/example/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | import createMDX from '@next/mdx'
3 |
4 | const nextConfig = {
5 | // Configure `pageExtensions` to include markdown and MDX files
6 | pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
7 | };
8 |
9 | const withMDX = createMDX({
10 | // Add markdown plugins here, as desired
11 | extension: /\.mdx?$/,
12 | options: {
13 | remarkPlugins: [],
14 | rehypePlugins: [],
15 | },
16 | })
17 |
18 | export default withMDX(nextConfig)
19 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@mdx-js/loader": "^3.0.1",
13 | "@mdx-js/react": "^3.0.1",
14 | "@next/mdx": "^14.2.3",
15 | "@radix-ui/react-label": "^2.0.2",
16 | "@radix-ui/react-radio-group": "^1.1.3",
17 | "@radix-ui/react-scroll-area": "^1.0.5",
18 | "@radix-ui/react-select": "^2.0.0",
19 | "@radix-ui/react-slot": "^1.0.2",
20 | "@radix-ui/react-switch": "^1.0.3",
21 | "@types/mdx": "^2.0.13",
22 | "@uiw/react-md-editor": "^4.0.4",
23 | "@vercel/analytics": "^1.2.2",
24 | "class-variance-authority": "^0.7.0",
25 | "clsx": "^2.1.1",
26 | "lucide-react": "^0.378.0",
27 | "markdown-to-image": "^0.0.12",
28 | "next": "15.1.6",
29 | "react": "^18",
30 | "react-dom": "^18",
31 | "tailwind-merge": "^2.3.0",
32 | "tailwindcss-animate": "^1.0.7"
33 | },
34 | "devDependencies": {
35 | "@tailwindcss/typography": "^0.5.13",
36 | "@types/node": "^20",
37 | "@types/react": "^18",
38 | "@types/react-dom": "^18",
39 | "eslint": "^8",
40 | "eslint-config-next": "14.2.3",
41 | "postcss": "^8",
42 | "tailwindcss": "^3.4.1",
43 | "typescript": "^5"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/example/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('postcss-load-config').Config} */
2 | const config = {
3 | plugins: {
4 | tailwindcss: {},
5 | },
6 | };
7 |
8 | export default config;
9 |
--------------------------------------------------------------------------------
/example/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/gcui-art/markdown-to-image/41e4f2252f8588f16385cd170d2bd89db675b48b/example/public/logo.png
--------------------------------------------------------------------------------
/example/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/example/src/app/docs/editProps.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 | import { useState, useRef } from 'react'
3 | import {
4 | Select,
5 | SelectContent,
6 | SelectGroup,
7 | SelectItem,
8 | SelectLabel,
9 | SelectTrigger,
10 | SelectValue,
11 | } from '@/components/ui/select'
12 | import { Md2PosterContent, Md2Poster, Md2PosterHeader, Md2PosterFooter, Md2PosterProps } from 'markdown-to-image'
13 | import { Label } from '@/components/ui/label'
14 | import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
15 | import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card'
16 | import MDEditor from '@uiw/react-md-editor';
17 | import { Switch } from '@/components/ui/switch'
18 |
19 |
20 | export function SwitchCopy({
21 | onChange,
22 | defaultChecked,
23 | }: {
24 | onChange: (value: boolean) => void
25 | defaultChecked: boolean
26 | }) {
27 | return (
28 |
73 |
74 | )
75 | }
76 |
77 | function SelectTheme({ onChange, defaultValue }: { onChange: (value) => void; defaultValue: string }) {
78 | const list = ['blue', 'pink', 'purple', 'green', 'yellow', 'gray', 'red', 'indigo', 'SpringGradientWave']
79 | return (
80 |
99 | )
100 | }
101 |
102 | export default function EditProps() {
103 | const markdownRef = useRef(null)
104 | const textareaRef = useRef(null)
105 | const [mdString, setMdString] = useState(`# AI Morning News - April 29th
106 | 
107 | 1. **MetaElephant Company Releases Multi-Modal Large Model XVERSE-V**: Supports image input of any aspect ratio, performs well in multiple authoritative evaluations, and has been open-sourced.
108 | 2. **Tongyi Qianwen Team Open-Sources Billion-Parameter Model Qwen1.5-110B**: Uses Transformer decoder architecture, supports multiple languages, and has an efficient attention mechanism.
109 | 3. **Shengshu Technology and Tsinghua University Release Video Large Model Vidu**: Adopts a fusion architecture of Diffusion and Transformer, generates high-definition videos with one click, leading internationally.
110 | 4. **Mutable AI Launches Auto Wiki v2**: Automatically converts code into Wikipedia-style articles, solving the problem of code documentation.
111 | 5. **Google Builds New Data Center in the U.S.**: Plans to invest $3 billion to build a data center campus in Indiana, expand facilities in Virginia, and launch an artificial intelligence opportunity fund.
112 | 6. **China Academy of Information and Communications Technology Releases Automobile Large Model Standard**: Aims to standardize and promote the intelligent development of the automotive industry.
113 | 7. Kimi Chat Mobile App Update: Version 1.2.1 completely revamps the user interface, introduces a new light mode, and provides a comfortable and intuitive experience.
114 | `)
115 | const [theme, setTheme] = useState('SpringGradientWave')
116 | const [size, setSize] = useState('mobile')
117 | const [radio, setRadio] = useState('auto')
118 | const [canCopy, setCanCopy] = useState(false)
119 |
120 | const copySuccessCallback = () => {
121 | console.log('copySuccessCallback')
122 | alert('copySuccessCallback')
123 | }
124 |
125 | return (
126 |