1use assets::Assets;
2use gpui::{prelude::*, rgb, App, KeyBinding, StyleRefinement, View, WindowOptions};
3use language::{language_settings::AllLanguageSettings, LanguageRegistry};
4use markdown::{Markdown, MarkdownStyle};
5use node_runtime::NodeRuntime;
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 = NodeRuntime::unavailable();
106 theme::init(LoadThemes::JustBase, cx);
107
108 let language_registry = LanguageRegistry::new(cx.background_executor().clone());
109 language_registry.set_theme(cx.theme().clone());
110 let language_registry = Arc::new(language_registry);
111 languages::init(language_registry.clone(), node_runtime, cx);
112 Assets.load_fonts(cx).unwrap();
113
114 cx.activate(true);
115 cx.open_window(WindowOptions::default(), |cx| {
116 cx.new_view(|cx| {
117 let markdown_style = MarkdownStyle {
118 base_text_style: gpui::TextStyle {
119 font_family: "Zed Plex Sans".into(),
120 color: cx.theme().colors().terminal_ansi_black,
121 ..Default::default()
122 },
123 code_block: StyleRefinement::default()
124 .font_family("Zed Plex Mono")
125 .m(rems(1.))
126 .bg(rgb(0xAAAAAAA)),
127 inline_code: gpui::TextStyleRefinement {
128 font_family: Some("Zed Mono".into()),
129 color: Some(cx.theme().colors().editor_foreground),
130 background_color: Some(cx.theme().colors().editor_background),
131 ..Default::default()
132 },
133 rule_color: Color::Muted.color(cx),
134 block_quote_border_color: Color::Muted.color(cx),
135 block_quote: gpui::TextStyleRefinement {
136 color: Some(Color::Muted.color(cx)),
137 ..Default::default()
138 },
139 link: gpui::TextStyleRefinement {
140 color: Some(Color::Accent.color(cx)),
141 underline: Some(gpui::UnderlineStyle {
142 thickness: px(1.),
143 color: Some(Color::Accent.color(cx)),
144 wavy: false,
145 }),
146 ..Default::default()
147 },
148 syntax: cx.theme().syntax().clone(),
149 selection_background_color: {
150 let mut selection = cx.theme().players().local().selection;
151 selection.fade_out(0.7);
152 selection
153 },
154 ..Default::default()
155 };
156
157 MarkdownExample::new(
158 MARKDOWN_EXAMPLE.to_string(),
159 markdown_style,
160 language_registry,
161 cx,
162 )
163 })
164 })
165 .unwrap();
166 });
167}
168
169struct MarkdownExample {
170 markdown: View<Markdown>,
171}
172
173impl MarkdownExample {
174 pub fn new(
175 text: String,
176 style: MarkdownStyle,
177 language_registry: Arc<LanguageRegistry>,
178 cx: &mut WindowContext,
179 ) -> Self {
180 let markdown =
181 cx.new_view(|cx| Markdown::new(text, style, Some(language_registry), None, cx));
182 Self { markdown }
183 }
184}
185
186impl Render for MarkdownExample {
187 fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
188 div()
189 .id("markdown-example")
190 .debug_selector(|| "foo".into())
191 .relative()
192 .bg(gpui::white())
193 .size_full()
194 .p_4()
195 .overflow_y_scroll()
196 .child(self.markdown.clone())
197 }
198}