瀏覽代碼

fix styling for editor and markdown content (#2045)

Falko Schindler 1 年之前
父節點
當前提交
22d29ec3ff

+ 1 - 0
nicegui/elements/editor.py

@@ -21,5 +21,6 @@ class Editor(ValueElement, DisableableElement):
         :param on_change: callback to be invoked when the value changes
         :param on_change: callback to be invoked when the value changes
         """
         """
         super().__init__(tag='q-editor', value=value, on_value_change=on_change)
         super().__init__(tag='q-editor', value=value, on_value_change=on_change)
+        self._classes.append('nicegui-editor')
         if placeholder is not None:
         if placeholder is not None:
             self._props['placeholder'] = placeholder
             self._props['placeholder'] = placeholder

+ 1 - 21
nicegui/elements/markdown.py

@@ -1,5 +1,4 @@
 import os
 import os
-import re
 from functools import lru_cache
 from functools import lru_cache
 from typing import List
 from typing import List
 
 
@@ -41,26 +40,7 @@ class Markdown(ContentElement, component='markdown.js'):
 @lru_cache(maxsize=int(os.environ.get('MARKDOWN_CONTENT_CACHE_SIZE', '1000')))
 @lru_cache(maxsize=int(os.environ.get('MARKDOWN_CONTENT_CACHE_SIZE', '1000')))
 def prepare_content(content: str, extras: str) -> str:
 def prepare_content(content: str, extras: str) -> str:
     """Render Markdown content to HTML."""
     """Render Markdown content to HTML."""
-    html = markdown2.markdown(remove_indentation(content), extras=extras.split())
-    return apply_tailwind(html)  # we need explicit Markdown styling because tailwind CSS removes all default styles
-
-
-def apply_tailwind(html: str) -> str:
-    """Apply tailwind CSS classes to the HTML."""
-    rep = {
-        '<h1': '<h1 class="text-5xl mb-4 mt-6"',
-        '<h2': '<h2 class="text-4xl mb-3 mt-5"',
-        '<h3': '<h3 class="text-3xl mb-2 mt-4"',
-        '<h4': '<h4 class="text-2xl mb-1 mt-3"',
-        '<h5': '<h5 class="text-1xl mb-0.5 mt-2"',
-        '<a': '<a class="underline text-blue-600 hover:text-blue-800 visited:text-purple-600"',
-        '<ul': '<ul class="list-disc ml-6"',
-        '<p>': '<p class="mb-2">',
-        r'<div\ class="codehilite">': '<div class="codehilite mb-2 p-2">',
-        '<code': '<code style="background-color: transparent"',
-    }
-    pattern = re.compile('|'.join(rep.keys()))
-    return pattern.sub(lambda m: rep[re.escape(m.group(0))], html)
+    return markdown2.markdown(remove_indentation(content), extras=extras.split())
 
 
 
 
 def remove_indentation(text: str) -> str:
 def remove_indentation(text: str) -> str:

+ 113 - 13
nicegui/static/nicegui.css

@@ -71,6 +71,119 @@
   content: ""; /* the gap compensates for the missing vertical padding */
   content: ""; /* the gap compensates for the missing vertical padding */
 }
 }
 
 
+/* revert Tailwind's CSS reset for ui.editor and ui.markdown */
+.nicegui-editor .q-editor__content h1,
+.nicegui-markdown h1 {
+  font-size: 3rem;
+  line-height: 1;
+  margin-bottom: 1rem;
+  margin-top: 1.5rem;
+  font-weight: 300;
+}
+.nicegui-editor .q-editor__content h2,
+.nicegui-markdown h2 {
+  font-size: 2.25rem;
+  line-height: 2.5rem;
+  margin-bottom: 0.75rem;
+  margin-top: 1.25rem;
+  font-weight: 300;
+}
+.nicegui-editor .q-editor__content h3,
+.nicegui-markdown h3 {
+  font-size: 1.875rem;
+  line-height: 2.25rem;
+  margin-bottom: 0.5rem;
+  margin-top: 1rem;
+  font-weight: 400;
+}
+.nicegui-editor .q-editor__content h4,
+.nicegui-markdown h4 {
+  font-size: 1.5rem;
+  line-height: 2rem;
+  margin-bottom: 0.25rem;
+  margin-top: 0.75rem;
+  font-weight: 400;
+}
+.nicegui-editor .q-editor__content h5,
+.nicegui-markdown h5 {
+  font-size: 1.25rem;
+  line-height: 1.75rem;
+  margin-bottom: 0.125rem;
+  margin-top: 0.5rem;
+  font-weight: 400;
+}
+.nicegui-editor .q-editor__content h6,
+.nicegui-markdown h6 {
+  font-size: 1.125rem;
+  line-height: 1.75rem;
+  margin-bottom: 0.125rem;
+  margin-top: 0.5rem;
+  font-weight: 500;
+}
+.nicegui-editor .q-editor__content a,
+.nicegui-markdown a {
+  text-decoration-line: underline;
+  color: rgb(37 99 235); /* blue-600 */
+}
+.nicegui-editor .q-editor__content a:hover,
+.nicegui-markdown a:hover {
+  color: rgb(30 64 175); /* blue-800 */
+}
+.nicegui-editor .q-editor__content a:visited,
+.nicegui-markdown a:visited {
+  color: rgb(147 51 234); /* purple-600 */
+}
+.nicegui-editor .q-editor__content hr,
+.nicegui-markdown hr {
+  margin-block-start: 0.5em;
+  margin-block-end: 0.5em;
+  height: 1px;
+  border-style: none;
+  background-color: rgba(128, 128, 128, 0.25);
+}
+.nicegui-editor .q-editor__content ul,
+.nicegui-markdown ul {
+  list-style-type: initial;
+  padding-inline-start: 2.5rem;
+  margin-block-start: 0.25rem;
+  margin-block-end: 0.25rem;
+}
+.nicegui-editor .q-editor__content ol,
+.nicegui-markdown ol {
+  list-style-type: decimal;
+  padding-inline-start: 2.5rem;
+  margin-block-start: 0.25rem;
+  margin-block-end: 0.25rem;
+}
+.nicegui-editor .q-editor__content blockquote,
+.nicegui-markdown blockquote {
+  border-left: 0.25rem solid #8884;
+  padding: 0.25rem 1rem 0.25rem 1rem;
+  margin: 0.5rem 0;
+}
+.nicegui-editor .q-editor__content p,
+.nicegui-markdown p {
+  margin: 0.5rem 0;
+}
+.nicegui-editor .q-editor__content table,
+.nicegui-markdown table {
+  border-collapse: collapse;
+  margin: 0.5rem 0;
+}
+.nicegui-editor .q-editor__content th,
+.nicegui-markdown th {
+  padding: 0.5rem;
+  border: 1px solid #8884;
+}
+.nicegui-editor .q-editor__content td,
+.nicegui-markdown td {
+  padding: 0.5rem;
+  border: 1px solid #8884;
+}
+.nicegui-markdown .codehilite pre {
+  margin: 0.5rem 0;
+}
+
 /* other NiceGUI elements */
 /* other NiceGUI elements */
 .nicegui-grid {
 .nicegui-grid {
   display: grid;
   display: grid;
@@ -102,19 +215,6 @@
   opacity: 1 !important;
   opacity: 1 !important;
   cursor: text !important;
   cursor: text !important;
 }
 }
-.nicegui-markdown blockquote {
-  border-left: 0.25rem solid #8884;
-  padding: 1rem 1rem 0.5rem 1rem;
-  margin: 1rem 0;
-}
-.nicegui-markdown th {
-  padding: 0.5rem;
-  border: 1px solid #8884;
-}
-.nicegui-markdown td {
-  padding: 0.5rem;
-  border: 1px solid #8884;
-}
 h6.q-timeline__title {
 h6.q-timeline__title {
   font-size: 1.25rem;
   font-size: 1.25rem;
   font-weight: 500;
   font-weight: 500;

+ 13 - 7
website/documentation/reference.py

@@ -5,7 +5,6 @@ from typing import Callable, Optional
 import docutils.core
 import docutils.core
 
 
 from nicegui import binding, ui
 from nicegui import binding, ui
-from nicegui.elements.markdown import apply_tailwind, remove_indentation
 
 
 from ..style import subheading
 from ..style import subheading
 
 
@@ -38,9 +37,7 @@ def generate_class_doc(class_obj: type) -> None:
                     _render_docstring(method.__doc__).classes('ml-8')
                     _render_docstring(method.__doc__).classes('ml-8')
     if ancestors:
     if ancestors:
         subheading('Inherited from')
         subheading('Inherited from')
-        with ui.column().classes('gap-2'):
-            for ancestor in ancestors:
-                ui.markdown(f'- `{ancestor.__name__}`')
+        ui.markdown('\n'.join(f'- `{ancestor.__name__}`' for ancestor in ancestors))
 
 
 
 
 def _is_method_or_property(cls: type, attribute_name: str) -> bool:
 def _is_method_or_property(cls: type, attribute_name: str) -> bool:
@@ -92,10 +89,19 @@ def _generate_method_signature_description(method: Callable) -> str:
 
 
 
 
 def _render_docstring(doc: str, with_params: bool = True) -> ui.html:
 def _render_docstring(doc: str, with_params: bool = True) -> ui.html:
-    doc = remove_indentation(doc)
+    doc = _remove_indentation_from_docstring(doc)
     doc = doc.replace('param ', '')
     doc = doc.replace('param ', '')
     html = docutils.core.publish_parts(doc, writer_name='html5_polyglot')['html_body']
     html = docutils.core.publish_parts(doc, writer_name='html5_polyglot')['html_body']
-    html = apply_tailwind(html)
     if not with_params:
     if not with_params:
         html = re.sub(r'<dl class=".* simple">.*?</dl>', '', html, flags=re.DOTALL)
         html = re.sub(r'<dl class=".* simple">.*?</dl>', '', html, flags=re.DOTALL)
-    return ui.html(html).classes('documentation bold-links arrow-links')
+    return ui.html(html).classes('bold-links arrow-links nicegui-markdown')
+
+
+def _remove_indentation_from_docstring(text: str) -> str:
+    lines = text.splitlines()
+    if not lines:
+        return ''
+    if len(lines) == 1:
+        return lines[0]
+    indentation = min(len(line) - len(line.lstrip()) for line in lines[1:] if line.strip())
+    return lines[0] + '\n'.join(line[indentation:] for line in lines[1:])

+ 1 - 3
website/documentation/rendering.py

@@ -1,7 +1,6 @@
 import docutils.core
 import docutils.core
 
 
 from nicegui import ui
 from nicegui import ui
-from nicegui.elements.markdown import apply_tailwind
 
 
 from ..header import add_head_html, add_header
 from ..header import add_head_html, add_header
 from ..style import section_heading, subheading
 from ..style import section_heading, subheading
@@ -43,8 +42,7 @@ def render_page(documentation: DocumentationPage, *, with_menu: bool = True) ->
                 if part.description_format == 'rst':
                 if part.description_format == 'rst':
                     description = part.description.replace('param ', '')
                     description = part.description.replace('param ', '')
                     html = docutils.core.publish_parts(description, writer_name='html5_polyglot')['html_body']
                     html = docutils.core.publish_parts(description, writer_name='html5_polyglot')['html_body']
-                    html = apply_tailwind(html)
-                    ui.html(html).classes('bold-links arrow-links')
+                    ui.html(html).classes('bold-links arrow-links nicegui-markdown')
                 else:
                 else:
                     ui.markdown(part.description).classes('bold-links arrow-links')
                     ui.markdown(part.description).classes('bold-links arrow-links')
             if part.ui:
             if part.ui:

+ 1 - 1
website/static/style.css

@@ -119,7 +119,7 @@ dl.docinfo dd {
 }
 }
 dl.field-list p,
 dl.field-list p,
 dl.docinfo p {
 dl.docinfo p {
-  margin-bottom: 0;
+  margin: 0;
 }
 }
 
 
 .dark-box {
 .dark-box {

+ 1 - 2
website/style.py

@@ -51,8 +51,7 @@ def features(icon: str, title_: str, items: List[str]) -> None:
     with ui.column().classes('gap-1'):
     with ui.column().classes('gap-1'):
         ui.icon(icon).classes('max-sm:hidden text-3xl md:text-5xl mb-3 text-primary opacity-80')
         ui.icon(icon).classes('max-sm:hidden text-3xl md:text-5xl mb-3 text-primary opacity-80')
         ui.label(title_).classes('font-bold mb-3')
         ui.label(title_).classes('font-bold mb-3')
-        for item in items:
-            ui.markdown(f'- {item}').classes('bold-links arrow-links')
+        ui.markdown('\n'.join(f'- {item}' for item in items)).classes('bold-links arrow-links -ml-4')
 
 
 
 
 def side_menu() -> ui.left_drawer:
 def side_menu() -> ui.left_drawer: