diff --git a/py/examples/markdown.py b/py/examples/markdown.py index dc4a6cb38d1..94d59cd73ab 100644 --- a/py/examples/markdown.py +++ b/py/examples/markdown.py @@ -14,6 +14,8 @@ ___ The **quick** __brown__ *fox* **_jumped_ over** the ~~lazy~~ _dog_. +This is superscript and this is subscript! + Block quote: > The quick brown fox jumped over the lazy dog. @@ -37,12 +39,6 @@ - First nested list item - Second nested list item - - -Ignore \*markdown\* formatting. - -This framework is made by [h2o.ai](https://h2o.ai) - Image: ![Monty Python](https://upload.wikimedia.org/wikipedia/en/c/cb/Flyingcircus_2.jpg) @@ -61,8 +57,7 @@ Inline code: -Use `git status` to list all new or modified files that haven't yet been committed. - +Use `ui.markdown_card` to start creating your own markdown content! Code block: @@ -81,17 +76,13 @@ async def serve(q: Q): await q.page.save() ``` -This is superscript and this is subscript! + -Linking --------------------- +Ignore \*markdown\* formatting. -Search with [Google][1], -[Yahoo][2] or [MSN][3]. +Linking: - [1]: http://google.com/ "Google" - [2]: http://search.yahoo.com/ "Yahoo Search" - [3]: http://search.msn.com/ "MSN Search" +This framework is made by [h2o.ai](https://h2o.ai) ''' @app('/demo') diff --git a/ui/src/markdown.tsx b/ui/src/markdown.tsx index f908988335a..ea1a9f7d671 100644 --- a/ui/src/markdown.tsx +++ b/ui/src/markdown.tsx @@ -51,8 +51,8 @@ const } }, }) -const highlightSyntax = async (str: S, language: S, codeBlockId: S) => { - const codeBlock = document.getElementById(codeBlockId) +const highlightSyntax = async (str: S, language: S, codeElementId: S) => { + const codeBlock = document.getElementById(codeElementId) if (!codeBlock) return '' if (language) { try { @@ -81,21 +81,23 @@ const highlightSyntax = async (str: S, language: S, codeBlockId: S) => { return highlightedCode } -export const Markdown = ({ source, compact = true }: { source: S, compact?: B }) => { +export const Markdown = ({ source, name, compact = true }: { source: S, name: S, compact?: B }) => { const prevHighlights = React.useRef([]), // Prevent flicker during streaming. codeBlockIdx = React.useRef(0), // MarkdownIt parses code blocks sequentially, which is a problem for streaming. markdown = React.useMemo(() => MarkdownIt({ html: true, linkify: true, typographer: true, highlight: (str, lang) => { const codeBlockId = codeBlockIdx.current.toString() + // Use the unique html element id to avoid conflicts when multiple markdown cards are rendered on the same page. + const codeElementId = `${name}-${codeBlockId}` if (prevHighlights.current.length === codeBlockIdx.current) prevHighlights.current.push('') // HACK: MarkdownIt does not support async rules. // https://github.com/markdown-it/markdown-it/blob/master/docs/development.md#i-need-async-rule-how-to-do-it - setTimeout(async () => prevHighlights.current[+codeBlockId] = await highlightSyntax(str, lang, codeBlockId), 0) + setTimeout(async () => prevHighlights.current[+codeBlockId] = await highlightSyntax(str, lang, codeElementId), 0) // TODO: Sanitize the HTML. - const ret = `${prevHighlights.current[codeBlockIdx.current] || str}` + const ret = `${prevHighlights.current[codeBlockIdx.current] || str}` codeBlockIdx.current++ return ret } @@ -163,7 +165,7 @@ export const
{title &&
{title}
}
- +
)