@iterant/site-runtime 3.9.0 → 3.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -50,7 +50,7 @@ runtime and says so.
50
50
 
51
51
  <!-- generated: available libraries -->
52
52
 
53
- _Generated from package.json by scripts/generate-kit-table.mjs. Runtime 3.9.0._
53
+ _Generated from package.json by scripts/generate-kit-table.mjs. Runtime 3.10.0._
54
54
 
55
55
  **Toolchain** (this package owns the version; do NOT declare these):
56
56
 
@@ -157,7 +157,7 @@ CommonMark, stored as written.
157
157
 
158
158
  const body = readMarkdown(data.body); // raw CommonMark | null
159
159
  <div
160
- class="prose"
160
+ class="markdown-body"
161
161
  data-editable="body"
162
162
  data-path="props.body"
163
163
  data-edit-type="markdown"
@@ -165,6 +165,22 @@ CommonMark, stored as written.
165
165
  />;
166
166
  ```
167
167
 
168
+ - **`markdown-body` is the wrapper class, and the stylesheet is opt-in
169
+ (3.10.0).** The compiler emits bare `<h2>`, `<ul>` and `<blockquote>`, and
170
+ Preflight flattens all three to paragraph size, so an unstyled body renders as
171
+ a run of identical lines. Add the import to `src/styles/globals.css` once,
172
+ below `@import "tailwindcss"`:
173
+
174
+ ```css
175
+ @import "@iterant/site-runtime/styles/markdown.css";
176
+ ```
177
+
178
+ It styles measure, rhythm and hierarchy from the repo's own `--it-*` and
179
+ `--font-*` tokens, and reads two knobs of its own:
180
+ `--it-markdown-measure` (the reading width, `68ch`, `none` to fill) and
181
+ `--it-markdown-flow` (the space between blocks, `1.25em`). Every rule sits in
182
+ the `base` layer, so a utility class on the wrapper still wins.
183
+
168
184
  - **Headings start at `##`.** The body renders below the page's own h1; the
169
185
  compiler does not demote levels for you.
170
186
  - Hrefs inside the value follow the same rules as link wrappers: root-relative
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iterant/site-runtime",
3
- "version": "3.9.0",
3
+ "version": "3.10.0",
4
4
  "type": "module",
5
5
  "description": "The platform layer every Iterant brand site runs on: content grammar, collection schemas, SEO head and JSON-LD, layout core, Astro config preset, dev integrations and the verify gates.",
6
6
  "scripts": {
@@ -27,6 +27,7 @@
27
27
  "docs",
28
28
  "scripts",
29
29
  "src",
30
+ "styles",
30
31
  "!**/*.test.ts",
31
32
  "!scripts/check-fixture.mjs",
32
33
  "!scripts/check-packed.mjs",
@@ -59,6 +60,7 @@
59
60
  "./routes": "./src/routes/index.ts",
60
61
  "./config": "./src/config/preset.ts",
61
62
  "./integrations/*": "./src/integrations/*.mjs",
63
+ "./styles/markdown.css": "./styles/markdown.css",
62
64
  "./package.json": "./package.json"
63
65
  },
64
66
  "iterant": {
@@ -0,0 +1,221 @@
1
+ /*
2
+ * The article-body stylesheet: `class="markdown-body"` around compiled
3
+ * `renderMarkdown` output.
4
+ *
5
+ * It exists because `renderMarkdown` is bare micromark: it emits `<h2>`, `<ul>`
6
+ * and `<blockquote>` with no classes, and Tailwind's Preflight flattens every
7
+ * one of them to the paragraph's size, weight and margin. A body compiled
8
+ * without this file renders as a run of identical lines, which is what a blog
9
+ * post looked like through 3.9.0.
10
+ *
11
+ * OPT-IN, and imported once. The package ships no stylesheet of its own and
12
+ * LayoutCore imports none, so nothing here reaches a brand until that brand's
13
+ * `globals.css` names it:
14
+ *
15
+ * @import "@iterant/site-runtime/styles/markdown.css";
16
+ *
17
+ * Put the line AFTER `@import "tailwindcss"`. Everything below lives in the
18
+ * `base` layer, so it wins over Preflight by order and loses to every utility
19
+ * class: `class="markdown-body text-lg"` still reads as the site author wrote
20
+ * it, and a brand rule outside a layer overrides anything here.
21
+ *
22
+ * Colors, fonts, radius and border come from the `--it-*` and `--font-*` tokens
23
+ * a brand's `globals.css` defines, each with a fallback so the file also works
24
+ * in a repo that defines none. Two knobs are its own, settable on any ancestor:
25
+ *
26
+ * --it-markdown-measure the reading width (default 68ch; `none` to fill)
27
+ * --it-markdown-flow the space between blocks (default 1.25em)
28
+ */
29
+
30
+ @layer base {
31
+ .markdown-body {
32
+ color: var(--it-text-primary, currentColor);
33
+ font-family: var(--font-body, inherit);
34
+ font-size: var(--font-size-base, 1rem);
35
+ font-weight: var(--font-body-weight, 400);
36
+ line-height: var(--font-body-line-height, 1.7);
37
+ max-width: var(--it-markdown-measure, 68ch);
38
+ }
39
+
40
+ /* The wrapper's own spacing belongs to the page around it. */
41
+ .markdown-body > :first-child {
42
+ margin-top: 0;
43
+ }
44
+
45
+ .markdown-body > :last-child {
46
+ margin-bottom: 0;
47
+ }
48
+
49
+ .markdown-body p {
50
+ margin: 0 0 var(--it-markdown-flow, 1.25em);
51
+ }
52
+
53
+ /* A body opens at `##` under the page's own h1, so h2 carries the section
54
+ weight here. h1 is styled anyway: a pasted body that starts at `#` should
55
+ read as a heading rather than as an outsized paragraph. */
56
+ .markdown-body h1,
57
+ .markdown-body h2,
58
+ .markdown-body h3,
59
+ .markdown-body h4 {
60
+ color: var(--it-text-primary, currentColor);
61
+ font-family: var(--font-heading, inherit);
62
+ font-weight: var(--font-heading-weight, 700);
63
+ letter-spacing: var(--font-heading-letter-spacing, normal);
64
+ line-height: var(--font-heading-line-height, 1.2);
65
+ margin: 2em 0 0.6em;
66
+ text-wrap: balance;
67
+ }
68
+
69
+ .markdown-body h1 {
70
+ font-size: var(--font-size-3xl, 1.875rem);
71
+ }
72
+
73
+ .markdown-body h2 {
74
+ font-size: var(--font-size-2xl, 1.5rem);
75
+ }
76
+
77
+ .markdown-body h3 {
78
+ font-size: var(--font-size-xl, 1.25rem);
79
+ }
80
+
81
+ .markdown-body h4 {
82
+ font-size: var(--font-size-lg, 1.125rem);
83
+ }
84
+
85
+ .markdown-body ul,
86
+ .markdown-body ol {
87
+ margin: 0 0 var(--it-markdown-flow, 1.25em);
88
+ padding-left: 1.5em;
89
+ }
90
+
91
+ .markdown-body ul {
92
+ list-style: disc;
93
+ }
94
+
95
+ .markdown-body ol {
96
+ list-style: decimal;
97
+ }
98
+
99
+ .markdown-body ul ul {
100
+ list-style: circle;
101
+ }
102
+
103
+ .markdown-body li {
104
+ margin-block: 0.35em;
105
+ }
106
+
107
+ .markdown-body li::marker {
108
+ color: var(--it-text-secondary, currentColor);
109
+ }
110
+
111
+ /* A nested list is part of its parent item, not a new block. */
112
+ .markdown-body li > ul,
113
+ .markdown-body li > ol {
114
+ margin-block: 0.35em;
115
+ }
116
+
117
+ .markdown-body li > p {
118
+ margin-bottom: 0.35em;
119
+ }
120
+
121
+ .markdown-body blockquote {
122
+ border-left: var(--border-width, 1px) var(--border-style, solid)
123
+ var(--it-border-primary, currentColor);
124
+ color: var(--it-text-secondary, currentColor);
125
+ margin: var(--it-markdown-flow, 1.25em) 0;
126
+ padding-left: 1.25em;
127
+ }
128
+
129
+ .markdown-body blockquote > :last-child {
130
+ margin-bottom: 0;
131
+ }
132
+
133
+ .markdown-body code {
134
+ font-family: var(--font-mono, ui-monospace, monospace);
135
+ font-size: 0.9em;
136
+ }
137
+
138
+ /* A code span is a chip; a fence is a surface. */
139
+ .markdown-body :not(pre) > code {
140
+ background-color: var(--it-background-secondary, transparent);
141
+ border-radius: calc(var(--radius, 0.5rem) / 2);
142
+ padding: 0.15em 0.4em;
143
+ }
144
+
145
+ .markdown-body pre {
146
+ background-color: var(--it-background-secondary, transparent);
147
+ border-radius: var(--radius, 0.5rem);
148
+ line-height: 1.55;
149
+ margin: var(--it-markdown-flow, 1.25em) 0;
150
+ overflow-x: auto;
151
+ padding: 1em 1.15em;
152
+ }
153
+
154
+ .markdown-body pre code {
155
+ background-color: transparent;
156
+ font-size: inherit;
157
+ padding: 0;
158
+ }
159
+
160
+ /* The link keeps the body's color: an accent token is a background color in
161
+ some brand palettes, and a link mid-sentence has to stay readable in all of
162
+ them. The underline is what marks it. */
163
+ .markdown-body a {
164
+ color: inherit;
165
+ text-decoration: underline;
166
+ text-decoration-thickness: from-font;
167
+ text-underline-offset: 0.2em;
168
+ }
169
+
170
+ .markdown-body a:hover {
171
+ text-decoration-thickness: 2px;
172
+ }
173
+
174
+ .markdown-body strong {
175
+ color: var(--it-text-primary, currentColor);
176
+ font-weight: var(--font-body-bold-weight, 600);
177
+ }
178
+
179
+ .markdown-body hr {
180
+ border: 0;
181
+ border-top: var(--border-width, 1px) var(--border-style, solid)
182
+ var(--it-border-primary, currentColor);
183
+ margin: 2.5em 0;
184
+ }
185
+
186
+ .markdown-body img {
187
+ display: block;
188
+ height: auto;
189
+ margin: var(--it-markdown-flow, 1.25em) 0;
190
+ max-width: 100%;
191
+ }
192
+
193
+ /* GFM tables. The table itself scrolls, so a wide one never widens the page. */
194
+ .markdown-body table {
195
+ border-collapse: collapse;
196
+ display: block;
197
+ font-size: 0.95em;
198
+ margin: var(--it-markdown-flow, 1.25em) 0;
199
+ max-width: 100%;
200
+ overflow-x: auto;
201
+ width: max-content;
202
+ }
203
+
204
+ .markdown-body th,
205
+ .markdown-body td {
206
+ border: var(--border-width, 1px) var(--border-style, solid)
207
+ var(--it-border-primary, currentColor);
208
+ padding: 0.5em 0.75em;
209
+ }
210
+
211
+ /* gfm writes `align` on a column the author aligned; only the rest defaults. */
212
+ .markdown-body th:not([align]),
213
+ .markdown-body td:not([align]) {
214
+ text-align: left;
215
+ }
216
+
217
+ .markdown-body th {
218
+ background-color: var(--it-background-secondary, transparent);
219
+ font-weight: var(--font-body-bold-weight, 600);
220
+ }
221
+ }