mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-09-06 00:02:13 +00:00
fix(frontend): render ordered lists in markdown descriptions
`GfmMarkdown` defaulted to `prose-xs`, which Tailwind Typography does not define — the class only ever matched four hand-rolled rules in app.css, all scoped to `ul`. Every surface on that default (script and flow descriptions, flow-graph notes, markdown job results) therefore rendered `<ol>` with Preflight's `list-style: none` and no typography at all: no numbers, no heading or paragraph rhythm. Route the default through the shared `markdownProse` stacks instead, and cut the app.css list rules down to the dash glyph so ordered and unordered lists share Tailwind Typography's indentation and rhythm. Fixes #10971 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S6G5gDXJnm6uqch4uCPkPE
This commit is contained in:
co-authored by
Claude Opus 5
parent
fda7b3f086
commit
fe36aa34f0
@@ -209,33 +209,25 @@
|
||||
U+1fac6, U+1fae0-1fae6, U+1fae8-1faea, U+1faef-1faf8;
|
||||
}
|
||||
|
||||
.prose-xs ul {
|
||||
margin-top: 0.5rem;
|
||||
list-style-type: '- ';
|
||||
padding-left: 1.5rem;
|
||||
}
|
||||
|
||||
/* Bullets read as a dash rather than a disc. Only the glyph is overridden:
|
||||
indentation and vertical rhythm stay with Tailwind Typography so ordered
|
||||
and unordered lists line up with each other. */
|
||||
.prose ul {
|
||||
margin-top: 1.5rem;
|
||||
list-style-type: '- ';
|
||||
padding-left: 3rem;
|
||||
}
|
||||
|
||||
/* The '- ' list markers, horizontal rules and blockquote bars otherwise
|
||||
fall through to Tailwind Typography's default bullet/border colors, which
|
||||
are nearly invisible on dark backgrounds (e.g. the AI chat). Use
|
||||
theme-aware tokens so they stay readable in both light and dark mode. */
|
||||
.prose-xs ul > li::marker,
|
||||
.prose ul > li::marker {
|
||||
/* The list markers, horizontal rules and blockquote bars otherwise fall
|
||||
through to Tailwind Typography's default bullet/border colors, which are
|
||||
nearly invisible on dark backgrounds (e.g. the AI chat). Use theme-aware
|
||||
tokens so they stay readable in both light and dark mode. */
|
||||
.prose :is(ul, ol) > li::marker {
|
||||
color: rgb(var(--color-text-secondary));
|
||||
}
|
||||
|
||||
.prose-xs hr,
|
||||
.prose hr {
|
||||
border-top-color: rgb(var(--color-border-normal));
|
||||
}
|
||||
|
||||
.prose-xs blockquote,
|
||||
.prose blockquote {
|
||||
border-left-color: rgb(var(--color-border-normal));
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
import Alert from './common/alert/Alert.svelte'
|
||||
import AutoDataTable from './table/AutoDataTable.svelte'
|
||||
import Markdown from 'svelte-exmarkdown'
|
||||
import { markdownProse } from './markdownProse'
|
||||
import Toggle from './Toggle.svelte'
|
||||
import FileDownload from './common/fileDownload/FileDownload.svelte'
|
||||
|
||||
@@ -1229,7 +1230,7 @@
|
||||
</div>
|
||||
</div>
|
||||
{:else if !forceJson && resultKind === 'markdown'}
|
||||
<div class="prose-xs dark:prose-invert !list-disc !list-outside">
|
||||
<div class={markdownProse.sm}>
|
||||
<Markdown md={result?.md ?? result?.markdown} />
|
||||
</div>
|
||||
{:else if largeObject || hasBigInt}
|
||||
|
||||
@@ -6,12 +6,11 @@
|
||||
interface Props {
|
||||
md: string
|
||||
noPadding?: boolean
|
||||
/** Shared prose stack to render with. Omitted keeps the legacy `prose-xs`,
|
||||
* which the flow-graph notes are laid out against. */
|
||||
/** Shared prose stack to render with. */
|
||||
prose?: MarkdownProseSize
|
||||
}
|
||||
|
||||
let { md, noPadding, prose }: Props = $props()
|
||||
let { md, noPadding, prose = 'xs' }: Props = $props()
|
||||
|
||||
// Rendering markdown turns `` into a real `<img>`, i.e. a request. On the
|
||||
// public replay page the source is a recording from an arbitrary origin and the
|
||||
@@ -21,7 +20,7 @@
|
||||
let asPlainText = $derived(isOfflineReplay())
|
||||
</script>
|
||||
|
||||
<div class="{prose ? markdownProse[prose] : '!prose-xs'} {noPadding ? '' : 'pgap'}">
|
||||
<div class="{markdownProse[prose]} {noPadding ? '' : 'pgap'}">
|
||||
{#if asPlainText}
|
||||
<p class="whitespace-pre-wrap">{md}</p>
|
||||
{:else}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import GfmMarkdown from '$lib/components/GfmMarkdown.svelte'
|
||||
import { Check, X } from 'lucide-svelte'
|
||||
import { NOTE_COLORS, NoteColor } from './noteColors'
|
||||
import { NOTE_COLORS, NOTE_TEXT_COLOR_OVERRIDE, NoteColor } from './noteColors'
|
||||
import { stopPropagation, preventDefault } from 'svelte/legacy'
|
||||
|
||||
interface Props {
|
||||
@@ -127,7 +127,7 @@
|
||||
{:else if note}
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<div
|
||||
class="w-full text-2xs break-words overflow-hidden p-2 select-text {noteColorConfig.text} {editMode
|
||||
class="w-full text-2xs break-words overflow-hidden p-2 select-text {noteColorConfig.text} {NOTE_TEXT_COLOR_OVERRIDE} {editMode
|
||||
? 'cursor-pointer'
|
||||
: ''}"
|
||||
ondblclick={editMode ? stopPropagation(preventDefault(handleDoubleClick)) : undefined}
|
||||
|
||||
@@ -105,6 +105,13 @@ export const NOTE_COLORS: Record<NoteColor, NoteColorConfig> = {
|
||||
}
|
||||
}
|
||||
|
||||
// A note renders its text as markdown, and the prose stack sets body, heading and
|
||||
// strong colors directly on those elements — which would beat the note color the
|
||||
// wrapper only passes down by inheritance, and leave the render mismatched against
|
||||
// the textarea shown while editing. Pin every descendant back to the note color.
|
||||
// (Kept as a literal: Tailwind's scanner reads class names verbatim from this file.)
|
||||
export const NOTE_TEXT_COLOR_OVERRIDE = '[&_*]:!text-inherit'
|
||||
|
||||
// Color swatch colors for the picker (solid colors for the palette dots)
|
||||
export const NOTE_COLOR_SWATCHES: Record<NoteColor, string> = {
|
||||
[NoteColor.YELLOW]: 'bg-yellow-400',
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import {
|
||||
NoteColor,
|
||||
NOTE_COLORS,
|
||||
NOTE_TEXT_COLOR_OVERRIDE,
|
||||
DEFAULT_NOTE_COLOR,
|
||||
MIN_NOTE_WIDTH,
|
||||
MIN_NOTE_HEIGHT
|
||||
@@ -294,10 +295,11 @@
|
||||
<div
|
||||
class={twMerge(
|
||||
'w-full text-xs rounded-md break-words overflow-hidden',
|
||||
colorConfig.text
|
||||
colorConfig.text,
|
||||
NOTE_TEXT_COLOR_OVERRIDE
|
||||
)}
|
||||
>
|
||||
<GfmMarkdown md={textForDisplay} noPadding />
|
||||
<GfmMarkdown md={textForDisplay} prose="sm" noPadding />
|
||||
</div>
|
||||
{:else}
|
||||
<div class={twMerge('text-xs italic opacity-60', colorConfig.text)}>
|
||||
|
||||
@@ -22,13 +22,13 @@ const base =
|
||||
|
||||
// One vertical rhythm for sm/doc; heading margins stay per-preset (fixed, not
|
||||
// the plugin's em-based ones) so 'doc' can breathe more between sections.
|
||||
const rhythm = 'prose-sm leading-snug prose-ul:!pl-6'
|
||||
const rhythm = 'prose-sm leading-snug'
|
||||
|
||||
const bodyXs =
|
||||
'text-primary prose-p:text-primary prose-li:text-primary prose-p:text-xs prose-li:text-xs prose-code:text-xs prose-pre:text-xs prose-table:text-xs'
|
||||
|
||||
export const markdownProse = {
|
||||
xs: `${base} prose-sm leading-snug prose-ul:!pl-5 prose-p:text-2xs prose-li:text-2xs prose-code:text-2xs prose-pre:text-2xs prose-headings:font-medium prose-headings:text-secondary prose-headings:mt-2 prose-headings:mb-1 prose-h1:text-2xs prose-h2:text-2xs prose-h3:text-2xs prose-h4:text-2xs prose-h5:text-2xs prose-h6:text-2xs prose-strong:text-secondary`,
|
||||
xs: `${base} prose-sm leading-snug prose-p:text-2xs prose-li:text-2xs prose-code:text-2xs prose-pre:text-2xs prose-headings:font-medium prose-headings:text-secondary prose-headings:mt-2 prose-headings:mb-1 prose-h1:text-2xs prose-h2:text-2xs prose-h3:text-2xs prose-h4:text-2xs prose-h5:text-2xs prose-h6:text-2xs prose-strong:text-secondary`,
|
||||
sm: `${base} ${rhythm} ${bodyXs} prose-headings:mt-3 prose-headings:mb-1 prose-headings:font-medium prose-headings:text-emphasis prose-h1:text-sm prose-h2:text-xs prose-h3:text-xs prose-h4:text-xs prose-h5:text-xs prose-h6:text-xs`,
|
||||
doc: `${base} ${rhythm} ${bodyXs} prose-headings:mt-8 prose-headings:mb-2 prose-headings:font-semibold prose-headings:text-emphasis prose-h1:text-lg prose-h2:text-base prose-h3:text-sm prose-h4:text-xs prose-h5:text-xs prose-h6:text-xs prose-pre:bg-transparent prose-pre:p-0`
|
||||
} as const
|
||||
|
||||
@@ -666,6 +666,7 @@
|
||||
<div class="p-4 rounded-md bg-surface-secondary">
|
||||
<GfmMarkdown
|
||||
md={defaultIfEmptyString(flow?.description, 'No description')}
|
||||
prose="sm"
|
||||
noPadding
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -888,6 +888,7 @@
|
||||
<div class="p-4 rounded-md bg-surface-secondary">
|
||||
<GfmMarkdown
|
||||
md={defaultIfEmptyString(script?.description, 'No description')}
|
||||
prose="sm"
|
||||
noPadding
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user