WYSIWYG Markdown Editor #3092
Replies: 3 comments 2 replies
-
I wanted to update you guys and share my current, initial approach. export default {
template: `
<div class='content'></div>
<div
id='preview'
class='preview'
contentEditable='true'
@input="handleInput"
>
<slot></slot>
</div>
`,
methods: {
handleInput(event) {
// Emit custom event when content changes
this.$emit('contentChanged', event.target.innerHTML);
}
}
} from nicegui import ui, app
from nicegui.element import Element
class Writer(Element, component='div.js'):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.on("contentChanged", self.on_content_change)
async def on_content_change(self, e):
# print(e.args)
print(e.args)
await ui.run_javascript(f'''
document.getElementsByClassName('content')[0].innerHTML = marked.parse("{e.args}");
''') |
Beta Was this translation helpful? Give feedback.
-
Hmm. I've got some more progress that I wanted to share. I think I've got my first actual working prototype. import os
from functools import lru_cache
from typing import List
import markdown2
from pygments.formatters import HtmlFormatter
import nicegui.elements.mixins.content_element as content_element
class Markdown(content_element.ContentElement, component='markdown.js'):
def __init__(self,
content: str = '', *,
extras: List[str] = ['fenced-code-blocks', 'tables'],
) -> None:
self.extras = extras[:]
super().__init__(content=content)
self._classes.append('nicegui-markdown')
self._props['contenteditable'] = True
self._props['codehilite_css'] = (
HtmlFormatter(nobackground=True).get_style_defs('.codehilite') +
HtmlFormatter(nobackground=True, style='github-dark').get_style_defs('.body--dark .codehilite')
)
self.on('input', self._print_content)
def _print_content(self, e) -> None:
self.content += e.args['data']
self._handle_content_change(self.content)
def _handle_content_change(self, content: str) -> None:
html = prepare_content(content, extras=' '.join(self.extras))
if self._props.get('innerHTML') != html:
self._props['innerHTML'] = html
self.update()
@lru_cache(maxsize=int(os.environ.get('MARKDOWN_CONTENT_CACHE_SIZE', '1000')))
def prepare_content(content: str, extras: str) -> str:
"""Render Markdown content to HTML."""
return markdown2.markdown(remove_indentation(content), extras=extras.split())
def remove_indentation(text: str) -> str:
"""Remove indentation from a multi-line string based on the indentation of the first non-empty line."""
lines = text.splitlines()
while lines and not lines[0].strip():
lines.pop(0)
if not lines:
return ''
indentation = len(lines[0]) - len(lines[0].lstrip())
return '\n'.join(line[indentation:] for line in lines) export default {
template: `<div></div>`,
async mounted() {
this.ensure_codehilite_css();
if (this.use_mermaid) {
this.mermaid = (await import("mermaid")).default;
this.renderMermaid();
}
},
data() {
return {
mermaid: null,
};
},
updated() {
this.renderMermaid();
},
methods: {
renderMermaid() {
this.$el.querySelectorAll(".mermaid-pre").forEach(async (pre, i) => {
await this.mermaid.run({ nodes: [pre.children[0]] });
});
},
ensure_codehilite_css() {
if (!document.querySelector(`style[data-codehilite-css]`)) {
const style = document.createElement("style");
style.setAttribute("data-codehilite-css", "");
style.innerHTML = this.codehilite_css;
document.head.appendChild(style);
}
},
},
props: {
codehilite_css: String,
use_mermaid: {
required: false,
default: false,
type: Boolean,
},
},
}; |
Beta Was this translation helpful? Give feedback.
-
Is it implemented until now? |
Beta Was this translation helpful? Give feedback.
-
I'm aware that we already have the https://nicegui.io/documentation/section_data_elements#editor, and a codemirror component. However, I am wondering if there is a way that we can have an element that supports editing the live preview of Markdown. I've been looking into this out of curiousity and almost all of the WYSIWYG editors only have the split screen option which shows the live output, but doesn't allow you to edit that directly. I was wondering if there was a way that we could have users edit it directly.
Something like https://github.com/sparksuite/simplemde-markdown-editor is nice, however it still doesn't show the live preview. This just updates the editor to show you what it might look like, without showing you the direct editor. This is similar to our CodeMirror component, which gives you an idea of what the syntax you just wrote does, but doesn't render that.
I'd be happy to help if someone has an idea of how we might be able to do this.
Beta Was this translation helpful? Give feedback.
All reactions