@ox-content/vite-plugin 3.0.0-alpha.13 → 3.0.0-alpha.15

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.
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-tables.cjs","sourceRoot":"","sources":["../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"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","sourcesContent":["export interface MarkdownTableEnhancementOptions {\n /**\n * Tables to enhance. Defaults to Markdown content tables styled by\n * `@ox-content/vite-plugin/styles/core.css`.\n */\n selector?: string;\n /**\n * Accessible name applied only when an overflowing table has no existing\n * `aria-label` or `aria-labelledby`.\n */\n label?: string;\n}\n\nconst TABINDEX_FLAG = \"oxTableScrollTabindex\";\nconst LABEL_FLAG = \"oxTableScrollLabel\";\nconst SCROLLABLE_ATTR = \"data-ox-table-scrollable\";\n\nexport function markdownTableScrollLabel(locale?: string): string {\n const language = locale?.split(\"-\")[0]?.toLowerCase();\n if (language === \"ja\") {\n return \"横スクロールできる表\";\n }\n return \"Scrollable table\";\n}\n\n/**\n * Makes overflowing Markdown tables keyboard-scrollable without wrapping or\n * replacing the native `<table>` element.\n *\n * Run this after rendering Markdown and again after layout-changing updates.\n * Narrow tables stay out of the tab order when overflow can be measured.\n */\nexport function enhanceMarkdownTables(\n root?: ParentNode,\n options: MarkdownTableEnhancementOptions = {},\n): number {\n const target = root ?? globalThis.document;\n if (!target?.querySelectorAll) {\n return 0;\n }\n\n const selector = options.selector ?? \".content table\";\n const locale = ownerDocument(target)?.documentElement.lang;\n const label = options.label ?? markdownTableScrollLabel(locale);\n let scrollableCount = 0;\n\n for (const table of target.querySelectorAll(selector)) {\n if (typeof HTMLElement === \"undefined\" || !(table instanceof HTMLElement)) {\n continue;\n }\n if (table.tagName !== \"TABLE\") {\n continue;\n }\n\n const scrollable = table.scrollWidth > table.clientWidth + 1;\n table.toggleAttribute(SCROLLABLE_ATTR, scrollable);\n if (scrollable) {\n scrollableCount++;\n if (!table.hasAttribute(\"tabindex\")) {\n table.tabIndex = 0;\n table.dataset[TABINDEX_FLAG] = \"true\";\n }\n if (!table.hasAttribute(\"aria-label\") && !table.hasAttribute(\"aria-labelledby\")) {\n table.setAttribute(\"aria-label\", label);\n table.dataset[LABEL_FLAG] = \"true\";\n }\n } else {\n if (table.dataset[TABINDEX_FLAG] === \"true\") {\n table.removeAttribute(\"tabindex\");\n delete table.dataset[TABINDEX_FLAG];\n }\n if (table.dataset[LABEL_FLAG] === \"true\") {\n table.removeAttribute(\"aria-label\");\n delete table.dataset[LABEL_FLAG];\n }\n }\n }\n\n return scrollableCount;\n}\n\nfunction ownerDocument(root: ParentNode): Document | undefined {\n if (typeof Document !== \"undefined\" && root instanceof Document) {\n return root;\n }\n return root.ownerDocument ?? globalThis.document;\n}\n"]}
1
+ {"version":3,"file":"markdown-tables.cjs","sourceRoot":"","sources":["../../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"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","sourcesContent":["export interface MarkdownTableEnhancementOptions {\n /**\n * Tables to enhance. Defaults to Markdown content tables styled by\n * `@ox-content/vite-plugin/styles/core.css`.\n */\n selector?: string;\n /**\n * Accessible name applied only when an overflowing table has no existing\n * `aria-label` or `aria-labelledby`.\n */\n label?: string;\n}\n\nconst TABINDEX_FLAG = \"oxTableScrollTabindex\";\nconst LABEL_FLAG = \"oxTableScrollLabel\";\nconst SCROLLABLE_ATTR = \"data-ox-table-scrollable\";\n\nexport function markdownTableScrollLabel(locale?: string): string {\n const language = locale?.split(\"-\")[0]?.toLowerCase();\n if (language === \"ja\") {\n return \"横スクロールできる表\";\n }\n return \"Scrollable table\";\n}\n\n/**\n * Makes overflowing Markdown tables keyboard-scrollable without wrapping or\n * replacing the native `<table>` element.\n *\n * Run this after rendering Markdown and again after layout-changing updates.\n * Narrow tables stay out of the tab order when overflow can be measured.\n */\nexport function enhanceMarkdownTables(\n root?: ParentNode,\n options: MarkdownTableEnhancementOptions = {},\n): number {\n const target = root ?? globalThis.document;\n if (!target?.querySelectorAll) {\n return 0;\n }\n\n const selector = options.selector ?? \".content table\";\n const locale = ownerDocument(target)?.documentElement.lang;\n const label = options.label ?? markdownTableScrollLabel(locale);\n let scrollableCount = 0;\n\n for (const table of target.querySelectorAll(selector)) {\n if (typeof HTMLElement === \"undefined\" || !(table instanceof HTMLElement)) {\n continue;\n }\n if (table.tagName !== \"TABLE\") {\n continue;\n }\n\n const scrollable = table.scrollWidth > table.clientWidth + 1;\n table.toggleAttribute(SCROLLABLE_ATTR, scrollable);\n if (scrollable) {\n scrollableCount++;\n if (!table.hasAttribute(\"tabindex\")) {\n table.tabIndex = 0;\n table.dataset[TABINDEX_FLAG] = \"true\";\n }\n if (!table.hasAttribute(\"aria-label\") && !table.hasAttribute(\"aria-labelledby\")) {\n table.setAttribute(\"aria-label\", label);\n table.dataset[LABEL_FLAG] = \"true\";\n }\n } else {\n if (table.dataset[TABINDEX_FLAG] === \"true\") {\n table.removeAttribute(\"tabindex\");\n delete table.dataset[TABINDEX_FLAG];\n }\n if (table.dataset[LABEL_FLAG] === \"true\") {\n table.removeAttribute(\"aria-label\");\n delete table.dataset[LABEL_FLAG];\n }\n }\n }\n\n return scrollableCount;\n}\n\nfunction ownerDocument(root: ParentNode): Document | undefined {\n if (typeof Document !== \"undefined\" && root instanceof Document) {\n return root;\n }\n return root.ownerDocument ?? globalThis.document;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"markdown-tables.mjs","sourceRoot":"","sources":["../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"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","sourcesContent":["export interface MarkdownTableEnhancementOptions {\n /**\n * Tables to enhance. Defaults to Markdown content tables styled by\n * `@ox-content/vite-plugin/styles/core.css`.\n */\n selector?: string;\n /**\n * Accessible name applied only when an overflowing table has no existing\n * `aria-label` or `aria-labelledby`.\n */\n label?: string;\n}\n\nconst TABINDEX_FLAG = \"oxTableScrollTabindex\";\nconst LABEL_FLAG = \"oxTableScrollLabel\";\nconst SCROLLABLE_ATTR = \"data-ox-table-scrollable\";\n\nexport function markdownTableScrollLabel(locale?: string): string {\n const language = locale?.split(\"-\")[0]?.toLowerCase();\n if (language === \"ja\") {\n return \"横スクロールできる表\";\n }\n return \"Scrollable table\";\n}\n\n/**\n * Makes overflowing Markdown tables keyboard-scrollable without wrapping or\n * replacing the native `<table>` element.\n *\n * Run this after rendering Markdown and again after layout-changing updates.\n * Narrow tables stay out of the tab order when overflow can be measured.\n */\nexport function enhanceMarkdownTables(\n root?: ParentNode,\n options: MarkdownTableEnhancementOptions = {},\n): number {\n const target = root ?? globalThis.document;\n if (!target?.querySelectorAll) {\n return 0;\n }\n\n const selector = options.selector ?? \".content table\";\n const locale = ownerDocument(target)?.documentElement.lang;\n const label = options.label ?? markdownTableScrollLabel(locale);\n let scrollableCount = 0;\n\n for (const table of target.querySelectorAll(selector)) {\n if (typeof HTMLElement === \"undefined\" || !(table instanceof HTMLElement)) {\n continue;\n }\n if (table.tagName !== \"TABLE\") {\n continue;\n }\n\n const scrollable = table.scrollWidth > table.clientWidth + 1;\n table.toggleAttribute(SCROLLABLE_ATTR, scrollable);\n if (scrollable) {\n scrollableCount++;\n if (!table.hasAttribute(\"tabindex\")) {\n table.tabIndex = 0;\n table.dataset[TABINDEX_FLAG] = \"true\";\n }\n if (!table.hasAttribute(\"aria-label\") && !table.hasAttribute(\"aria-labelledby\")) {\n table.setAttribute(\"aria-label\", label);\n table.dataset[LABEL_FLAG] = \"true\";\n }\n } else {\n if (table.dataset[TABINDEX_FLAG] === \"true\") {\n table.removeAttribute(\"tabindex\");\n delete table.dataset[TABINDEX_FLAG];\n }\n if (table.dataset[LABEL_FLAG] === \"true\") {\n table.removeAttribute(\"aria-label\");\n delete table.dataset[LABEL_FLAG];\n }\n }\n }\n\n return scrollableCount;\n}\n\nfunction ownerDocument(root: ParentNode): Document | undefined {\n if (typeof Document !== \"undefined\" && root instanceof Document) {\n return root;\n }\n return root.ownerDocument ?? globalThis.document;\n}\n"]}
1
+ {"version":3,"file":"markdown-tables.mjs","sourceRoot":"","sources":["../../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/markdown-tables.ts"],"names":[],"mappings":"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","sourcesContent":["export interface MarkdownTableEnhancementOptions {\n /**\n * Tables to enhance. Defaults to Markdown content tables styled by\n * `@ox-content/vite-plugin/styles/core.css`.\n */\n selector?: string;\n /**\n * Accessible name applied only when an overflowing table has no existing\n * `aria-label` or `aria-labelledby`.\n */\n label?: string;\n}\n\nconst TABINDEX_FLAG = \"oxTableScrollTabindex\";\nconst LABEL_FLAG = \"oxTableScrollLabel\";\nconst SCROLLABLE_ATTR = \"data-ox-table-scrollable\";\n\nexport function markdownTableScrollLabel(locale?: string): string {\n const language = locale?.split(\"-\")[0]?.toLowerCase();\n if (language === \"ja\") {\n return \"横スクロールできる表\";\n }\n return \"Scrollable table\";\n}\n\n/**\n * Makes overflowing Markdown tables keyboard-scrollable without wrapping or\n * replacing the native `<table>` element.\n *\n * Run this after rendering Markdown and again after layout-changing updates.\n * Narrow tables stay out of the tab order when overflow can be measured.\n */\nexport function enhanceMarkdownTables(\n root?: ParentNode,\n options: MarkdownTableEnhancementOptions = {},\n): number {\n const target = root ?? globalThis.document;\n if (!target?.querySelectorAll) {\n return 0;\n }\n\n const selector = options.selector ?? \".content table\";\n const locale = ownerDocument(target)?.documentElement.lang;\n const label = options.label ?? markdownTableScrollLabel(locale);\n let scrollableCount = 0;\n\n for (const table of target.querySelectorAll(selector)) {\n if (typeof HTMLElement === \"undefined\" || !(table instanceof HTMLElement)) {\n continue;\n }\n if (table.tagName !== \"TABLE\") {\n continue;\n }\n\n const scrollable = table.scrollWidth > table.clientWidth + 1;\n table.toggleAttribute(SCROLLABLE_ATTR, scrollable);\n if (scrollable) {\n scrollableCount++;\n if (!table.hasAttribute(\"tabindex\")) {\n table.tabIndex = 0;\n table.dataset[TABINDEX_FLAG] = \"true\";\n }\n if (!table.hasAttribute(\"aria-label\") && !table.hasAttribute(\"aria-labelledby\")) {\n table.setAttribute(\"aria-label\", label);\n table.dataset[LABEL_FLAG] = \"true\";\n }\n } else {\n if (table.dataset[TABINDEX_FLAG] === \"true\") {\n table.removeAttribute(\"tabindex\");\n delete table.dataset[TABINDEX_FLAG];\n }\n if (table.dataset[LABEL_FLAG] === \"true\") {\n table.removeAttribute(\"aria-label\");\n delete table.dataset[LABEL_FLAG];\n }\n }\n }\n\n return scrollableCount;\n}\n\nfunction ownerDocument(root: ParentNode): Document | undefined {\n if (typeof Document !== \"undefined\" && root instanceof Document) {\n return root;\n }\n return root.ownerDocument ?? globalThis.document;\n}\n"]}
@@ -59,8 +59,8 @@
59
59
  --octc-focus-offset: 2px;
60
60
  --octc-motion-base: 150ms;
61
61
  --octc-motion-ease: ease;
62
- --octc-code-pad-block: 1rem;
63
- --octc-code-pad-inline: 1.25rem;
62
+ --octc-code-pad-block: 1.05rem;
63
+ --octc-code-pad-inline: 1rem;
64
64
  --octc-code-title-pad-block: 0.75rem;
65
65
  --octc-code-title-gap: 0.875rem;
66
66
  --octc-table-cell-pad-block: 0.75rem;
@@ -1013,11 +1013,11 @@ a:hover {
1013
1013
  margin-bottom: 0;
1014
1014
  }
1015
1015
  .content .ox-steps {
1016
- margin: 1.75rem 0 2rem;
1017
- padding: 1.1rem 1rem 1.1rem 0;
1016
+ margin: 1.25rem 0 1.5rem;
1017
+ padding: 0.85rem 0.9rem;
1018
1018
  border: 1px solid var(--octc-color-border);
1019
- border-radius: 8px;
1020
- background: color-mix(in srgb, var(--octc-color-bg-alt) 42%, transparent);
1019
+ border-radius: 6px;
1020
+ background: color-mix(in srgb, var(--octc-color-bg-alt) 34%, transparent);
1021
1021
  }
1022
1022
  .content .ox-steps__list {
1023
1023
  list-style: none;
@@ -1027,20 +1027,20 @@ a:hover {
1027
1027
  }
1028
1028
  .content .ox-steps__item {
1029
1029
  position: relative;
1030
- margin: 0 0 1rem;
1031
- padding-left: 2.5rem;
1030
+ margin: 0 0 0.85rem;
1031
+ padding-left: 2.2rem;
1032
1032
  counter-increment: ox-steps;
1033
1033
  }
1034
1034
  .content .ox-steps__item::before {
1035
1035
  content: counter(ox-steps);
1036
1036
  position: absolute;
1037
1037
  left: 0;
1038
- top: 0.15rem;
1038
+ top: 0.12rem;
1039
1039
  display: flex;
1040
1040
  align-items: center;
1041
1041
  justify-content: center;
1042
- width: 1.6rem;
1043
- height: 1.6rem;
1042
+ width: 1.45rem;
1043
+ height: 1.45rem;
1044
1044
  border-radius: 999px;
1045
1045
  background: var(--octc-color-primary);
1046
1046
  color: var(--octc-color-bg);
@@ -1196,13 +1196,13 @@ a:hover {
1196
1196
  position: relative;
1197
1197
  }
1198
1198
  .content pre.ox-code-block.line-numbers-mode .line {
1199
- padding-left: 4rem;
1199
+ padding-left: 3rem;
1200
1200
  }
1201
1201
  .content pre.ox-code-block.line-numbers-mode .line::before {
1202
1202
  content: attr(data-line-number);
1203
1203
  position: absolute;
1204
1204
  left: var(--octc-code-pad-inline);
1205
- width: 2rem;
1205
+ width: 1.65rem;
1206
1206
  text-align: right;
1207
1207
  color: var(--octc-color-code-line-number);
1208
1208
  user-select: none;
@@ -1264,7 +1264,7 @@ a:hover {
1264
1264
  margin: 1.25rem 0;
1265
1265
  font-size: 0.875rem;
1266
1266
  }
1267
- .content table[data-ox-table-scrollable="true"]:focus-visible {
1267
+ .content table[data-ox-table-scrollable]:focus-visible {
1268
1268
  outline: var(--octc-focus-ring);
1269
1269
  outline-offset: var(--octc-focus-offset);
1270
1270
  }
@@ -2104,10 +2104,10 @@ a:hover {
2104
2104
  font-size: 0.82rem !important;
2105
2105
  }
2106
2106
  .content pre.ox-code-block.line-numbers-mode .line {
2107
- padding-left: 3.7rem;
2107
+ padding-left: 2.85rem;
2108
2108
  }
2109
2109
  .content pre.ox-code-block.line-numbers-mode .line::before {
2110
- width: 1.75rem;
2110
+ width: 1.65rem;
2111
2111
  }
2112
2112
  .content table {
2113
2113
  margin: 1rem 0;
@@ -8,7 +8,9 @@
8
8
  -webkit-overflow-scrolling: touch;
9
9
  }
10
10
 
11
- .content table[data-ox-table-scrollable="true"]:focus-visible {
11
+ /* `enhanceMarkdownTables()` marks overflow with `toggleAttribute()`, so the
12
+ attribute is present with an empty value. Match on presence, never a value. */
13
+ .content table[data-ox-table-scrollable]:focus-visible {
12
14
  outline: var(--octc-focus-ring, 2px solid Highlight);
13
15
  outline-offset: var(--octc-focus-offset, 2px);
14
16
  }
@@ -17,6 +17,13 @@
17
17
  color: var(--octc-color-text);
18
18
  }
19
19
 
20
+ /* A fetched tweet renders `<figure><header>…` rather than wrapping its body in
21
+ one anchor, so the rule above never matches it. Pad the card itself to keep
22
+ it level with the Bluesky card. */
23
+ .ox-tweet--fetched {
24
+ padding: 1rem 0;
25
+ }
26
+
20
27
  .ox-tweet > a:hover,
21
28
  .ox-bluesky > a:hover {
22
29
  text-decoration: none;
@@ -292,13 +299,13 @@
292
299
  .ox-tweet__quote .ox-tweet__media {
293
300
  margin-bottom: 0;
294
301
  }
295
-
296
302
  /* WebContainer lazy placeholder */
297
303
  .ox-webcontainer {
298
304
  margin: 1.5rem 0;
299
305
  border: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
300
306
  border-radius: 8px;
301
307
  overflow: hidden;
308
+ background: var(--octc-color-bg);
302
309
  }
303
310
 
304
311
  .ox-webcontainer__header {
@@ -306,40 +313,79 @@
306
313
  align-items: center;
307
314
  justify-content: space-between;
308
315
  gap: 0.75rem;
309
- padding: 0.625rem 1rem;
316
+ padding: 0.65rem 0.85rem;
310
317
  border-bottom: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
311
318
  background: var(--octc-color-bg-alt);
312
319
  }
313
320
 
314
- .ox-webcontainer__header strong {
321
+ .ox-webcontainer__title {
322
+ display: inline-flex;
323
+ align-items: center;
324
+ min-width: 0;
325
+ gap: 0.55rem;
326
+ }
327
+
328
+ .ox-webcontainer__title strong {
315
329
  font-size: 0.875rem;
316
330
  color: var(--octc-color-text);
317
331
  }
318
332
 
319
- .ox-webcontainer__header span {
333
+ .ox-webcontainer__title code {
334
+ color: var(--octc-color-text-muted);
335
+ overflow: hidden;
336
+ text-overflow: ellipsis;
337
+ white-space: nowrap;
338
+ }
339
+
340
+ .ox-webcontainer__status,
341
+ .ox-webcontainer__meta {
320
342
  font-size: 0.75rem;
321
343
  color: var(--octc-color-text-muted);
344
+ }
345
+
346
+ .ox-webcontainer__status {
347
+ padding: 0.16rem 0.5rem;
348
+ border: 1px solid color-mix(in srgb, var(--octc-color-primary) 26%, transparent);
349
+ border-radius: 999px;
350
+ background: color-mix(in srgb, var(--octc-color-primary) 8%, transparent);
351
+ color: var(--octc-color-primary);
322
352
  white-space: nowrap;
323
353
  }
324
354
 
355
+ .ox-webcontainer__preview {
356
+ background: var(--octc-color-code-bg);
357
+ }
358
+
325
359
  .ox-webcontainer pre {
326
360
  margin: 0;
327
361
  border: 0;
328
362
  border-radius: 0;
329
363
  }
364
+
365
+ .ox-webcontainer__meta {
366
+ display: flex;
367
+ flex-wrap: wrap;
368
+ gap: 0.45rem 0.85rem;
369
+ padding: 0.6rem 0.85rem;
370
+ border-top: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
371
+ background: color-mix(in srgb, var(--octc-color-bg-alt) 54%, transparent);
372
+ }
373
+
374
+ .ox-webcontainer__meta code {
375
+ color: var(--octc-color-text);
376
+ }
330
377
  /* Provider cards for static article, place, community, and social embeds */
331
378
  .ox-provider-card {
332
379
  display: block;
333
- margin: 1.5rem 0;
380
+ margin: 1rem 0;
334
381
  border: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
335
- border-radius: 8px;
382
+ border-radius: 6px;
336
383
  overflow: hidden;
337
384
  background: var(--octc-color-bg);
338
385
  }
339
386
 
340
387
  .ox-provider-card__main {
341
- display: block;
342
- padding: 1rem;
388
+ display: grid;
343
389
  color: var(--octc-color-text);
344
390
  text-decoration: none;
345
391
  }
@@ -358,7 +404,10 @@
358
404
  }
359
405
 
360
406
  .ox-provider-card__header {
361
- margin-bottom: 0.625rem;
407
+ min-height: 2.1rem;
408
+ padding: 0.45rem 0.8rem;
409
+ border-bottom: 1px solid color-mix(in srgb, var(--octc-color-border) 68%, transparent);
410
+ background: color-mix(in srgb, var(--octc-color-bg-alt) 60%, transparent);
362
411
  font-size: 0.75rem;
363
412
  }
364
413
 
@@ -378,6 +427,7 @@
378
427
  align-items: flex-start;
379
428
  gap: 0.75rem;
380
429
  min-width: 0;
430
+ padding: 0.8rem;
381
431
  }
382
432
 
383
433
  .ox-provider-card__avatar {
@@ -393,7 +443,7 @@
393
443
  min-width: 0;
394
444
  }
395
445
 
396
- .ox-provider-card__title {
446
+ .ox-provider-card .ox-provider-card__title {
397
447
  margin: 0;
398
448
  font-size: 1rem;
399
449
  line-height: 1.35;
@@ -404,8 +454,8 @@
404
454
  text-decoration: underline;
405
455
  }
406
456
 
407
- .ox-provider-card__excerpt {
408
- margin: 0.625rem 0 0;
457
+ .ox-provider-card .ox-provider-card__excerpt {
458
+ margin: 0.35rem 0 0;
409
459
  font-size: 0.875rem;
410
460
  line-height: 1.55;
411
461
  color: var(--octc-color-text-muted);
@@ -417,15 +467,18 @@
417
467
  width: 100%;
418
468
  height: auto;
419
469
  max-height: 420px;
420
- margin-top: 0.875rem;
421
470
  border: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
422
- border-radius: 8px;
471
+ border-width: 1px 0 0;
472
+ border-radius: 0;
423
473
  object-fit: cover;
424
474
  background: var(--octc-color-bg-alt);
425
475
  }
426
476
 
427
477
  .ox-provider-card__meta {
428
- margin-top: 0.875rem;
478
+ min-height: 2.15rem;
479
+ padding: 0.45rem 0.8rem;
480
+ border-top: 1px solid color-mix(in srgb, var(--octc-color-border) 68%, transparent);
481
+ background: color-mix(in srgb, var(--octc-color-bg-alt) 48%, transparent);
429
482
  font-size: 0.75rem;
430
483
  }
431
484
 
@@ -1,18 +1,18 @@
1
1
  /* ox-content Tabs Plugin - Pure CSS, No JS */
2
2
 
3
3
  .ox-tabs {
4
- margin: 1.5rem 0;
4
+ margin: 1.25rem 0;
5
5
  border: 1px solid var(--octc-color-border);
6
- border-radius: 4px;
6
+ border-radius: 6px;
7
7
  overflow: hidden;
8
8
  background: var(--octc-color-bg);
9
9
  }
10
10
 
11
11
  .ox-tabs-header {
12
12
  display: flex;
13
- align-items: end;
14
- gap: 0.125rem;
15
- padding: 0.35rem 0.35rem 0;
13
+ align-items: center;
14
+ gap: 0.2rem;
15
+ padding: 0.35rem;
16
16
  background: var(--octc-color-bg-alt);
17
17
  border-bottom: 1px solid var(--octc-color-border);
18
18
  overflow-x: auto;
@@ -42,17 +42,17 @@
42
42
  display: inline-flex;
43
43
  align-items: center;
44
44
  justify-content: center;
45
- flex: 1 0 max-content;
46
- min-width: 3.5rem;
47
- padding: 0.65rem 0.85rem;
45
+ flex: 0 0 auto;
46
+ min-width: 0;
47
+ min-height: 2.1rem;
48
+ padding: 0.42rem 0.7rem;
48
49
  cursor: pointer;
49
- font-size: 0.875rem;
50
- font-weight: 500;
50
+ font-size: 0.8125rem;
51
+ font-weight: 600;
51
52
  color: var(--octc-color-text-muted);
52
53
  border: 1px solid transparent;
53
54
  border-bottom: 2px solid transparent;
54
- margin-bottom: -1px;
55
- border-radius: 4px 4px 0 0;
55
+ border-radius: 5px;
56
56
  white-space: nowrap;
57
57
  transition:
58
58
  background-color 0.2s ease,
@@ -82,7 +82,7 @@
82
82
  /* Tab content panels */
83
83
  .ox-tab-panel {
84
84
  display: none;
85
- padding: 1rem;
85
+ padding: 0.85rem 0.9rem;
86
86
  background: var(--octc-color-bg);
87
87
  }
88
88
 
@@ -169,7 +169,7 @@
169
169
  }
170
170
 
171
171
  .ox-tabs-fallback summary {
172
- padding: 0.75rem 1rem;
172
+ padding: 0.55rem 0.75rem;
173
173
  cursor: pointer;
174
174
  font-weight: 500;
175
175
  background: var(--octc-color-bg-alt);
@@ -198,7 +198,7 @@
198
198
  }
199
199
 
200
200
  .ox-tabs-fallback .ox-tabs-fallback-content {
201
- padding: 1rem;
201
+ padding: 0.85rem 0.9rem;
202
202
  }
203
203
 
204
204
  /* The disclosure marker still turns, it just turns instantly. */
@@ -1,3 +1,74 @@
1
+ /*
2
+ * Host-prose isolation for full-fidelity Tweet cards.
3
+ *
4
+ * The full card replaces native elements — a `<figure>` root, `<img>`
5
+ * avatars and media, a `<blockquote>` for the quoted post — and an article
6
+ * stylesheet such as `@tailwindcss/typography` styles those by element. The
7
+ * component rules below the isolation block win wherever they set a
8
+ * property; this file covers the properties they never set, which is how a
9
+ * `.prose` article was adding image margins to avatars and quotation
10
+ * typography to the quoted post.
11
+ *
12
+ * Every selector doubles the root class (`.ox-tweet.ox-tweet--full`) so it
13
+ * outranks `.prose <element>` regardless of which stylesheet the host
14
+ * imports last. Generated quotes need a longer chain still: Tailwind writes
15
+ * them at `.prose blockquote p:first-of-type::before`.
16
+ */
17
+
18
+ /*
19
+ * The card root is a `<figure>`, and the component sets its margin at one
20
+ * class of specificity — which `.prose figure` outranks. Restate it here
21
+ * through the same custom property, so a host that overrides the property
22
+ * still gets what it asked for.
23
+ */
24
+ .ox-tweet.ox-tweet--full {
25
+ margin: var(--ox-tweet-container-margin);
26
+ }
27
+
28
+ .ox-tweet.ox-tweet--full :where(img, video, figure, picture, svg) {
29
+ margin: 0;
30
+ }
31
+
32
+ .ox-tweet.ox-tweet--full :where(p, ul, ol, li, dl, dd, dt, hr, h1, h2, h3, h4, h5, h6) {
33
+ margin: 0;
34
+ padding: 0;
35
+ }
36
+
37
+ .ox-tweet.ox-tweet--full :where(ul, ol) {
38
+ list-style: none;
39
+ }
40
+
41
+ .ox-tweet.ox-tweet--full :where(a) {
42
+ font-weight: inherit;
43
+ text-decoration: none;
44
+ }
45
+
46
+ .ox-tweet.ox-tweet--full :where(code, pre, kbd, samp) {
47
+ padding: 0;
48
+ font-size: inherit;
49
+ font-family: inherit;
50
+ background: none;
51
+ }
52
+
53
+ .ox-tweet.ox-tweet--full :where(code)::before,
54
+ .ox-tweet.ox-tweet--full :where(code)::after {
55
+ content: none;
56
+ }
57
+
58
+ /* The quoted post is a `<blockquote>`, which prose styles the hardest. */
59
+ .ox-tweet.ox-tweet--full .ox-tweet__quote {
60
+ font-style: normal;
61
+ font-weight: 400;
62
+ color: inherit;
63
+ quotes: none;
64
+ }
65
+
66
+ .ox-tweet.ox-tweet--full .ox-tweet__quote :where(p)::before,
67
+ .ox-tweet.ox-tweet--full .ox-tweet__quote :where(p)::after,
68
+ .ox-tweet.ox-tweet--full .ox-tweet__quote :where(p):first-of-type::before,
69
+ .ox-tweet.ox-tweet--full .ox-tweet__quote :where(p):last-of-type::after {
70
+ content: none;
71
+ }
1
72
  /*
2
73
  * Opt-in full-card chrome for Twitter/X embeds.
3
74
  * Loaded only when a page has .ox-tweet--full.
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderThemeTokenCss = renderThemeTokenCss;
4
+ exports.tokensToCss = tokensToCss;
5
+ const TOKEN_PREFIX = "--octc-";
6
+ const TOKEN_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;
7
+ /**
8
+ * Renders a theme's `--octc-*` tokens as a standalone stylesheet.
9
+ *
10
+ * The built-in SSG emits these declarations itself, but `ssg.bare: true` and
11
+ * custom hosts render their own document — this is how they get the same
12
+ * tokens. The built-in highlighter emits `var(--octc-syntax-*)` references, so
13
+ * a bare host that wants only the highlighter palette can ask for it:
14
+ *
15
+ * ```ts
16
+ * import { renderThemeTokenCss } from "@ox-content/vite-plugin/theme-tokens";
17
+ * import { kanagawa } from "@ox-content/theme-color-kanagawa";
18
+ *
19
+ * const css = renderThemeTokenCss(kanagawa, {
20
+ * include: (name) => name.startsWith("syntax-"),
21
+ * });
22
+ * ```
23
+ *
24
+ * Layers compose left to right and each layer's `extends` chain is flattened
25
+ * base-first, matching how `resolveTheme()` stacks a skin and a color scheme.
26
+ */
27
+ function renderThemeTokenCss(theme, options = {}) {
28
+ const layers = (Array.isArray(theme) ? theme : [theme]).flatMap(expandExtendsChain);
29
+ return tokensToCss(mergeTokens(layers, "tokens", options.include), mergeTokens(layers, "darkTokens", options.include));
30
+ }
31
+ /**
32
+ * Renders light and dark token records as the three selectors the SSG runtime
33
+ * switches between: an explicit `[data-theme="dark"]` opt-in, the OS
34
+ * `prefers-color-scheme` fallback, and the `:root` base.
35
+ *
36
+ * Emitted after the typed color variables and before the theme's own `css`, so
37
+ * a token can override a typed color and raw `css` can override a token.
38
+ */
39
+ function tokensToCss(light, dark) {
40
+ const lightBody = declarations(light, " ");
41
+ const darkBody = declarations(dark, " ");
42
+ const blocks = [];
43
+ if (lightBody) {
44
+ blocks.push(`:root {\n${lightBody}\n}`);
45
+ }
46
+ if (darkBody) {
47
+ blocks.push(`[data-theme="dark"] {\n${darkBody}\n}`);
48
+ blocks.push(`@media (prefers-color-scheme: dark) {\n :root:not([data-theme="light"]) {\n${declarations(dark, " ")}\n }\n}`);
49
+ }
50
+ return blocks.join("\n");
51
+ }
52
+ function declarations(tokens, indent) {
53
+ return Object.entries(tokens)
54
+ .filter(([, value]) => value !== undefined && value !== "")
55
+ .map(([name, value]) => `${indent}${TOKEN_PREFIX}${assertTokenName(name)}: ${value};`)
56
+ .join("\n");
57
+ }
58
+ function assertTokenName(name) {
59
+ // Token names land verbatim inside a declaration block, so a stray `:` or `}`
60
+ // would silently break every rule after it. Fail the build with the offending
61
+ // key instead of shipping a corrupt stylesheet.
62
+ if (!TOKEN_NAME_PATTERN.test(name)) {
63
+ throw new Error(`Invalid theme token name: ${JSON.stringify(name)}. ` +
64
+ `Token names are lowercase kebab-case without the "${TOKEN_PREFIX}" prefix (e.g. "surface-glass").`);
65
+ }
66
+ return name;
67
+ }
68
+ function mergeTokens(layers, field, include) {
69
+ const merged = {};
70
+ for (const layer of layers) {
71
+ for (const [name, value] of Object.entries(layer[field] ?? {})) {
72
+ if (!include || include(name)) {
73
+ merged[name] = value;
74
+ }
75
+ }
76
+ }
77
+ return merged;
78
+ }
79
+ /**
80
+ * Flattens one layer's `extends` chain into base-first order, mirroring the
81
+ * SSG's own resolution. The `seen` guard keeps a theme that extends itself (or
82
+ * forms a cycle across two packages) from hanging the caller.
83
+ */
84
+ function expandExtendsChain(theme) {
85
+ const chain = [];
86
+ const seen = new Set();
87
+ let current = theme;
88
+ while (current && !seen.has(current)) {
89
+ seen.add(current);
90
+ chain.unshift(current);
91
+ current = current.extends;
92
+ }
93
+ return chain;
94
+ }
95
+ //# sourceMappingURL=theme-tokens.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme-tokens.cjs","sourceRoot":"","sources":["../../../../home/runner/work/ox-content/ox-content/npm/vite-plugin-ox-content/src/theme-tokens.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Free-form `--octc-*` custom properties for themes that need more than the\n * typed `colors` / `fonts` / `layout` fields.\n *\n * Keys are written **without** the `--octc-` prefix, so `\"surface-glass\"`\n * becomes `--octc-surface-glass`. This is the seam that keeps the two theme\n * axes independent: a color package can restyle code-block line markers, brand\n * accents, and surface textures purely through tokens, while a skin package\n * lays out geometry against those same tokens without knowing any color.\n */\nexport type ThemeTokens = Record<string, string>;\n\nconst TOKEN_PREFIX = \"--octc-\";\nconst TOKEN_NAME_PATTERN = /^[a-z][a-z0-9-]*$/;\n\n/**\n * The token-bearing shape of a theme.\n *\n * Declared structurally instead of importing `ThemeConfig` so this module keeps\n * an empty import graph: `@ox-content/vite-plugin/theme-tokens` has to be\n * loadable by a bare (`ssg.bare: true`) or custom host that never pulls in the\n * Vite plugin, the SSG, the native binding, or a filesystem API. Every\n * `ThemeConfig` — including the published `@ox-content/theme-color-*` and\n * `@ox-content/theme-*` packages — satisfies it.\n */\nexport interface ThemeTokenSource {\n tokens?: ThemeTokens;\n darkTokens?: ThemeTokens;\n extends?: ThemeTokenSource;\n}\n\n/**\n * Options for {@link renderThemeTokenCss}.\n */\nexport interface RenderThemeTokenCssOptions {\n /**\n * Keeps only the tokens whose name passes the predicate. Names arrive without\n * the `--octc-` prefix, so `(name) => name.startsWith(\"syntax-\")` reuses a\n * color scheme's highlighter palette without adopting its page colors,\n * typography, or layout policy.\n *\n * Filtering runs per layer, before merging, so a token a later layer would\n * have overridden is dropped along with the override.\n */\n include?: (name: string) => boolean;\n}\n\n/**\n * Renders a theme's `--octc-*` tokens as a standalone stylesheet.\n *\n * The built-in SSG emits these declarations itself, but `ssg.bare: true` and\n * custom hosts render their own document — this is how they get the same\n * tokens. The built-in highlighter emits `var(--octc-syntax-*)` references, so\n * a bare host that wants only the highlighter palette can ask for it:\n *\n * ```ts\n * import { renderThemeTokenCss } from \"@ox-content/vite-plugin/theme-tokens\";\n * import { kanagawa } from \"@ox-content/theme-color-kanagawa\";\n *\n * const css = renderThemeTokenCss(kanagawa, {\n * include: (name) => name.startsWith(\"syntax-\"),\n * });\n * ```\n *\n * Layers compose left to right and each layer's `extends` chain is flattened\n * base-first, matching how `resolveTheme()` stacks a skin and a color scheme.\n */\nexport function renderThemeTokenCss(\n theme: ThemeTokenSource | ThemeTokenSource[],\n options: RenderThemeTokenCssOptions = {},\n): string {\n const layers = (Array.isArray(theme) ? theme : [theme]).flatMap(expandExtendsChain);\n return tokensToCss(\n mergeTokens(layers, \"tokens\", options.include),\n mergeTokens(layers, \"darkTokens\", options.include),\n );\n}\n\n/**\n * Renders light and dark token records as the three selectors the SSG runtime\n * switches between: an explicit `[data-theme=\"dark\"]` opt-in, the OS\n * `prefers-color-scheme` fallback, and the `:root` base.\n *\n * Emitted after the typed color variables and before the theme's own `css`, so\n * a token can override a typed color and raw `css` can override a token.\n */\nexport function tokensToCss(light: ThemeTokens, dark: ThemeTokens): string {\n const lightBody = declarations(light, \" \");\n const darkBody = declarations(dark, \" \");\n const blocks: string[] = [];\n\n if (lightBody) {\n blocks.push(`:root {\\n${lightBody}\\n}`);\n }\n if (darkBody) {\n blocks.push(`[data-theme=\"dark\"] {\\n${darkBody}\\n}`);\n blocks.push(\n `@media (prefers-color-scheme: dark) {\\n :root:not([data-theme=\"light\"]) {\\n${declarations(dark, \" \")}\\n }\\n}`,\n );\n }\n\n return blocks.join(\"\\n\");\n}\n\nfunction declarations(tokens: ThemeTokens, indent: string): string {\n return Object.entries(tokens)\n .filter(([, value]) => value !== undefined && value !== \"\")\n .map(([name, value]) => `${indent}${TOKEN_PREFIX}${assertTokenName(name)}: ${value};`)\n .join(\"\\n\");\n}\n\nfunction assertTokenName(name: string): string {\n // Token names land verbatim inside a declaration block, so a stray `:` or `}`\n // would silently break every rule after it. Fail the build with the offending\n // key instead of shipping a corrupt stylesheet.\n if (!TOKEN_NAME_PATTERN.test(name)) {\n throw new Error(\n `Invalid theme token name: ${JSON.stringify(name)}. ` +\n `Token names are lowercase kebab-case without the \"${TOKEN_PREFIX}\" prefix (e.g. \"surface-glass\").`,\n );\n }\n return name;\n}\n\nfunction mergeTokens(\n layers: ThemeTokenSource[],\n field: \"tokens\" | \"darkTokens\",\n include?: (name: string) => boolean,\n): ThemeTokens {\n const merged: ThemeTokens = {};\n\n for (const layer of layers) {\n for (const [name, value] of Object.entries(layer[field] ?? {})) {\n if (!include || include(name)) {\n merged[name] = value;\n }\n }\n }\n\n return merged;\n}\n\n/**\n * Flattens one layer's `extends` chain into base-first order, mirroring the\n * SSG's own resolution. The `seen` guard keeps a theme that extends itself (or\n * forms a cycle across two packages) from hanging the caller.\n */\nfunction expandExtendsChain(theme: ThemeTokenSource): ThemeTokenSource[] {\n const chain: ThemeTokenSource[] = [];\n const seen = new Set<ThemeTokenSource>();\n let current: ThemeTokenSource | undefined = theme;\n\n while (current && !seen.has(current)) {\n seen.add(current);\n chain.unshift(current);\n current = current.extends;\n }\n\n return chain;\n}\n"]}
@@ -0,0 +1,75 @@
1
+ //#region src/theme-tokens.d.ts
2
+ /**
3
+ * Free-form `--octc-*` custom properties for themes that need more than the
4
+ * typed `colors` / `fonts` / `layout` fields.
5
+ *
6
+ * Keys are written **without** the `--octc-` prefix, so `"surface-glass"`
7
+ * becomes `--octc-surface-glass`. This is the seam that keeps the two theme
8
+ * axes independent: a color package can restyle code-block line markers, brand
9
+ * accents, and surface textures purely through tokens, while a skin package
10
+ * lays out geometry against those same tokens without knowing any color.
11
+ */
12
+ type ThemeTokens = Record<string, string>;
13
+ /**
14
+ * The token-bearing shape of a theme.
15
+ *
16
+ * Declared structurally instead of importing `ThemeConfig` so this module keeps
17
+ * an empty import graph: `@ox-content/vite-plugin/theme-tokens` has to be
18
+ * loadable by a bare (`ssg.bare: true`) or custom host that never pulls in the
19
+ * Vite plugin, the SSG, the native binding, or a filesystem API. Every
20
+ * `ThemeConfig` — including the published `@ox-content/theme-color-*` and
21
+ * `@ox-content/theme-*` packages — satisfies it.
22
+ */
23
+ interface ThemeTokenSource {
24
+ tokens?: ThemeTokens;
25
+ darkTokens?: ThemeTokens;
26
+ extends?: ThemeTokenSource;
27
+ }
28
+ /**
29
+ * Options for {@link renderThemeTokenCss}.
30
+ */
31
+ interface RenderThemeTokenCssOptions {
32
+ /**
33
+ * Keeps only the tokens whose name passes the predicate. Names arrive without
34
+ * the `--octc-` prefix, so `(name) => name.startsWith("syntax-")` reuses a
35
+ * color scheme's highlighter palette without adopting its page colors,
36
+ * typography, or layout policy.
37
+ *
38
+ * Filtering runs per layer, before merging, so a token a later layer would
39
+ * have overridden is dropped along with the override.
40
+ */
41
+ include?: (name: string) => boolean;
42
+ }
43
+ /**
44
+ * Renders a theme's `--octc-*` tokens as a standalone stylesheet.
45
+ *
46
+ * The built-in SSG emits these declarations itself, but `ssg.bare: true` and
47
+ * custom hosts render their own document — this is how they get the same
48
+ * tokens. The built-in highlighter emits `var(--octc-syntax-*)` references, so
49
+ * a bare host that wants only the highlighter palette can ask for it:
50
+ *
51
+ * ```ts
52
+ * import { renderThemeTokenCss } from "@ox-content/vite-plugin/theme-tokens";
53
+ * import { kanagawa } from "@ox-content/theme-color-kanagawa";
54
+ *
55
+ * const css = renderThemeTokenCss(kanagawa, {
56
+ * include: (name) => name.startsWith("syntax-"),
57
+ * });
58
+ * ```
59
+ *
60
+ * Layers compose left to right and each layer's `extends` chain is flattened
61
+ * base-first, matching how `resolveTheme()` stacks a skin and a color scheme.
62
+ */
63
+ declare function renderThemeTokenCss(theme: ThemeTokenSource | ThemeTokenSource[], options?: RenderThemeTokenCssOptions): string;
64
+ /**
65
+ * Renders light and dark token records as the three selectors the SSG runtime
66
+ * switches between: an explicit `[data-theme="dark"]` opt-in, the OS
67
+ * `prefers-color-scheme` fallback, and the `:root` base.
68
+ *
69
+ * Emitted after the typed color variables and before the theme's own `css`, so
70
+ * a token can override a typed color and raw `css` can override a token.
71
+ */
72
+ declare function tokensToCss(light: ThemeTokens, dark: ThemeTokens): string;
73
+ //#endregion
74
+ export { RenderThemeTokenCssOptions, ThemeTokenSource, ThemeTokens, renderThemeTokenCss, tokensToCss };
75
+ //# sourceMappingURL=theme-tokens.d.cts.map