├── .github
└── workflows
│ └── rust.yml
├── .gitignore
├── ARCHITECTURE.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── assets
├── example-v2.png
├── example-v3.png
├── example-v4.png
└── example.png
├── egui_commonmark
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── examples
│ ├── README.md
│ ├── book.rs
│ ├── cuddlyferris.png
│ ├── hello_world.rs
│ ├── html.rs
│ ├── interactive.rs
│ ├── link_hooks.rs
│ ├── macros.rs
│ ├── markdown
│ │ ├── blockquotes.md
│ │ ├── code-blocks.md
│ │ ├── definition_list.md
│ │ ├── embedded_image.md
│ │ ├── headers.md
│ │ ├── hello_world.md
│ │ ├── html.md
│ │ ├── lists.md
│ │ └── tables.md
│ ├── mixing.rs
│ ├── scroll.rs
│ └── show_mut.rs
└── src
│ ├── lib.rs
│ └── parsers
│ ├── mod.rs
│ └── pulldown.rs
├── egui_commonmark_backend
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
└── src
│ ├── alerts.rs
│ ├── data_url_loader.rs
│ ├── elements.rs
│ ├── lib.rs
│ ├── misc.rs
│ └── pulldown.rs
├── egui_commonmark_macros
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── README.md
├── src
│ ├── generator.rs
│ └── lib.rs
└── tests
│ ├── fail
│ ├── commonmark_str_not_found.rs
│ ├── commonmark_str_not_found.stderr
│ ├── incorrect_immutable.rs
│ ├── incorrect_immutable.stderr
│ ├── incorrect_type.rs
│ └── incorrect_type.stderr
│ ├── file.md
│ └── pass
│ ├── book.rs
│ ├── commonmark.rs
│ ├── commonmark_str.rs
│ └── ui_hygiene.rs
└── rust-toolchain
/.github/workflows/rust.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v4
14 | - name: Clippy
15 | run: cargo clippy -- -Dwarnings
16 |
17 | - name: Check all features pulldown
18 | run: cargo check --no-default-features --features pulldown_cmark,better_syntax_highlighting,macros,embedded_image
19 |
20 | - name: Cargo fmt
21 | run: cargo fmt --check -q
22 |
23 | - name: Test
24 | run: cargo test --features macros
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/target
2 | egui_commonmark_macros/wip/
3 |
--------------------------------------------------------------------------------
/ARCHITECTURE.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | ## Crates
4 |
5 | - `egui_commonmark`
6 | - `egui_commonmark_macros`
7 | - `egui_commonmark_backend`
8 |
9 | ### egui_commonmark
10 |
11 | This is the main crate. It depends on `egui_commonmark_backend` and can expose
12 | `egui_commonmark_macros` through the `macros` feature.
13 |
14 | ### egui_commonmark_macros
15 |
16 | This is a proc macro crate. It depends on `egui_commonmark_backend`
17 |
18 | ### egui_commonmark_backend
19 |
20 | This is a crate that contains all code shared between the egui_commonmark
21 | crates. The code in this crate is also used by the code generated by
22 | `egui_commonmark_macros`. As a result the visibility of most items in it is `pub`
23 | by default. Since a user should not directly rely on these APIs most elements
24 | are hidden from the documentation.
25 |
26 | `egui_commonmark` reexports some of it's items. So care must be taken to ensure
27 | that no implementation details are accidentally exposed.
28 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # egui_commomnark changelog
2 |
3 | ## Unreleased
4 |
5 | ### Changed
6 |
7 | - Updated to pulldown-cmark 0.13
8 |
9 |
10 | ### Fixed
11 |
12 | - Rendering of html in macros
13 |
14 | ## 0.20.0 - 2025-02-04
15 |
16 | ### Added
17 |
18 | - Callback function `render_math_fn` for custom math rendering
19 | - Callback function `render_html_fn` for custom html rendering
20 |
21 | ### Changed
22 |
23 | - Updated egui to 0.31 ([#71](https://github.com/lampsitter/egui_commonmark/pull/71) by
24 | [@Wumpf](https://github.com/Wumpf) and [@emilk](https://github.com/emilk))
25 |
26 | ### Fixed
27 |
28 | - Html is rendered as text instead of not being displayed
29 |
30 | ## 0.19.0 - 2024-12-17
31 |
32 | ## Added
33 |
34 | - Support for loading images embedded in the markdown with data urls.
35 |
36 | ### Changed
37 |
38 | - Updated egui to 0.30 ([#69](https://github.com/lampsitter/egui_commonmark/pull/69) by [@abey79](https://github.com/abey79))
39 |
40 | ## 0.18.0 - 2024-09-26
41 |
42 | ### Added
43 |
44 | - Definition lists
45 | - Proper inline code block rendering
46 |
47 | ### Changed
48 |
49 | - `CommonMarkViewer::new` no longer takes in an id.
50 | - `commonmark!` and `commonmark_str!` no longer takes in an id.
51 | - `CommonMarkViewer::show_scrollable` takes in an id explicity.
52 |
53 | - Updated pulldown-cmark to 0.12
54 | - Newlines are no longer inserted before/after markdown ([#56](https://github.com/lampsitter/egui_commonmark/pull/56))
55 | > For the old behaviour you can call `ui.label("");` before and and after
56 |
57 | ### Removed
58 |
59 | - Experimental comrak backend ([#57](https://github.com/lampsitter/egui_commonmark/pull/57))
60 | - Deprecated method `syntax_theme`
61 |
62 | ## 0.17.0 - 2024-07-03
63 |
64 | ### Changed
65 |
66 | - Updated egui to 0.28 ([#51](https://github.com/lampsitter/egui_commonmark/pull/51) by [@emilk](https://github.com/emilk))
67 | - Updated pulldown-cmark to 0.11
68 |
69 | ## 0.16.1 - 2024-05-12
70 |
71 | ## Fixed
72 |
73 | - Fixed docs.rs build
74 |
75 | ## 0.16.0 - 2024-05-12
76 |
77 | ### Added
78 |
79 | - `commonmark!` and `commonmark_str!` for compile time parsing of markdown. The
80 | proc macros will output egui widgets directly into your code. To use this
81 | enable the `macros` feature.
82 |
83 | ### Changed
84 |
85 | - MSRV bumped to 1.76
86 |
87 | ### Fixed
88 |
89 | - Missing newline before alerts
90 |
91 | ## 0.15.0 - 2024-04-02
92 |
93 | ### Added
94 |
95 | - Replace copy icon with checkmark when clicking copy button in code blocks
96 | ([#42](https://github.com/lampsitter/egui_commonmark/pull/42) by [@zeozeozeo](https://github.com/zeozeozeo))
97 | - Interactive tasklists with `CommonMarkViewer::show_mut`
98 | ([#40](https://github.com/lampsitter/egui_commonmark/pull/40) by [@crumblingstatue](https://github.com/crumblingstatue))
99 |
100 | ### Changed
101 |
102 | - MSRV bumped to 1.74 due to pulldown_cmark
103 | - Alerts are case-insensitive
104 | - More spacing between list indicator and elements ([#46](https://github.com/lampsitter/egui_commonmark/pull/46))
105 |
106 | ### Fixed
107 |
108 | - Lists align text when wrapping instead of wrapping at the beginning of the next
109 | line ([#46](https://github.com/lampsitter/egui_commonmark/pull/46))
110 | - Code blocks won't insert a newline when in lists
111 | - In certain scenarios there was no newline after lists
112 | - Copy button for code blocks show the correct cursor again on hover (regression
113 | after egui 0.27)
114 |
115 | ## 0.14.0 - 2024-03-26
116 |
117 | ### Added
118 |
119 | - `AlertBundle::from_alerts`
120 | - `AlertBundle::into_alerts`
121 |
122 | ### Changed
123 |
124 | - Update to egui 0.27 ([#37](https://github.com/lampsitter/egui_commonmark/pull/37) by [@emilk](https://github.com/emilk))
125 | - `CommonMarkViewer::show` returns `InnerResponse<()>`
126 | ([#36](https://github.com/lampsitter/egui_commonmark/pull/36) by [@ElhamAryanpur](https://github.com/ElhamAryanpur))
127 |
128 | ### Fixed
129 |
130 | - A single table cell split into multiple cells ([#35](https://github.com/lampsitter/egui_commonmark/pull/35))
131 |
132 | ## 0.13.0 - 2024-02-20
133 |
134 | ### Added
135 |
136 | - Alerts ([#32](https://github.com/lampsitter/egui_commonmark/pull/32))
137 |
138 | > [!TIP]
139 | > Alerts like this can be used
140 |
141 | ### Changed
142 |
143 | - Prettier blockquotes
144 |
145 | Before two simple horizontal lines were rendered. Now it's a single horizontal
146 | line in front of the elements.
147 |
148 | - Upgraded to pulldown-cmark 0.10
149 |
150 | ### Fixed
151 |
152 | - Ordered lists remember their number when mixing bullet and ordered lists
153 |
154 | ## 0.12.1 - 2024-02-12
155 |
156 | ### Fixed
157 |
158 | - Build failure with 1.72
159 |
160 |
161 | ## 0.12.0 - 2024-02-05
162 |
163 | ### Changed
164 |
165 | - Update to egui 0.26
166 |
167 | ### Fixed
168 |
169 | - Missing space after tables
170 |
171 |
172 | ## 0.11.0 - 2024-01-08
173 |
174 | ### Changed
175 |
176 | - Update to egui 0.25 ([#27](https://github.com/lampsitter/egui_commonmark/pull/27) by [@emilk](https://github.com/emilk))
177 |
178 |
179 | ## 0.10.2 - 2023-12-13
180 |
181 | ### Added
182 |
183 | - Option to change default implicit uri scheme [#24](https://github.com/lampsitter/egui_commonmark/pull/24)
184 |
185 | ## 0.10.1 - 2023-12-03
186 |
187 | ### Changed
188 |
189 | - Code block has borders.
190 |
191 | ### Fixed
192 |
193 | - Make code blocks non-editable ([#22](https://github.com/lampsitter/egui_commonmark/pull/22) by [@emilk](https://github.com/emilk)).
194 |
195 |
196 | ## 0.10.0 - 2023-11-23
197 |
198 | ### Changed
199 |
200 | - Update to egui 0.24
201 |
202 | ## 0.9.2 - 2023-11-07
203 |
204 | ### Fixed
205 |
206 | - Header sizing issues ([#20](https://github.com/lampsitter/egui_commonmark/pull/20) by [@abey79](https://github.com/abey79)).
207 |
208 | ## 0.9.1 - 2023-10-24
209 |
210 | ### Fixed
211 |
212 | - Missing space after heading when preceded by an image
213 | - Missing space after separator
214 |
215 | ## 0.9.0 - 2023-10-14
216 |
217 | ### Added
218 |
219 | - Copy text button in code blocks
220 |
221 | ## 0.8.0 - 2023-09-28
222 |
223 | ### Added
224 |
225 | - Primitive syntax highlighting by default
226 | - Code blocks now use the syntax highlighting theme's caret and selection colors while using the
227 | `better_syntax_highlighting` feature.
228 | - Image loading errors are shown ([#8](https://github.com/lampsitter/egui_commonmark/pull/8) by [@emilk](https://github.com/emilk)).
229 | - `CommonMarkCache` implements `Debug` ([#7](https://github.com/lampsitter/egui_commonmark/pull/7) by [@ChristopherPerry6060](https://github.com/ChristopherPerry6060)).
230 | - `CommonMarkCache::add_syntax_themes_from_folder`
231 | - `CommonMarkCache::add_syntax_theme_from_bytes`
232 | - `CommonMarkViewer::explicit_image_uri_scheme`
233 |
234 | ### Fixed
235 |
236 | - Links of the type ``[`fancy` _link_](..)`` is rendered correctly.
237 |
238 | ### Changed
239 |
240 | - Update to egui 0.23
241 | - Image formats are no longer implicitly enabled.
242 | - Use new image API from egui ([#11](https://github.com/lampsitter/egui_commonmark/pull/11) by [@jprochazk](https://github.com/jprochazk)).
243 | - Feature `syntax_highlighting` has been renamed to `better_syntax_highlighting`.
244 |
245 | ### Removed
246 |
247 | - `CommonMarkCache::reload_images`
248 | - Removed trimming of svg's transparency. The function has been removed from resvg.
249 |
250 | ## 0.7.4 - 2023-07-08
251 |
252 | ### Changed
253 |
254 | - Better looking checkboxes
255 |
256 | ## 0.7.3 - 2023-05-24
257 |
258 | ### Added
259 |
260 | - Support for egui 0.22. This release can also still be used with 0.21.
261 | An explicit dependency update might be needed to use egui 0.22: `cargo update -p egui_commonmark`
262 |
263 | ## 0.7.2 - 2023-04-22
264 |
265 | ### Added
266 |
267 | - `CommonMarkCache::clear_scrollable_with_id` to clear the cache for only a single scrollable viewer.
268 |
269 | ### Fixed
270 |
271 | - Removed added spacing between elements in `show_scrollable`
272 |
273 | ## 0.7.1 - 2023-04-21
274 |
275 | ### Added
276 |
277 | - Only render visible elements within a ScrollArea with `show_scrollable`
278 | ([#4](https://github.com/lampsitter/egui_commonmark/pull/4) by [@localcc](https://github.com/localcc)).
279 |
280 | ## 0.7.0 - 2023-02-09
281 |
282 | ### Changed
283 |
284 | - Upgraded egui to 0.21
285 |
286 | ## 0.6.0 - 2022-12-08
287 |
288 | ### Changed
289 |
290 | - Upgraded egui to 0.20
291 |
292 | ## 0.5.0 - 2022-11-29
293 |
294 | ### Changed
295 |
296 | - Default dark syntax highlighting theme has been changed from base16-mocha.dark
297 | to base16-ocean.dark.
298 |
299 | ### Fixed
300 |
301 | - Render text in svg images.
302 | - Fixed erroneous newline after images.
303 | - Fixed missing newline after lists and quotes.
304 |
305 | ## 0.4.0 - 2022-08-25
306 |
307 | ### Changed
308 |
309 | - Upgraded egui to 0.19.
310 |
311 | ### Fixed
312 |
313 | - Display indented code blocks in a single code block ([#1](https://github.com/lampsitter/egui_commonmark/pull/1) by [@lazytanuki](https://github.com/lazytanuki)).
314 |
315 | ## 0.3.0 - 2022-08-13
316 |
317 | ### Added
318 |
319 | - Automatic light/dark theme in code blocks.
320 | - Copyable code blocks.
321 |
322 | ### Changed
323 |
324 | - Deprecated `syntax_theme` in favour of `syntax_theme_dark` and
325 | `syntax_theme_light`.
326 |
327 | ### Fixed
328 |
329 | - No longer panic upon unknown syntax theme.
330 | - Fixed incorrect line endings within headings.
331 |
332 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## How to contribute
2 |
3 | First of all thank you for considering it. Check out
4 | [ARCHITECTURE.md](ARCHITECTURE.md) for an overview of how the repo is put together.
5 |
6 | ### Running tests
7 |
8 | You won't be able to run the tests without enabling the `macros` feature
9 | as one of the examples depend on it.
10 |
11 | `cargo test --features macros`
12 |
13 |
14 | ### Debugging the proc macros
15 |
16 | To see the output of the macros enable the `dump-macro` feature.
17 | For the macro example the output can be viewed like this:
18 |
19 | ```sh
20 | cargo r --example macro --features dump-macro,macros -- dark | rustfmt --edition=2021 | less
21 | ```
22 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | "egui_commonmark",
4 | "egui_commonmark_macros",
5 | "egui_commonmark_backend",
6 | ]
7 |
8 | resolver = "2"
9 |
10 |
11 | [workspace.package]
12 | license = "MIT OR Apache-2.0"
13 | edition = "2021"
14 | rust-version = "1.81" # Follows egui
15 | version = "0.20.0"
16 | repository = "https://github.com/lampsitter/egui_commonmark"
17 |
18 | [workspace.dependencies]
19 | egui_extras = { version = "0.31", default-features = false }
20 | egui = { version = "0.31", default-features = false }
21 |
22 | egui_commonmark_backend = { version = "0.20.0", path = "egui_commonmark_backend", default-features = false }
23 | egui_commonmark_macros = { version = "0.20.0", path = "egui_commonmark_macros", default-features = false }
24 |
25 | # To add features to documentation
26 | document-features = { version = "0.2" }
27 |
28 | pulldown-cmark = { version = "0.13", default-features = false }
29 |
30 |
31 | [patch.crates-io]
32 | # eframe = { git = "https://github.com/emilk/egui.git", branch = "master" }
33 | # egui = { git = "https://github.com/emilk/egui.git", branch = "master" }
34 | # egui_extras = { git = "https://github.com/emilk/egui.git", branch = "master" }
35 |
36 | # eframe = { path = "../../egui/crates/eframe" }
37 | # egui = { path = "../../egui/crates/egui" }
38 | # egui_extras = { path = "../../egui/crates/egui_extras" }
39 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022-2025 Erlend Walstad
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A commonmark viewer for [egui](https://github.com/emilk/egui)
2 |
3 | [](https://crates.io/crates/egui_commonmark)
4 | [](https://docs.rs/egui_commonmark)
5 |
6 |
7 |
8 | While this crate's main focus is commonmark, it also supports a subset of
9 | Github's markdown syntax: tables, strikethrough, tasklists and footnotes.
10 |
11 | ## Usage
12 |
13 | In Cargo.toml:
14 |
15 | ```toml
16 | egui_commonmark = "0.20"
17 | # Specify what image formats you want to use
18 | image = { version = "0.25", default-features = false, features = ["png"] }
19 | ```
20 |
21 | ```rust
22 | use egui_commonmark::*;
23 | let markdown =
24 | r"# Hello world
25 |
26 | * A list
27 | * [ ] Checkbox
28 | ";
29 |
30 | let mut cache = CommonMarkCache::default();
31 | CommonMarkViewer::new().show(ui, &mut cache, markdown);
32 | ```
33 |
34 |
35 | ## Compile time evaluation of markdown
36 |
37 | If you want to embed markdown directly the binary then you can enable the `macros` feature.
38 | This will do the parsing of the markdown at compile time and output egui widgets.
39 |
40 | ### Example
41 |
42 | ```rust
43 | use egui_commonmark::{CommonMarkCache, commonmark};
44 | let mut cache = CommonMarkCache::default();
45 | let _response = commonmark!(ui, &mut cache, "# ATX Heading Level 1");
46 | ```
47 |
48 | Alternatively you can embed a file
49 |
50 | ### Example
51 |
52 | ```rust
53 | use egui_commonmark::{CommonMarkCache, commonmark_str};
54 | let mut cache = CommonMarkCache::default();
55 | commonmark_str!(ui, &mut cache, "content.md");
56 | ```
57 |
58 |
59 | ## Features
60 |
61 | * `macros`: macros for compile time parsing of markdown
62 | * `better_syntax_highlighting`: Syntax highlighting inside code blocks with
63 | [`syntect`](https://crates.io/crates/syntect)
64 | * `svg`: Support for viewing svg images
65 | * `fetch`: Images with urls will be downloaded and displayed
66 |
67 |
68 | ## Examples
69 |
70 | For an easy intro check out the `hello_world` example. To see all the different
71 | features egui_commonmark has to offer check out the `book` example.
72 |
73 | ## FAQ
74 |
75 | ### URL is not displayed when hovering over a link
76 |
77 | By default egui does not show urls when you hover hyperlinks. To enable it,
78 | you can do the following before calling any ui related functions:
79 |
80 | ```rust
81 | ui.style_mut().url_in_tooltip = true;
82 | ```
83 |
84 | ## MSRV Policy
85 |
86 | This crate uses the same MSRV as the latest released egui version.
87 |
88 | ## License
89 |
90 | Licensed under either of
91 |
92 | * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
93 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
94 |
95 | at your option.
96 |
--------------------------------------------------------------------------------
/assets/example-v2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lampsitter/egui_commonmark/86f6a1d4a1fbe38b89f0034de839d879fe540f31/assets/example-v2.png
--------------------------------------------------------------------------------
/assets/example-v3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lampsitter/egui_commonmark/86f6a1d4a1fbe38b89f0034de839d879fe540f31/assets/example-v3.png
--------------------------------------------------------------------------------
/assets/example-v4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lampsitter/egui_commonmark/86f6a1d4a1fbe38b89f0034de839d879fe540f31/assets/example-v4.png
--------------------------------------------------------------------------------
/assets/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lampsitter/egui_commonmark/86f6a1d4a1fbe38b89f0034de839d879fe540f31/assets/example.png
--------------------------------------------------------------------------------
/egui_commonmark/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "egui_commonmark"
3 | authors = ["Erlend Walstad"]
4 |
5 | version.workspace = true
6 | edition.workspace = true
7 | license.workspace = true
8 | rust-version.workspace = true
9 | repository.workspace = true
10 |
11 | description = "Commonmark viewer for egui"
12 | keywords = ["commonmark", "egui"]
13 | categories = ["gui"]
14 | readme = "README.md"
15 | documentation = "https://docs.rs/egui_commonmark"
16 | include = ["src/**/*.rs", "LICENSE-MIT", "LICENSE-APACHE", "Cargo.toml"]
17 |
18 | [dependencies]
19 | egui_commonmark_backend = { workspace = true }
20 | egui_commonmark_macros = { workspace = true, optional = true }
21 |
22 | egui_extras = { workspace = true }
23 | egui = { workspace = true }
24 |
25 | document-features = { workspace = true, optional = true }
26 |
27 | pulldown-cmark = { workspace = true }
28 |
29 | [features]
30 | default = ["load-images", "pulldown_cmark"]
31 |
32 | ## Enable proc macros for compile time generation of egui widgets from markdown
33 | macros = [
34 | "dep:egui_commonmark_macros",
35 | ] # For simplicity it only supports pulldown-cmark
36 |
37 | ## Builds upon the `macros` feature. Enables tracking of markdown files to recompile
38 | ## when their content changes. Uses nightly features
39 | nightly = ["macros", "egui_commonmark_macros/nightly"]
40 |
41 | # For internal debugging use only!
42 | dump-macro = ["egui_commonmark_macros/dump-macro"]
43 |
44 | ## No-op feature
45 | pulldown_cmark = []
46 |
47 | ## Syntax highlighting for code blocks using syntect
48 | better_syntax_highlighting = [
49 | "egui_commonmark_backend/better_syntax_highlighting",
50 | ]
51 |
52 | ## Enable loading of images. Make sure to also opt in to what image format you need
53 | ## through the image crate.
54 | load-images = ["egui_extras/image", "egui_extras/file"]
55 |
56 | ## Support loading svg images
57 | svg = ["egui_extras/svg"]
58 |
59 | ## Images with urls will be downloaded and displayed
60 | fetch = ["egui_extras/http"]
61 |
62 | ## Allows loading base64 image data urls from within markdown files. e.g: `data:image/png;base64,...`
63 | ## Note that this is really space inefficient. No size limit is in place for the maximum allowed
64 | ## data in the url.
65 | ##
66 | ## This enables the data urls for your entire app as it installs an egui bytes loader
67 | ## in the background.
68 | ##
69 | ## Currently this does not support wasm.
70 | embedded_image = ["egui_commonmark_backend/embedded_image"]
71 |
72 | [dev-dependencies]
73 | eframe = { version = "0.31", default-features = false, features = [
74 | "default_fonts",
75 | "glow",
76 | "wayland",
77 | "x11",
78 | ] }
79 | image = { version = "0.25", default-features = false, features = ["png"] }
80 | egui_commonmark_macros = { workspace = true } # Tests won't build otherswise
81 |
82 | [package.metadata.docs.rs]
83 | features = ["better_syntax_highlighting", "document-features", "macros"]
84 |
--------------------------------------------------------------------------------
/egui_commonmark/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | ../LICENSE-APACHE
--------------------------------------------------------------------------------
/egui_commonmark/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | ../LICENSE-MIT
--------------------------------------------------------------------------------
/egui_commonmark/README.md:
--------------------------------------------------------------------------------
1 | ../README.md
--------------------------------------------------------------------------------
/egui_commonmark/examples/README.md:
--------------------------------------------------------------------------------
1 | # Overview of examples
2 |
3 | ## hello_world.rs
4 |
5 | A good starting point.
6 |
7 | ## interactive.rs
8 |
9 | An interactive example where you can play around with the markdown text at
10 | runtime.
11 |
12 | ## book.rs
13 |
14 | Intended to show all the different rendering features of the crate.
15 |
16 | ## macros.rs
17 |
18 | Features compile time markdown parsing.
19 |
20 | ## show_mut.rs
21 |
22 | How to make checkboxes interactive.
23 |
24 | ## link_hooks.rs
25 |
26 | Allow hijacking links for doing operations within the application such as
27 | changing a markdown page in a book without displaying the destination link.
28 |
29 | ## mixing.rs
30 |
31 | Shows commonmark elements mixed with egui widgets. It displays the widgets with
32 | no spaces in between as if the markdown was egui widgets.
33 |
34 | ## scroll.rs
35 |
36 | Intended to allow showing a long markdown text and only process the displayed
37 | parts. Currently it only works in very basic cases, the feature requires some
38 | more work to be generally useful.
39 |
40 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/book.rs:
--------------------------------------------------------------------------------
1 | //! Make sure to run this example from the repo directory and not the example
2 | //! directory. To see all the features in full effect, run this example with
3 | //! `cargo r --features better_syntax_highlighting,svg,fetch`
4 | //! Add `light` or `dark` to the end of the command to specify theme. Default
5 | //! is system theme. `cargo r --features better_syntax_highlighting,svg,fetch -- dark`
6 | //!
7 | //! Shows a simple way to use the crate to implement a book like view.
8 |
9 | use eframe::egui;
10 | use egui_commonmark::*;
11 |
12 | struct Page {
13 | name: String,
14 | content: String,
15 | }
16 |
17 | struct App {
18 | cache: CommonMarkCache,
19 | curr_tab: Option,
20 | pages: Vec,
21 | }
22 |
23 | impl App {
24 | fn sidepanel(&mut self, ui: &mut egui::Ui) {
25 | egui::SidePanel::left("left_documentation_panel")
26 | .resizable(false)
27 | .default_width(100.0)
28 | .show_inside(ui, |ui| {
29 | let style = ui.style_mut();
30 | style.visuals.widgets.active.bg_stroke = egui::Stroke::NONE;
31 | style.visuals.widgets.hovered.bg_stroke = egui::Stroke::NONE;
32 | style.visuals.widgets.inactive.bg_fill = egui::Color32::TRANSPARENT;
33 | style.visuals.widgets.inactive.bg_stroke = egui::Stroke::NONE;
34 | ui.with_layout(egui::Layout::top_down_justified(egui::Align::LEFT), |ui| {
35 | for (i, p) in self.pages.iter().enumerate() {
36 | if Some(i) == self.curr_tab {
37 | let _ = ui.selectable_label(true, &p.name);
38 | } else if ui.selectable_label(false, &p.name).clicked() {
39 | self.curr_tab = Some(i);
40 | }
41 | ui.separator();
42 | }
43 | });
44 | });
45 | }
46 |
47 | fn content_panel(&mut self, ui: &mut egui::Ui) {
48 | egui::ScrollArea::vertical().show(ui, |ui| {
49 | // Add a frame with margin to prevent the content from hugging the sidepanel
50 | egui::Frame::new()
51 | .inner_margin(egui::Margin::symmetric(5, 0))
52 | .show(ui, |ui| {
53 | CommonMarkViewer::new()
54 | .default_width(Some(200))
55 | .max_image_width(Some(512))
56 | .show(
57 | ui,
58 | &mut self.cache,
59 | &self.pages[self.curr_tab.unwrap_or(0)].content,
60 | );
61 | });
62 | });
63 | }
64 | }
65 |
66 | impl eframe::App for App {
67 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
68 | egui::CentralPanel::default().show(ctx, |ui| {
69 | self.sidepanel(ui);
70 | self.content_panel(ui);
71 | });
72 | }
73 | }
74 |
75 | fn main() -> eframe::Result {
76 | let mut args = std::env::args();
77 | args.next();
78 |
79 | eframe::run_native(
80 | "Markdown viewer",
81 | eframe::NativeOptions::default(),
82 | Box::new(move |cc| {
83 | if let Some(theme) = args.next() {
84 | if theme == "light" {
85 | cc.egui_ctx.set_theme(egui::Theme::Light);
86 | } else if theme == "dark" {
87 | cc.egui_ctx.set_theme(egui::Theme::Dark);
88 | }
89 | }
90 | cc.egui_ctx.style_mut(|style| {
91 | // Show the url of a hyperlink on hover
92 | style.url_in_tooltip = true;
93 | });
94 |
95 | Ok(Box::new(App {
96 | cache: CommonMarkCache::default(),
97 | curr_tab: Some(0),
98 | pages: vec![
99 | Page {
100 | name: "Hello World".to_owned(),
101 | content: include_str!("markdown/hello_world.md").to_owned(),
102 | },
103 | Page {
104 | name: "Headers".to_owned(),
105 | content: include_str!("markdown/headers.md").to_owned(),
106 | },
107 | Page {
108 | name: "Lists".to_owned(),
109 | content: include_str!("markdown/lists.md").to_owned(),
110 | },
111 | Page {
112 | name: "Definition lists".to_owned(),
113 | content: include_str!("markdown/definition_list.md").to_owned(),
114 | },
115 | Page {
116 | name: "Code blocks".to_owned(),
117 | content: include_str!("markdown/code-blocks.md").to_owned(),
118 | },
119 | Page {
120 | name: "Block Quotes".to_owned(),
121 | content: include_str!("markdown/blockquotes.md").to_owned(),
122 | },
123 | Page {
124 | name: "Tables".to_owned(),
125 | content: include_str!("markdown/tables.md").to_owned(),
126 | },
127 | Page {
128 | name: "Embedded Image".to_owned(),
129 | content: include_str!("markdown/embedded_image.md").to_owned(),
130 | },
131 | Page {
132 | name: "Html text".to_owned(),
133 | content: include_str!("markdown/html.md").to_owned(),
134 | },
135 | ],
136 | }))
137 | }),
138 | )
139 | }
140 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/cuddlyferris.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lampsitter/egui_commonmark/86f6a1d4a1fbe38b89f0034de839d879fe540f31/egui_commonmark/examples/cuddlyferris.png
--------------------------------------------------------------------------------
/egui_commonmark/examples/hello_world.rs:
--------------------------------------------------------------------------------
1 | //! Make sure to run this example from the repo directory and not the example
2 | //! directory. To see all the features in full effect, run this example with
3 | //! `cargo r --features better_syntax_highlighting,svg,fetch`
4 | //! Add `light` or `dark` to the end of the command to specify theme. Default
5 | //! is system theme. `cargo r --features better_syntax_highlighting,svg,fetch -- dark`
6 |
7 | use eframe::egui;
8 | use egui_commonmark::*;
9 |
10 | struct App {
11 | cache: CommonMarkCache,
12 | }
13 |
14 | impl eframe::App for App {
15 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
16 | let text = include_str!("markdown/hello_world.md");
17 | egui::CentralPanel::default().show(ctx, |ui| {
18 | egui::ScrollArea::vertical().show(ui, |ui| {
19 | CommonMarkViewer::new()
20 | .max_image_width(Some(512))
21 | .show(ui, &mut self.cache, text);
22 | });
23 | });
24 | }
25 | }
26 |
27 | fn main() -> eframe::Result {
28 | let mut args = std::env::args();
29 | args.next();
30 |
31 | eframe::run_native(
32 | "Markdown viewer",
33 | eframe::NativeOptions::default(),
34 | Box::new(move |cc| {
35 | if let Some(theme) = args.next() {
36 | if theme == "light" {
37 | cc.egui_ctx.set_theme(egui::Theme::Light);
38 | } else if theme == "dark" {
39 | cc.egui_ctx.set_theme(egui::Theme::Dark);
40 | }
41 | }
42 |
43 | cc.egui_ctx.style_mut(|style| {
44 | // Show the url of a hyperlink on hover
45 | style.url_in_tooltip = true;
46 | });
47 |
48 | Ok(Box::new(App {
49 | cache: CommonMarkCache::default(),
50 | }))
51 | }),
52 | )
53 | }
54 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/html.rs:
--------------------------------------------------------------------------------
1 | //! Add `light` or `dark` to the end of the command to specify theme. Default
2 | //! is light. `cargo r --example html -- dark`
3 |
4 | use eframe::egui;
5 | use egui_commonmark::*;
6 | use std::cell::RefCell;
7 | use std::rc::Rc;
8 |
9 | struct App {
10 | cache: CommonMarkCache,
11 | /// To avoid id collisions
12 | counter: Rc>,
13 | }
14 |
15 | impl eframe::App for App {
16 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
17 | *self.counter.as_ref().borrow_mut() = 0;
18 |
19 | egui::CentralPanel::default().show(ctx, |ui| {
20 | egui::ScrollArea::vertical().show(ui, |ui| {
21 | CommonMarkViewer::new()
22 | .render_html_fn({
23 | let counter = Rc::clone(&self.counter);
24 | Some(&move |ui, html| {
25 | // For simplicity lets just hide the content regardless of what kind of
26 | // node it is.
27 | ui.collapsing(
28 | format!("Collapsed {}", counter.as_ref().borrow()),
29 | |ui| {
30 | ui.label(html);
31 | },
32 | );
33 |
34 | *counter.as_ref().borrow_mut() += 1;
35 | })
36 | })
37 | .show(ui, &mut self.cache, EXAMPLE_TEXT);
38 | });
39 | });
40 | }
41 | }
42 |
43 | fn main() -> eframe::Result {
44 | let mut args = std::env::args();
45 | args.next();
46 |
47 | eframe::run_native(
48 | "Markdown viewer",
49 | eframe::NativeOptions::default(),
50 | Box::new(move |cc| {
51 | if let Some(theme) = args.next() {
52 | if theme == "light" {
53 | cc.egui_ctx.set_theme(egui::Theme::Light);
54 | } else if theme == "dark" {
55 | cc.egui_ctx.set_theme(egui::Theme::Dark);
56 | }
57 | }
58 |
59 | cc.egui_ctx.style_mut(|style| {
60 | // Show the url of a hyperlink on hover
61 | style.url_in_tooltip = true;
62 | });
63 |
64 | Ok(Box::new(App {
65 | cache: CommonMarkCache::default(),
66 | counter: Rc::new(RefCell::new(0)),
67 | }))
68 | }),
69 | )
70 | }
71 |
72 | const EXAMPLE_TEXT: &str = r#"
73 | # Customized rendering using html
74 |
75 | some text
76 |
77 |
78 |
79 | some text 2
80 |
81 | "#;
82 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/interactive.rs:
--------------------------------------------------------------------------------
1 | //! Make sure to run this example from the repo directory and not the example
2 | //! directory. To see all the features in full effect, run this example with
3 | //! `cargo r --features better_syntax_highlighting,svg,fetch`
4 | //! Add `light` or `dark` to the end of the command to specify theme. Default
5 | //! is system theme. `cargo r --features better_syntax_highlighting,svg,fetch -- dark`
6 | //!
7 | //! An easy way to visualize rendered markdown interactively
8 |
9 | use eframe::egui;
10 | use egui_commonmark::*;
11 |
12 | struct App {
13 | cache: CommonMarkCache,
14 | markdown: String,
15 | }
16 |
17 | impl eframe::App for App {
18 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
19 | egui::CentralPanel::default().show(ctx, |ui| {
20 | egui::SidePanel::left("left_panel")
21 | .show_inside(ui, |ui| ui.text_edit_multiline(&mut self.markdown));
22 | egui::CentralPanel::default().show_inside(ui, |ui| {
23 | egui::ScrollArea::vertical().show(ui, |ui| {
24 | CommonMarkViewer::new().show(ui, &mut self.cache, &self.markdown);
25 | });
26 | });
27 | });
28 | }
29 | }
30 |
31 | fn main() -> eframe::Result {
32 | let mut args = std::env::args();
33 | args.next();
34 |
35 | eframe::run_native(
36 | "Interactive markdown viewer",
37 | eframe::NativeOptions::default(),
38 | Box::new(move |cc| {
39 | if let Some(theme) = args.next() {
40 | if theme == "light" {
41 | cc.egui_ctx.set_theme(egui::Theme::Light);
42 | } else if theme == "dark" {
43 | cc.egui_ctx.set_theme(egui::Theme::Dark);
44 | }
45 | }
46 |
47 | cc.egui_ctx.style_mut(|style| {
48 | // Show the url of a hyperlink on hover
49 | style.url_in_tooltip = true;
50 | });
51 |
52 | Ok(Box::new(App {
53 | markdown: r#"# Heading
54 |
55 | text with a \
56 | break
57 |
58 | text with a large
59 |
60 | separator
61 |
62 | ```python
63 | if __name__ == "__main__":
64 | pass
65 | ```"#
66 | .to_owned(),
67 | cache: CommonMarkCache::default(),
68 | }))
69 | }),
70 | )
71 | }
72 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/link_hooks.rs:
--------------------------------------------------------------------------------
1 | //! Add `light` or `dark` to the end of the command to specify theme. Default
2 | //! is system theme. `cargo r --example link_hooks -- dark`
3 |
4 | use eframe::egui;
5 | use egui_commonmark::*;
6 |
7 | struct App {
8 | cache: CommonMarkCache,
9 | curr_page: usize,
10 | }
11 |
12 | impl eframe::App for App {
13 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
14 | let p1 = r#"# Page 1
15 | Check out the [next](#next) page."#;
16 | let p2 = r#"# Page 2
17 | Check out the [previous](#prev) page.
18 |
19 | Notice how the destination is not shown on [hover](#prev) unlike with [urls](https://www.example.org)
20 | "#;
21 |
22 | let p = [p1, p2];
23 | if self.cache.get_link_hook("#next").unwrap() {
24 | self.curr_page = 1;
25 | } else if self.cache.get_link_hook("#prev").unwrap() {
26 | self.curr_page = 0;
27 | }
28 |
29 | egui::CentralPanel::default().show(ctx, |ui| {
30 | egui::ScrollArea::vertical().show(ui, |ui| {
31 | CommonMarkViewer::new().show(ui, &mut self.cache, p[self.curr_page]);
32 | });
33 | });
34 | }
35 | }
36 |
37 | fn main() -> eframe::Result {
38 | let mut args = std::env::args();
39 | args.next();
40 |
41 | eframe::run_native(
42 | "Markdown viewer link hooks",
43 | eframe::NativeOptions::default(),
44 | Box::new(move |cc| {
45 | if let Some(theme) = args.next() {
46 | if theme == "light" {
47 | cc.egui_ctx.set_theme(egui::Theme::Light);
48 | } else if theme == "dark" {
49 | cc.egui_ctx.set_theme(egui::Theme::Dark);
50 | }
51 | }
52 |
53 | cc.egui_ctx.style_mut(|style| {
54 | // Show the url of a hyperlink on hover. The demonstration of
55 | // the link hooks would be a little pointless without this
56 | style.url_in_tooltip = true;
57 | });
58 |
59 | let mut cache = CommonMarkCache::default();
60 | cache.add_link_hook("#next");
61 | cache.add_link_hook("#prev");
62 |
63 | Ok(Box::new(App {
64 | cache,
65 | curr_page: 0,
66 | }))
67 | }),
68 | )
69 | }
70 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/macros.rs:
--------------------------------------------------------------------------------
1 | //! Make sure to run this example from the repo directory and not the example
2 | //! directory. To see all the features in full effect, run this example with
3 | //! `cargo r --example macro --features macros,better_syntax_highlighting`
4 | //! Add `light` or `dark` to the end of the command to specify theme. Default
5 | //! is system theme. `cargo r --example macro --features macros,better_syntax_highlighting -- dark`
6 |
7 | use eframe::egui;
8 | use egui_commonmark::*;
9 |
10 | struct App {
11 | cache: CommonMarkCache,
12 | }
13 |
14 | impl eframe::App for App {
15 | fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
16 | egui::CentralPanel::default().show(ctx, |ui| {
17 | egui::ScrollArea::vertical().show(ui, |ui| {
18 | // Embed text directly
19 | commonmark!(ui, &mut self.cache, "Hello, world");
20 |
21 | // In cases like these it's better to use egui::Separator directly
22 | commonmark!(ui, &mut self.cache, "------------");
23 |
24 | // From a file like include_str! NOTE: This does not cause a recompile when the
25 | // file has changed!
26 | commonmark_str!(
27 | ui,
28 | &mut self.cache,
29 | "egui_commonmark/examples/markdown/hello_world.md"
30 | );
31 | commonmark!(ui, &mut self.cache, "------------");
32 |
33 | commonmark_str!(
34 | ui,
35 | &mut self.cache,
36 | "egui_commonmark/examples/markdown/headers.md"
37 | );
38 | commonmark!(ui, &mut self.cache, "------------");
39 |
40 | commonmark_str!(
41 | ui,
42 | &mut self.cache,
43 | "egui_commonmark/examples/markdown/lists.md"
44 | );
45 |
46 | commonmark!(ui, &mut self.cache, "------------");
47 |
48 | commonmark_str!(
49 | ui,
50 | &mut self.cache,
51 | "egui_commonmark/examples/markdown/code-blocks.md"
52 | );
53 |
54 | commonmark!(ui, &mut self.cache, "------------");
55 |
56 | commonmark_str!(
57 | ui,
58 | &mut self.cache,
59 | "egui_commonmark/examples/markdown/blockquotes.md"
60 | );
61 |
62 | commonmark!(ui, &mut self.cache, "------------");
63 |
64 | // The table will end up with the same id as the table in the hello_world file.
65 | // Providing the id explicitly is annoying for all other widgets that are not tables
66 | // so push_id must be used in this case.
67 | ui.push_id("tables", |ui| {
68 | commonmark_str!(
69 | ui,
70 | &mut self.cache,
71 | "egui_commonmark/examples/markdown/tables.md"
72 | );
73 | });
74 |
75 | commonmark!(ui, &mut self.cache, "------------");
76 |
77 | commonmark_str!(
78 | ui,
79 | &mut self.cache,
80 | "egui_commonmark/examples/markdown/definition_list.md"
81 | );
82 | commonmark!(ui, &mut self.cache, "------------");
83 | });
84 | });
85 | }
86 | }
87 |
88 | fn main() -> eframe::Result {
89 | let mut args = std::env::args();
90 | args.next();
91 |
92 | eframe::run_native(
93 | "Markdown viewer",
94 | eframe::NativeOptions::default(),
95 | Box::new(move |cc| {
96 | if let Some(theme) = args.next() {
97 | if theme == "light" {
98 | cc.egui_ctx.set_theme(egui::Theme::Light);
99 | } else if theme == "dark" {
100 | cc.egui_ctx.set_theme(egui::Theme::Dark);
101 | }
102 | }
103 |
104 | cc.egui_ctx.style_mut(|style| {
105 | // Show the url of a hyperlink on hover
106 | style.url_in_tooltip = true;
107 | });
108 |
109 | Ok(Box::new(App {
110 | cache: CommonMarkCache::default(),
111 | }))
112 | }),
113 | )
114 | }
115 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/blockquotes.md:
--------------------------------------------------------------------------------
1 | # Block quotes
2 |
3 | > This is a simple block quote
4 |
5 | > A block quote with more other blocks inside it
6 | >
7 | > ```rust
8 | > fn main() {
9 | > println!("Hello, World!");
10 | > }
11 | > ```
12 |
13 | ## Alerts
14 |
15 | Alerts build upon block quotes.
16 |
17 | ```markdown
18 | > [!NOTE]
19 | > note alert
20 | ```
21 |
22 | or
23 |
24 | ```markdown
25 | > [!NOTE]
26 | >
27 | > note alert
28 | ```
29 |
30 | will be displayed as:
31 |
32 | > [!NOTE]
33 | > note alert
34 |
35 | > [!TIP]
36 | > tip alert
37 |
38 |
39 |
40 | > [!imporTant]
41 | > important alert
42 |
43 | > [!WARNING]
44 | > warning alert
45 |
46 | > [!CAUTION]
47 | >
48 | > caution alert
49 |
50 | The alerts are completely customizable. An arbitrary amount of alerts can be
51 | added
52 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/code-blocks.md:
--------------------------------------------------------------------------------
1 | # Code blocks
2 |
3 | ```rs
4 | use egui_commonmark::*;
5 | let markdown =
6 | r"# Hello world
7 |
8 | * A list
9 | * [ ] Checkbox
10 | ";
11 |
12 | let mut cache = CommonMarkCache::default();
13 | CommonMarkViewer::new("viewer").show(ui, &mut cache, markdown);
14 | ```
15 |
16 | The `better_syntax_highlighting` feature does not have toml highlighting by
17 | default. It will therefore fallback to default highlighting.
18 |
19 | ```toml
20 | egui_commonmark = "0.10"
21 | image = { version = "0.24", default-features = false, features = ["png"] }
22 | ```
23 |
24 | - ```rs
25 | let x = 3.14;
26 | ```
27 | - Code blocks can be in lists too :)
28 |
29 |
30 | More content...
31 |
32 | Inline code blocks are supported if you for some reason need them
33 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/definition_list.md:
--------------------------------------------------------------------------------
1 | # Definition list
2 |
3 | **Term 1**
4 |
5 | : Definition 1
6 |
7 | **Term 2**
8 |
9 | : Definition 2
10 |
11 | ```rs
12 | let x = 3
13 | ```
14 |
15 | Third paragraph of definition 2.
16 |
17 | An easy way to have indentation without the bullet points of lists
18 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/embedded_image.md:
--------------------------------------------------------------------------------
1 | # Embedded image
2 |
3 | Requires the `embedded_image` feature to be enabled which will install a
4 | bytes loader globally.
5 |
6 | 
7 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/headers.md:
--------------------------------------------------------------------------------
1 |
2 | # Header 1
3 |
4 | ## Header 2
5 |
6 | ### Header 3
7 |
8 | #### Header 4
9 |
10 | ##### Header 5
11 |
12 | ###### Header 6
13 |
14 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/hello_world.md:
--------------------------------------------------------------------------------
1 | # Commonmark Viewer Example
2 |
3 | A *bunch* ~~of~~ __different__ `text` styles.
4 |
5 |
6 | 
7 |
8 | | __A table!__ |
9 | | ------------ |
10 | | Aa |
11 | | *Bb* |
12 | | Cc |
13 |
14 | [Link to repo](https://github.com/lampsitter/egui_commonmark)
15 |
16 | ```rs
17 | let mut vec = Vec::new();
18 | vec.push(5);
19 | ```
20 |
21 | > Some smart quote here
22 |
23 | - [ ] A feature[^1]
24 | - [X] A completed feature
25 | 1. Sub item
26 |
27 | [^1]: A footnote
28 |
29 | # Header 1
30 | ## Header 2
31 | ### Header 3
32 | #### Header 4
33 | ##### Header 5
34 | ###### Header 6
35 |
36 | Some text.
37 |
--------------------------------------------------------------------------------
/egui_commonmark/examples/markdown/html.md:
--------------------------------------------------------------------------------
1 | # Html
2 |
3 | Inline Html is rendered as text
4 |
5 |