# Prose

> Style a block of HTML you did not write — Markdown output, a CMS field, an RSS description.

A Markdown renderer hands back bare tags: `<h2>`, `<p>`, `<ul>`, `<blockquote>` — with no classes to hook onto. `prose()` wraps that HTML and styles it.

It is the one deliberate exception in this library. Everywhere else, styling is scoped to `su-` classes precisely so it never touches markup you did not opt into; here there are no classes to target, so the rules match bare tags — but only inside the wrapper.

## Basic prose

```javascript
prose(
  '<h2>Getting started</h2>' +
  '<p>Write a function that returns HTML. Run <code>sitelo build</code>. Publish <code>dist/</code>.</p>' +
  '<ul><li>File-based routing</li><li>Build-time data</li><li>No client runtime</li></ul>'
)
```

## Everything it styles

```javascript
prose(
  '<h3>A heading</h3>' +
  '<p>Body copy with <a href="/docs">a link</a>, <strong>bold</strong>, and <code>inline code</code>.</p>' +
  '<blockquote><p>A pull quote, set apart from the text around it.</p></blockquote>' +
  '<ol><li>First</li><li>Second<ul><li>Nested</li></ul></li></ol>' +
  '<pre><code>export default () => "&lt;h1&gt;Hi&lt;/h1&gt;"</code></pre>' +
  '<table><thead><tr><th>Option</th><th>Default</th></tr></thead>' +
  '<tbody><tr><td>cleanUrls</td><td>true</td></tr><tr><td>outDir</td><td>dist</td></tr></tbody></table>' +
  '<hr>' +
  '<p>Press <kbd>⌘</kbd> <kbd>K</kbd> to search.</p>'
)
```

## Sizes

```javascript
stack({ gap: 'lg' },
  prose({ size: 'sm' }, '<p><strong>Small</strong> — for a card summary or a sidebar.</p>'),
  prose('<p><strong>Medium</strong> — the default, for article body copy.</p>'),
  prose({ size: 'lg' }, '<p><strong>Large</strong> — for a short, prominent introduction.</p>'),
)
```

## With a Markdown blog

The shape the blog example wants: render the Markdown at build time, wrap the result, and ship it.

`src/blog/[slug].ht.js`

```javascript
import { marked } from 'marked'
import { article, body, h1, html, head, title } from 'javascript-to-html'
import { container, prose, styles, text } from 'sitelo/ui'

export async function data({ params }) {
  return { post: await loadPost(params.slug) }
}

export default ({ data }) => html({ lang: 'en' },
  head(title(data.post.title), styles()),
  body(
    container({ size: 'sm' },
      h1(data.post.title),
      text({ variant: 'caption' }, data.post.date),
      // marked returns a string of HTML with no classes on it
      prose(marked.parse(data.post.markdown)),
    ),
  ),
)
```

## Components inside prose

Every prose rule excludes elements carrying an `su-` class, so a component dropped into a block of prose keeps its own styling instead of picking up article margins.

```javascript
prose(
  '<p>Some rendered Markdown, and then a component:</p>',
  alert({ color: 'warning', title: 'Still a normal alert' },
    'It is not restyled by the prose block around it.'),
  '<p>And back to prose.</p>',
)
```

## A word about trust

`prose()` renders its children as HTML — that is the whole point, and it is how `javascript-to-html` works throughout. If the HTML comes from somewhere you do not control, sanitize it before it gets here. A Markdown renderer with raw HTML disabled is usually enough.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Base font size; everything else scales in em from it. |
| `as` | `string` | `'div'` | Element to render, e.g. article. |
