@ox-content/vite-plugin 3.0.0-alpha.10 → 3.0.0-alpha.12

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.
@@ -7,4 +7,6 @@
7
7
  @import "./youtube.css";
8
8
  @import "./tabs.css";
9
9
  @import "./mermaid.css";
10
+ @import "./graphviz.css";
11
+ @import "./citations.css";
10
12
  @import "./not-by-ai.css";
@@ -0,0 +1,62 @@
1
+ .content .ox-cite {
2
+ white-space: nowrap;
3
+ font-size: 0.95em;
4
+ }
5
+
6
+ .content .ox-cite__ref {
7
+ font-variant-numeric: tabular-nums;
8
+ text-decoration-thickness: 0.08em;
9
+ text-underline-offset: 0.2em;
10
+ }
11
+
12
+ .content .ox-cite__ref:focus-visible,
13
+ .content .ox-bibliography__item:focus-within {
14
+ outline: var(--octc-focus-ring);
15
+ outline-offset: var(--octc-focus-offset);
16
+ }
17
+
18
+ .content .ox-cite__ref:target,
19
+ .content .ox-bibliography__item:target {
20
+ background: var(--octc-color-code-line-focus);
21
+ }
22
+
23
+ .content .ox-bibliography {
24
+ margin-top: 2rem;
25
+ padding-top: 1rem;
26
+ border-top: 1px solid var(--octc-color-border);
27
+ }
28
+
29
+ .content .ox-bibliography__title {
30
+ margin-top: 0;
31
+ font-size: 1.25rem;
32
+ }
33
+
34
+ .content .ox-bibliography__list {
35
+ margin-block: 0;
36
+ padding-inline-start: 1.5rem;
37
+ }
38
+
39
+ .content .ox-bibliography__item {
40
+ padding-inline-start: 0.25rem;
41
+ color: var(--octc-color-text-muted);
42
+ }
43
+
44
+ .content .ox-bibliography__item + .ox-bibliography__item {
45
+ margin-top: 0.65rem;
46
+ }
47
+
48
+ .content .ox-bibliography__item cite {
49
+ color: var(--octc-color-text);
50
+ font-style: italic;
51
+ }
52
+
53
+ .content .ox-bibliography__url,
54
+ .content .ox-bibliography__doi {
55
+ overflow-wrap: anywhere;
56
+ }
57
+
58
+ @media print {
59
+ .content .ox-cite__ref {
60
+ text-decoration: none;
61
+ }
62
+ }
@@ -1147,6 +1147,34 @@ a:hover {
1147
1147
  .content pre.ox-code-block code {
1148
1148
  display: block;
1149
1149
  }
1150
+ /* Each `.line` is a block, so the newline the highlighter writes between two of
1151
+ them renders as a second break inside a `pre` and every code line comes out
1152
+ double-spaced. Collapsing whitespace on the `code` drops those newlines;
1153
+ each line restores its own. The `:has` guard leaves a block whose code was
1154
+ never split into lines — an unhighlighted one — reading its indentation from
1155
+ the `pre` as before. */
1156
+ .content pre.ox-code-block code:has(> .line) {
1157
+ white-space: normal;
1158
+ }
1159
+ .content pre.ox-code-block code:has(> .line) > .line {
1160
+ white-space: pre;
1161
+ }
1162
+ .content pre.ox-code-block--wrap {
1163
+ overflow-x: hidden;
1164
+ white-space: pre-wrap;
1165
+ }
1166
+ .content pre.ox-code-block--wrap code,
1167
+ .content pre.ox-code-block--wrap .line {
1168
+ white-space: inherit;
1169
+ overflow-wrap: anywhere;
1170
+ }
1171
+ .content pre.ox-code-block--wrap code:has(> .line) > .line {
1172
+ white-space: pre-wrap;
1173
+ }
1174
+ .content pre.ox-code-block--nowrap {
1175
+ overflow-x: auto;
1176
+ white-space: pre;
1177
+ }
1150
1178
  .content pre.ox-code-block[data-code-title]::before {
1151
1179
  content: attr(data-code-title);
1152
1180
  display: block;
@@ -1180,6 +1208,14 @@ a:hover {
1180
1208
  user-select: none;
1181
1209
  pointer-events: none;
1182
1210
  }
1211
+ .content pre.ox-code-block .ox-code-line:target {
1212
+ scroll-margin-top: calc(var(--octc-header-height) + 1rem);
1213
+ opacity: 1;
1214
+ filter: none;
1215
+ background: var(--octc-color-code-line-focus);
1216
+ outline: 1px solid color-mix(in srgb, var(--octc-color-primary) 48%, transparent);
1217
+ outline-offset: -1px;
1218
+ }
1183
1219
  .content pre.ox-code-block.has-focused .line {
1184
1220
  opacity: var(--octc-color-code-line-dim);
1185
1221
  filter: blur(0.6px);
@@ -1228,6 +1264,10 @@ a:hover {
1228
1264
  margin: 1.25rem 0;
1229
1265
  font-size: 0.875rem;
1230
1266
  }
1267
+ .content table[data-ox-table-scrollable="true"]:focus-visible {
1268
+ outline: var(--octc-focus-ring);
1269
+ outline-offset: var(--octc-focus-offset);
1270
+ }
1231
1271
  .content th,
1232
1272
  .content td {
1233
1273
  border: 0;
@@ -42,6 +42,29 @@
42
42
  text-decoration: underline;
43
43
  }
44
44
 
45
+ .ox-github-resource-kind {
46
+ display: inline-flex;
47
+ align-items: center;
48
+ border: 1px solid color-mix(in srgb, var(--octc-color-border) 70%, transparent);
49
+ border-radius: 999px;
50
+ padding: 0.05rem 0.45rem;
51
+ color: var(--octc-color-text-muted);
52
+ font-size: 0.75rem;
53
+ line-height: 1.4;
54
+ }
55
+
56
+ .ox-github-resource-title {
57
+ margin: 0 0 0.5rem;
58
+ color: var(--octc-color-text);
59
+ font-weight: 600;
60
+ line-height: 1.45;
61
+ }
62
+
63
+ .ox-github-resource-card:hover .ox-github-resource-title {
64
+ color: var(--octc-color-primary);
65
+ text-decoration: underline;
66
+ }
67
+
45
68
  .ox-github-description {
46
69
  font-size: 0.875rem;
47
70
  color: var(--octc-color-text-muted);
@@ -133,37 +156,14 @@
133
156
  background: #89e051;
134
157
  }
135
158
 
136
- /* Loading state */
137
- .ox-github-card.loading {
138
- min-height: 100px;
139
- }
140
-
141
- .ox-github-card.loading::after {
142
- content: "";
143
- display: block;
144
- width: 24px;
145
- height: 24px;
146
- margin: 2rem auto;
147
- border: 2px solid var(--octc-color-border);
148
- border-top-color: var(--octc-color-primary);
149
- border-radius: 50%;
150
- animation: ox-github-spin 0.8s linear infinite;
151
- }
152
-
153
- @keyframes ox-github-spin {
154
- to {
155
- transform: rotate(360deg);
156
- }
157
- }
158
-
159
159
  /* Error state */
160
160
  .ox-github-card.error {
161
- border-color: #f87171;
161
+ border-color: var(--octc-color-danger);
162
162
  background: transparent;
163
163
  }
164
164
 
165
165
  .ox-github-error {
166
- color: #f87171;
166
+ color: var(--octc-color-danger);
167
167
  font-size: 0.875rem;
168
168
  }
169
169
 
@@ -254,3 +254,9 @@
254
254
  border-radius: 0 !important;
255
255
  background: transparent !important;
256
256
  }
257
+
258
+ @media (prefers-reduced-motion: reduce) {
259
+ .ox-github-card {
260
+ transition: none;
261
+ }
262
+ }
@@ -0,0 +1,34 @@
1
+ .ox-graphviz {
2
+ margin: 1.5rem 0;
3
+ overflow-x: auto;
4
+ color: var(--octc-color-text);
5
+ }
6
+
7
+ .ox-graphviz svg {
8
+ display: block;
9
+ width: max-content;
10
+ max-width: 100%;
11
+ height: auto;
12
+ margin-inline: auto;
13
+ }
14
+
15
+ .ox-graphviz text {
16
+ fill: currentColor;
17
+ font-family: var(--octc-font-family-base);
18
+ }
19
+
20
+ .ox-graphviz .node polygon,
21
+ .ox-graphviz .node rect,
22
+ .ox-graphviz .node ellipse {
23
+ fill: var(--octc-color-bg-soft);
24
+ stroke: currentColor;
25
+ }
26
+
27
+ .ox-graphviz .edge path,
28
+ .ox-graphviz .edge polygon {
29
+ stroke: currentColor;
30
+ }
31
+
32
+ .ox-graphviz .edge polygon {
33
+ fill: currentColor;
34
+ }
@@ -22,6 +22,7 @@
22
22
  .content .ox-magic-link__image {
23
23
  width: 1em;
24
24
  height: 1em;
25
+ margin: 0;
25
26
  border-radius: 999px;
26
27
  object-fit: cover;
27
28
  flex: 0 0 auto;
@@ -121,29 +121,6 @@
121
121
  }
122
122
  }
123
123
 
124
- /* Loading state */
125
- .ox-ogp-card.loading {
126
- min-height: 100px;
127
- justify-content: center;
128
- align-items: center;
129
- }
130
-
131
- .ox-ogp-card.loading::after {
132
- content: "";
133
- width: 24px;
134
- height: 24px;
135
- border: 2px solid var(--octc-color-border);
136
- border-top-color: var(--octc-color-primary);
137
- border-radius: 50%;
138
- animation: ox-ogp-spin 0.8s linear infinite;
139
- }
140
-
141
- @keyframes ox-ogp-spin {
142
- to {
143
- transform: rotate(360deg);
144
- }
145
- }
146
-
147
124
  /* Error/fallback state */
148
125
  .ox-ogp-card.error {
149
126
  border-color: var(--octc-color-border);
@@ -177,3 +154,10 @@
177
154
  height: 14px;
178
155
  color: var(--octc-color-text-muted);
179
156
  }
157
+
158
+ @media (prefers-reduced-motion: reduce) {
159
+ .ox-ogp-card,
160
+ .ox-ogp-simple {
161
+ transition: none;
162
+ }
163
+ }
@@ -327,24 +327,123 @@
327
327
  border: 0;
328
328
  border-radius: 0;
329
329
  }
330
-
331
- /* Media iframes */
332
- .ox-spotify,
333
- .ox-apple-music,
334
- .ox-speaker-deck,
335
- .ox-stackblitz,
336
- .ox-audio,
337
- .ox-video {
330
+ /* Provider cards for static article, place, community, and social embeds */
331
+ .ox-provider-card {
338
332
  display: block;
339
- width: 100%;
340
333
  margin: 1.5rem 0;
341
- border: 0;
342
- border-radius: 12px;
334
+ border: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
335
+ border-radius: 8px;
336
+ overflow: hidden;
337
+ background: var(--octc-color-bg);
338
+ }
339
+
340
+ .ox-provider-card__main {
341
+ display: block;
342
+ padding: 1rem;
343
+ color: var(--octc-color-text);
344
+ text-decoration: none;
345
+ }
346
+
347
+ .ox-provider-card__main:hover {
348
+ text-decoration: none;
349
+ }
350
+
351
+ .ox-provider-card__header,
352
+ .ox-provider-card__meta {
353
+ display: flex;
354
+ flex-wrap: wrap;
355
+ align-items: center;
356
+ gap: 0.35rem 0.75rem;
357
+ color: var(--octc-color-text-muted);
358
+ }
359
+
360
+ .ox-provider-card__header {
361
+ margin-bottom: 0.625rem;
362
+ font-size: 0.75rem;
363
+ }
364
+
365
+ .ox-provider-card__network,
366
+ .ox-provider-card__source {
367
+ font-weight: 600;
368
+ }
369
+
370
+ .ox-provider-card__network {
371
+ color: var(--octc-color-primary);
372
+ letter-spacing: 0.08em;
373
+ text-transform: uppercase;
374
+ }
375
+
376
+ .ox-provider-card__body-wrap {
377
+ display: flex;
378
+ align-items: flex-start;
379
+ gap: 0.75rem;
380
+ min-width: 0;
381
+ }
382
+
383
+ .ox-provider-card__avatar {
384
+ flex: 0 0 auto;
385
+ width: 42px;
386
+ height: 42px;
387
+ border-radius: 50%;
388
+ object-fit: cover;
389
+ background: var(--octc-color-bg-alt);
390
+ }
391
+
392
+ .ox-provider-card__copy {
393
+ min-width: 0;
394
+ }
395
+
396
+ .ox-provider-card__title {
397
+ margin: 0;
398
+ font-size: 1rem;
399
+ line-height: 1.35;
400
+ color: var(--octc-color-text);
343
401
  }
344
402
 
345
- .ox-stackblitz {
403
+ .ox-provider-card__main:hover .ox-provider-card__title {
404
+ text-decoration: underline;
405
+ }
406
+
407
+ .ox-provider-card__excerpt {
408
+ margin: 0.625rem 0 0;
409
+ font-size: 0.875rem;
410
+ line-height: 1.55;
411
+ color: var(--octc-color-text-muted);
412
+ white-space: pre-wrap;
413
+ }
414
+
415
+ .ox-provider-card__image {
416
+ display: block;
417
+ width: 100%;
418
+ height: auto;
419
+ max-height: 420px;
420
+ margin-top: 0.875rem;
346
421
  border: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
347
422
  border-radius: 8px;
423
+ object-fit: cover;
424
+ background: var(--octc-color-bg-alt);
425
+ }
426
+
427
+ .ox-provider-card__meta {
428
+ margin-top: 0.875rem;
429
+ font-size: 0.75rem;
430
+ }
431
+
432
+ .ox-provider-card__metric > span {
433
+ font-weight: 600;
434
+ color: var(--octc-color-text);
435
+ }
436
+
437
+ .ox-provider-card__source {
438
+ color: var(--octc-color-primary);
439
+ }
440
+
441
+ .ox-provider-card__map {
442
+ display: block;
443
+ width: 100%;
444
+ border: 0;
445
+ border-top: 1px solid color-mix(in srgb, var(--octc-color-border) 74%, transparent);
446
+ background: var(--octc-color-bg-alt);
348
447
  }
349
448
  .ox-tweet--rich .ox-tweet__card {
350
449
  display: block;
@@ -200,3 +200,11 @@
200
200
  .ox-tabs-fallback .ox-tabs-fallback-content {
201
201
  padding: 1rem;
202
202
  }
203
+
204
+ /* The disclosure marker still turns, it just turns instantly. */
205
+ @media (prefers-reduced-motion: reduce) {
206
+ .ox-tabs label,
207
+ .ox-tabs-fallback summary::before {
208
+ transition: none;
209
+ }
210
+ }
@@ -80,7 +80,8 @@
80
80
  background: var(--ox-tweet-bg);
81
81
  }
82
82
 
83
- [data-theme="dark"] .ox-tweet--full {
83
+ [data-theme="dark"] .ox-tweet--full,
84
+ .dark .ox-tweet--full {
84
85
  --ox-tweet-border: 1px solid rgb(66, 83, 100);
85
86
  --ox-tweet-font-color: rgb(247, 249, 249);
86
87
  --ox-tweet-font-color-secondary: rgb(139, 152, 165);
@@ -93,7 +94,7 @@
93
94
  }
94
95
 
95
96
  @media (prefers-color-scheme: dark) {
96
- :root:not([data-theme="light"]) .ox-tweet--full {
97
+ :root:not([data-theme="light"]):not(.light) .ox-tweet--full {
97
98
  --ox-tweet-border: 1px solid rgb(66, 83, 100);
98
99
  --ox-tweet-font-color: rgb(247, 249, 249);
99
100
  --ox-tweet-font-color-secondary: rgb(139, 152, 165);
@@ -75,3 +75,13 @@
75
75
  width: calc(100% + 1.5rem);
76
76
  }
77
77
  }
78
+
79
+ @media (prefers-reduced-motion: reduce) {
80
+ .ox-youtube-placeholder::after {
81
+ transition: none;
82
+ }
83
+
84
+ .ox-youtube-placeholder:hover::after {
85
+ transform: none;
86
+ }
87
+ }
@@ -41,8 +41,8 @@ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["modu
41
41
  let node_module = require("node:module");
42
42
  let node_fs = require("node:fs");
43
43
  let node_path = require("node:path");
44
- let node_fs_promises = require("node:fs/promises");
45
44
  let node_crypto = require("node:crypto");
45
+ let node_fs_promises = require("node:fs/promises");
46
46
  let glob = require("glob");
47
47
  //#region src/napi.ts
48
48
  const requireNapi = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
@@ -1,8 +1,8 @@
1
1
  import { createRequire } from "node:module";
2
2
  import { existsSync } from "node:fs";
3
3
  import { isAbsolute, join, resolve } from "node:path";
4
- import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
5
4
  import { createHash } from "node:crypto";
5
+ import { mkdir, readFile, readdir, stat, writeFile } from "node:fs/promises";
6
6
  import { glob } from "glob";
7
7
  //#region src/napi.ts
8
8
  const requireNapi = createRequire(import.meta.url);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ox-content/vite-plugin",
3
- "version": "3.0.0-alpha.10",
3
+ "version": "3.0.0-alpha.12",
4
4
  "description": "Vite plugin for Ox Content - High-performance Markdown processing with Environment API",
5
5
  "keywords": [
6
6
  "environment-api",
@@ -62,6 +62,8 @@
62
62
  "./styles/youtube.css": "./dist/styles/youtube.css",
63
63
  "./styles/tabs.css": "./dist/styles/tabs.css",
64
64
  "./styles/mermaid.css": "./dist/styles/mermaid.css",
65
+ "./styles/graphviz.css": "./dist/styles/graphviz.css",
66
+ "./styles/citations.css": "./dist/styles/citations.css",
65
67
  "./styles/not-by-ai.css": "./dist/styles/not-by-ai.css"
66
68
  },
67
69
  "publishConfig": {
@@ -86,7 +88,7 @@
86
88
  "satori-html": "^0.3.2",
87
89
  "typescript": "^7.0.2",
88
90
  "unified": "^11.0.5",
89
- "@ox-content/napi": "3.0.0-alpha.10"
91
+ "@ox-content/napi": "3.0.0-alpha.12"
90
92
  },
91
93
  "devDependencies": {
92
94
  "@playwright/test": "^1.62.1",
@@ -95,6 +97,7 @@
95
97
  "@types/react": "^19.2.18",
96
98
  "@types/react-dom": "^19.2.4",
97
99
  "@typescript/native-preview": "^7.0.0-dev.20260707.2",
100
+ "budoux": "^0.9.0",
98
101
  "katex": "^0.16.22",
99
102
  "vite": "npm:@voidzero-dev/vite-plus-core@0.2.8",
100
103
  "vite-plus": "0.2.9",
@@ -102,6 +105,7 @@
102
105
  },
103
106
  "peerDependencies": {
104
107
  "@vue/compiler-sfc": "^3.4.0",
108
+ "budoux": "^0.9.0",
105
109
  "katex": "^0.16.0",
106
110
  "react": "^19.0.0",
107
111
  "react-dom": "^19.0.0",
@@ -110,6 +114,9 @@
110
114
  "vue": "^3.4.0"
111
115
  },
112
116
  "peerDependenciesMeta": {
117
+ "budoux": {
118
+ "optional": true
119
+ },
113
120
  "katex": {
114
121
  "optional": true
115
122
  },