1use assets::Assets;
2use gpui::{prelude::*, rgb, App, KeyBinding, StyleRefinement, Task, View, WindowOptions};
3use language::{language_settings::AllLanguageSettings, LanguageRegistry};
4use markdown::{Markdown, MarkdownStyle};
5use node_runtime::FakeNodeRuntime;
6use settings::SettingsStore;
7use std::sync::Arc;
8use theme::LoadThemes;
9use ui::prelude::*;
10use ui::{div, WindowContext};
11
12const MARKDOWN_EXAMPLE: &str = r#"
13# Markdown Example Document
14
15## Headings
16Headings are created by adding one or more `#` symbols before your heading text. The number of `#` you use will determine the size of the heading.
17
18```rust
19gpui::window::ViewContext
20impl<'a, V> ViewContext<'a, V>
21pub fn on_blur(&mut self, handle: &FocusHandle, listener: impl FnMut(&mut V, &mut iewContext<V>) + 'static) -> Subscription
22where
23 // Bounds from impl:
24 V: 'static,
25```
26
27## Emphasis
28Emphasis can be added with italics or bold. *This text will be italic*. _This will also be italic_
29
30## Lists
31
32### Unordered Lists
33Unordered lists use asterisks `*`, plus `+`, or minus `-` as list markers.
34
35* Item 1
36* Item 2
37 * Item 2a
38 * Item 2b
39
40### Ordered Lists
41Ordered lists use numbers followed by a period.
42
431. Item 1
442. Item 2
453. Item 3
46 1. Item 3a
47 2. Item 3b
48
49## Links
50Links are created using the format [http://zed.dev](https://zed.dev).
51
52They can also be detected automatically, for example https://zed.dev/blog.
53
54## Images
55Images are like links, but with an exclamation mark `!` in front.
56
57```todo!
58
59```
60
61## Code
62Inline `code` can be wrapped with backticks `` ` ``.
63
64```markdown
65Inline `code` has `back-ticks around` it.
66```
67
68Code blocks can be created by indenting lines by four spaces or with triple backticks ```.
69
70```javascript
71function test() {
72 console.log("notice the blank line before this function?");
73}
74```
75
76## Blockquotes
77Blockquotes are created with `>`.
78
79> This is a blockquote.
80
81## Horizontal Rules
82Horizontal rules are created using three or more asterisks `***`, dashes `---`, or underscores `___`.
83
84## Line breaks
85This is a
86\
87line break!
88
89---
90
91Remember, markdown processors may have slight differences and extensions, so always refer to the specific documentation or guides relevant to your platform or editor for the best practices and additional features.
92"#;
93
94pub fn main() {
95 env_logger::init();
96 App::new().with_assets(Assets).run(|cx| {
97 let store = SettingsStore::test(cx);
98 cx.set_global(store);
99 language::init(cx);
100 SettingsStore::update(cx, |store, cx| {
101 store.update_user_settings::<AllLanguageSettings>(cx, |_| {});
102 });
103 cx.bind_keys([KeyBinding::new("cmd-c", markdown::Copy, None)]);
104
105 let node_runtime = FakeNodeRuntime::new();
106 theme::init(LoadThemes::JustBase, cx);
107
108 let language_registry =
109 LanguageRegistry::new(Task::ready(()), cx.background_executor().clone());
110 language_registry.set_theme(cx.theme().clone());
111 let language_registry = Arc::new(language_registry);
112 languages::init(language_registry.clone(), node_runtime, cx);
113 Assets.load_fonts(cx).unwrap();
114
115 cx.activate(true);
116 cx.open_window(WindowOptions::default(), |cx| {
117 cx.new_view(|cx| {
118 let markdown_style = MarkdownStyle {
119 base_text_style: gpui::TextStyle {
120 font_family: "Zed Plex Sans".into(),
121 color: cx.theme().colors().terminal_ansi_black,
122 ..Default::default()
123 },
124 code_block: StyleRefinement::default()
125 .font_family("Zed Plex Mono")
126 .m(rems(1.))
127 .bg(rgb(0xAAAAAAA)),
128 inline_code: gpui::TextStyleRefinement {
129 font_family: Some("Zed Mono".into()),
130 color: Some(cx.theme().colors().editor_foreground),
131 background_color: Some(cx.theme().colors().editor_background),
132 ..Default::default()
133 },
134 rule_color: Color::Muted.color(cx),
135 block_quote_border_color: Color::Muted.color(cx),
136 block_quote: gpui::TextStyleRefinement {
137 color: Some(Color::Muted.color(cx)),
138 ..Default::default()
139 },
140 link: gpui::TextStyleRefinement {
141 color: Some(Color::Accent.color(cx)),
142 underline: Some(gpui::UnderlineStyle {
143 thickness: px(1.),
144 color: Some(Color::Accent.color(cx)),
145 wavy: false,
146 }),
147 ..Default::default()
148 },
149 syntax: cx.theme().syntax().clone(),
150 selection_background_color: {
151 let mut selection = cx.theme().players().local().selection;
152 selection.fade_out(0.7);
153 selection
154 },
155 ..Default::default()
156 };
157
158 MarkdownExample::new(
159 MARKDOWN_EXAMPLE.to_string(),
160 markdown_style,
161 language_registry,
162 cx,
163 )
164 })
165 })
166 .unwrap();
167 });
168}
169
170struct MarkdownExample {
171 markdown: View<Markdown>,
172}
173
174impl MarkdownExample {
175 pub fn new(
176 text: String,
177 style: MarkdownStyle,
178 language_registry: Arc<LanguageRegistry>,
179 cx: &mut WindowContext,
180 ) -> Self {
181 let markdown =
182 cx.new_view(|cx| Markdown::new(text, style, Some(language_registry), cx, None));
183 Self { markdown }
184 }
185}
186
187impl Render for MarkdownExample {
188 fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
189 div()
190 .id("markdown-example")
191 .debug_selector(|| "foo".into())
192 .relative()
193 .bg(gpui::white())
194 .size_full()
195 .p_4()
196 .overflow_y_scroll()
197 .child(self.markdown.clone())
198 }
199}