@orz/ui-markdown 0.0.0-stage → 0.1.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.
- package/LICENSE +29 -0
- package/README.md +175 -2
- package/dist/attachment-links.d.ts +20 -0
- package/dist/attachment-links.d.ts.map +1 -0
- package/dist/attachment-links.js +27 -0
- package/dist/attachment-links.js.map +1 -0
- package/dist/content.d.ts +31 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +78 -0
- package/dist/content.js.map +1 -0
- package/dist/embeds.d.ts +18 -0
- package/dist/embeds.d.ts.map +1 -0
- package/dist/embeds.js +59 -0
- package/dist/embeds.js.map +1 -0
- package/dist/external-links.d.ts +23 -0
- package/dist/external-links.d.ts.map +1 -0
- package/dist/external-links.js +43 -0
- package/dist/external-links.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/markdown-processor.d.ts +23 -0
- package/dist/lib/markdown-processor.d.ts.map +1 -0
- package/dist/lib/markdown-processor.js +35 -0
- package/dist/lib/markdown-processor.js.map +1 -0
- package/dist/lib/rehype-details.d.ts +13 -0
- package/dist/lib/rehype-details.d.ts.map +1 -0
- package/dist/lib/rehype-details.js +256 -0
- package/dist/lib/rehype-details.js.map +1 -0
- package/dist/lib/rehype-source-lines.d.ts +23 -0
- package/dist/lib/rehype-source-lines.d.ts.map +1 -0
- package/dist/lib/rehype-source-lines.js +77 -0
- package/dist/lib/rehype-source-lines.js.map +1 -0
- package/dist/lib/remark-frontmatter-table.d.ts +119 -0
- package/dist/lib/remark-frontmatter-table.d.ts.map +1 -0
- package/dist/lib/remark-frontmatter-table.js +212 -0
- package/dist/lib/remark-frontmatter-table.js.map +1 -0
- package/dist/lib/remark-rejected-urls.d.ts +23 -0
- package/dist/lib/remark-rejected-urls.d.ts.map +1 -0
- package/dist/lib/remark-rejected-urls.js +79 -0
- package/dist/lib/remark-rejected-urls.js.map +1 -0
- package/dist/markdown.d.ts +30 -0
- package/dist/markdown.d.ts.map +1 -0
- package/dist/markdown.js +146 -0
- package/dist/markdown.js.map +1 -0
- package/dist/plugin.d.ts +39 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +2 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +66 -3
- package/styles.css +293 -0
package/package.json
CHANGED
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orz/ui-markdown",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GitHub-style markdown rendering on react-markdown, extended by markdown plugins and drawing code and embeds through @orz/ui-content",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/orzFly/ui.git",
|
|
9
|
+
"directory": "packages/ui-markdown"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"**/*.css"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"@orz/source": "./src/index.ts",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./lib/*": {
|
|
22
|
+
"@orz/source": "./src/lib/*.ts",
|
|
23
|
+
"types": "./dist/lib/*.d.ts",
|
|
24
|
+
"default": "./dist/lib/*.js"
|
|
25
|
+
},
|
|
26
|
+
"./styles.css": "./styles.css"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"styles.css"
|
|
31
|
+
],
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"lucide-react": "^1",
|
|
37
|
+
"react": "^19",
|
|
38
|
+
"react-dom": "^19",
|
|
39
|
+
"@orz/ui": "^0.1.0",
|
|
40
|
+
"@orz/ui-content": "^0.1.0"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@types/hast": "^3.0.5",
|
|
44
|
+
"@types/mdast": "^4.0.4",
|
|
45
|
+
"react-markdown": "^10.1.0",
|
|
46
|
+
"remark-frontmatter": "^5.0.0",
|
|
47
|
+
"remark-gfm": "^4.0.1",
|
|
48
|
+
"remark-parse": "^11.0.0",
|
|
49
|
+
"unified": "^11.0.5"
|
|
50
|
+
},
|
|
51
|
+
"devDependencies": {
|
|
52
|
+
"@testing-library/react": "^16.3.2",
|
|
53
|
+
"@types/node": "^22.20.5",
|
|
54
|
+
"@types/react": "^19.2.18",
|
|
55
|
+
"@types/react-dom": "^19.2.4",
|
|
56
|
+
"happy-dom": "^21.0.3",
|
|
57
|
+
"lucide-react": "^1.31.0",
|
|
58
|
+
"react": "^19.2.8",
|
|
59
|
+
"react-dom": "^19.2.8",
|
|
60
|
+
"vitest": "^5.0.5",
|
|
61
|
+
"@orz/ui-content": "0.1.0",
|
|
62
|
+
"@orz/ui": "0.1.0"
|
|
63
|
+
},
|
|
64
|
+
"scripts": {
|
|
65
|
+
"build": "tsc -p tsconfig.build.json",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"test": "vitest run"
|
|
68
|
+
}
|
|
6
69
|
}
|
package/styles.css
ADDED
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
/* GitHub-flavoured markdown typography (T-32). One plain-CSS block —
|
|
3
|
+
theme tokens make it track light/dark for free, and element swaps in
|
|
4
|
+
the renderer (react-markdown `components`) don't need class surgery.
|
|
5
|
+
Sizes follow github.com issue comments (14px base). */
|
|
6
|
+
.markdown-body {
|
|
7
|
+
font-size: 0.875rem;
|
|
8
|
+
line-height: 1.6;
|
|
9
|
+
overflow-wrap: break-word;
|
|
10
|
+
}
|
|
11
|
+
.markdown-body > :first-child {
|
|
12
|
+
margin-top: 0;
|
|
13
|
+
}
|
|
14
|
+
.markdown-body > :last-child {
|
|
15
|
+
margin-bottom: 0;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* .markdown-paragraph is a <p> stand-in for paragraphs carrying a
|
|
19
|
+
block-level embed — block content HTML forbids inside real <p>. */
|
|
20
|
+
.markdown-body p,
|
|
21
|
+
.markdown-body .markdown-paragraph,
|
|
22
|
+
.markdown-body blockquote,
|
|
23
|
+
.markdown-body ul,
|
|
24
|
+
.markdown-body ol,
|
|
25
|
+
.markdown-body table,
|
|
26
|
+
.markdown-body details,
|
|
27
|
+
.markdown-body .markdown-fence,
|
|
28
|
+
.markdown-body pre {
|
|
29
|
+
margin-block: 0 1rem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* No JS toggle anywhere: native <summary> brings Enter/Space, the `open`
|
|
33
|
+
state and the screen-reader semantics with it. */
|
|
34
|
+
.markdown-body summary {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: center;
|
|
37
|
+
gap: 0.4em;
|
|
38
|
+
cursor: pointer;
|
|
39
|
+
font-weight: 600;
|
|
40
|
+
list-style: none;
|
|
41
|
+
}
|
|
42
|
+
.markdown-body summary::-webkit-details-marker {
|
|
43
|
+
display: none;
|
|
44
|
+
}
|
|
45
|
+
/* lucide's `chevron-right`, painted through a mask so it follows the text
|
|
46
|
+
colour into dark mode. */
|
|
47
|
+
.markdown-body summary::before {
|
|
48
|
+
content: "";
|
|
49
|
+
flex: none;
|
|
50
|
+
width: 1em;
|
|
51
|
+
height: 1em;
|
|
52
|
+
background-color: currentColor;
|
|
53
|
+
mask:
|
|
54
|
+
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m9 18 6-6-6-6'/%3E%3C/svg%3E")
|
|
55
|
+
center / contain no-repeat;
|
|
56
|
+
transition: rotate 120ms ease;
|
|
57
|
+
}
|
|
58
|
+
.markdown-body details[open] > summary::before {
|
|
59
|
+
rotate: 90deg;
|
|
60
|
+
}
|
|
61
|
+
.markdown-body summary > :last-child {
|
|
62
|
+
margin-bottom: 0;
|
|
63
|
+
}
|
|
64
|
+
.markdown-body details > :last-child {
|
|
65
|
+
margin-bottom: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.markdown-body h1,
|
|
69
|
+
.markdown-body h2,
|
|
70
|
+
.markdown-body h3,
|
|
71
|
+
.markdown-body h4,
|
|
72
|
+
.markdown-body h5,
|
|
73
|
+
.markdown-body h6 {
|
|
74
|
+
margin-block: 1.5rem 1rem;
|
|
75
|
+
font-weight: 600;
|
|
76
|
+
line-height: 1.25;
|
|
77
|
+
}
|
|
78
|
+
.markdown-body h1,
|
|
79
|
+
.markdown-body h2 {
|
|
80
|
+
padding-bottom: 0.3em;
|
|
81
|
+
border-bottom: 1px solid var(--border);
|
|
82
|
+
}
|
|
83
|
+
.markdown-body h1 {
|
|
84
|
+
font-size: 2em;
|
|
85
|
+
}
|
|
86
|
+
.markdown-body h2 {
|
|
87
|
+
font-size: 1.5em;
|
|
88
|
+
}
|
|
89
|
+
.markdown-body h3 {
|
|
90
|
+
font-size: 1.25em;
|
|
91
|
+
}
|
|
92
|
+
.markdown-body h4 {
|
|
93
|
+
font-size: 1em;
|
|
94
|
+
}
|
|
95
|
+
.markdown-body h5 {
|
|
96
|
+
font-size: 0.875em;
|
|
97
|
+
}
|
|
98
|
+
.markdown-body h6 {
|
|
99
|
+
font-size: 0.85em;
|
|
100
|
+
color: var(--muted-foreground);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.markdown-body a {
|
|
104
|
+
text-decoration: underline;
|
|
105
|
+
text-underline-offset: 2px;
|
|
106
|
+
}
|
|
107
|
+
/* What externalLinks sets a target on. Generated rather than written into
|
|
108
|
+
the DOM so a copy of the paragraph does not pick it up; the empty alt
|
|
109
|
+
keeps screen readers from announcing an arrow. Inline-block stops the
|
|
110
|
+
underline running under it. An image link is its own affordance and
|
|
111
|
+
gets no arrow. */
|
|
112
|
+
.markdown-body a[target="_blank"]:not(:has(img))::after {
|
|
113
|
+
content: "↗";
|
|
114
|
+
/* biome-ignore lint/suspicious/noDuplicateProperties: the line above is the fallback where content takes no alt text */
|
|
115
|
+
content: "↗" / "";
|
|
116
|
+
display: inline-block;
|
|
117
|
+
margin-left: 0.1em;
|
|
118
|
+
font-size: 0.8em;
|
|
119
|
+
text-decoration: none;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.markdown-body ul,
|
|
123
|
+
.markdown-body ol {
|
|
124
|
+
padding-left: 2em;
|
|
125
|
+
}
|
|
126
|
+
.markdown-body ul {
|
|
127
|
+
list-style-type: disc;
|
|
128
|
+
}
|
|
129
|
+
.markdown-body ol {
|
|
130
|
+
list-style-type: decimal;
|
|
131
|
+
}
|
|
132
|
+
/* Nested lists sit tight under their parent item instead of taking the
|
|
133
|
+
block gap; declared ahead of the deeper marker rules only to keep
|
|
134
|
+
specificity ascending. */
|
|
135
|
+
.markdown-body ul ul,
|
|
136
|
+
.markdown-body ul ol,
|
|
137
|
+
.markdown-body ol ul,
|
|
138
|
+
.markdown-body ol ol {
|
|
139
|
+
margin-block: 0.25em 0;
|
|
140
|
+
}
|
|
141
|
+
.markdown-body ul ul,
|
|
142
|
+
.markdown-body ol ul {
|
|
143
|
+
list-style-type: circle;
|
|
144
|
+
}
|
|
145
|
+
.markdown-body ul ul ul,
|
|
146
|
+
.markdown-body ol ul ul {
|
|
147
|
+
list-style-type: square;
|
|
148
|
+
}
|
|
149
|
+
.markdown-body li + li {
|
|
150
|
+
margin-top: 0.25em;
|
|
151
|
+
}
|
|
152
|
+
/* remark-gfm task lists: the checkbox replaces the marker. */
|
|
153
|
+
.markdown-body li.task-list-item {
|
|
154
|
+
list-style-type: none;
|
|
155
|
+
}
|
|
156
|
+
.markdown-body ul.contains-task-list {
|
|
157
|
+
padding-left: 1.25em;
|
|
158
|
+
}
|
|
159
|
+
.markdown-body .task-list-item input[type="checkbox"] {
|
|
160
|
+
margin-right: 0.4em;
|
|
161
|
+
vertical-align: middle;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.markdown-body blockquote {
|
|
165
|
+
padding: 0 1em;
|
|
166
|
+
border-left: 0.25em solid var(--border);
|
|
167
|
+
color: var(--muted-foreground);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.markdown-body hr {
|
|
171
|
+
height: 0.25em;
|
|
172
|
+
margin: 1.5rem 0;
|
|
173
|
+
border: 0;
|
|
174
|
+
background-color: var(--border);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/* Tables scroll horizontally when wider than their container —
|
|
178
|
+
GitHub's own mechanism (block table, max-content width), which
|
|
179
|
+
needs no wrapper element around the <table>. */
|
|
180
|
+
.markdown-body table {
|
|
181
|
+
display: block;
|
|
182
|
+
width: max-content;
|
|
183
|
+
max-width: 100%;
|
|
184
|
+
overflow-x: auto;
|
|
185
|
+
border-collapse: collapse;
|
|
186
|
+
border-spacing: 0;
|
|
187
|
+
}
|
|
188
|
+
.markdown-body th,
|
|
189
|
+
.markdown-body td {
|
|
190
|
+
padding: 6px 13px;
|
|
191
|
+
border: 1px solid var(--border);
|
|
192
|
+
}
|
|
193
|
+
.markdown-body th {
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
background-color: var(--muted);
|
|
196
|
+
}
|
|
197
|
+
.markdown-body tbody tr:nth-child(2n) {
|
|
198
|
+
background-color: color-mix(in oklab, var(--muted) 50%, transparent);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/* A document's frontmatter, as a metadata grid (T-240). It is a `<table>`
|
|
202
|
+
so that anything reading the tree as tables gets one, and it must not
|
|
203
|
+
look like one: the keys are syntax, not a header row, so they get mono at
|
|
204
|
+
small size in the muted tone while the values keep body typography.
|
|
205
|
+
|
|
206
|
+
Grid rather than table layout for one concrete reason: `.markdown-body
|
|
207
|
+
table` above is `width: max-content`, which would let a long value push
|
|
208
|
+
the grid into its own horizontal scrollbar. `minmax(0, 1fr)` on the value
|
|
209
|
+
column caps it at the container instead, and `subgrid` is what still
|
|
210
|
+
aligns every key against every other. */
|
|
211
|
+
.markdown-body table.markdown-frontmatter {
|
|
212
|
+
display: grid;
|
|
213
|
+
grid-template-columns: max-content minmax(0, 1fr);
|
|
214
|
+
width: 100%;
|
|
215
|
+
overflow-x: visible;
|
|
216
|
+
border: 1px solid var(--border);
|
|
217
|
+
border-radius: var(--radius-sm);
|
|
218
|
+
background-color: color-mix(in oklab, var(--muted) 45%, transparent);
|
|
219
|
+
font-size: 0.9375em;
|
|
220
|
+
}
|
|
221
|
+
.markdown-body table.markdown-frontmatter tbody,
|
|
222
|
+
.markdown-body table.markdown-frontmatter tr {
|
|
223
|
+
display: grid;
|
|
224
|
+
grid-column: 1 / -1;
|
|
225
|
+
grid-template-columns: subgrid;
|
|
226
|
+
}
|
|
227
|
+
/* The striping above counts rows; here every row is a field and reads better
|
|
228
|
+
separated by a hairline than by alternating fills. */
|
|
229
|
+
.markdown-body table.markdown-frontmatter tbody tr {
|
|
230
|
+
background-color: transparent;
|
|
231
|
+
}
|
|
232
|
+
.markdown-body table.markdown-frontmatter tr + tr {
|
|
233
|
+
border-top: 1px solid color-mix(in oklab, var(--border) 60%, transparent);
|
|
234
|
+
}
|
|
235
|
+
.markdown-body table.markdown-frontmatter th,
|
|
236
|
+
.markdown-body table.markdown-frontmatter td {
|
|
237
|
+
border: 0;
|
|
238
|
+
padding: 0.2rem 0.6rem;
|
|
239
|
+
text-align: left;
|
|
240
|
+
font-weight: 400;
|
|
241
|
+
background-color: transparent;
|
|
242
|
+
}
|
|
243
|
+
/* `--font-mono` is Tailwind's theme default rather than an @orz/ui token,
|
|
244
|
+
and Tailwind only emits it when something uses it — hence the fallback. */
|
|
245
|
+
.markdown-body table.markdown-frontmatter th {
|
|
246
|
+
font-family: var(--font-mono, ui-monospace, monospace);
|
|
247
|
+
font-size: 0.8125em;
|
|
248
|
+
line-height: 1.7;
|
|
249
|
+
color: var(--muted-foreground);
|
|
250
|
+
white-space: nowrap;
|
|
251
|
+
}
|
|
252
|
+
/* Indentation and line breaks are the whole of what a nested map or a block
|
|
253
|
+
scalar shows, since the value is never parsed (T-240). */
|
|
254
|
+
.markdown-body table.markdown-frontmatter td {
|
|
255
|
+
white-space: pre-wrap;
|
|
256
|
+
}
|
|
257
|
+
/* A field with no key at all — TOML's `[section]`, or a line ahead of the
|
|
258
|
+
first field. Its key cell exists so a reader of the table still sees two
|
|
259
|
+
columns, and spans away here so the row reads as the full-width line it
|
|
260
|
+
is. */
|
|
261
|
+
.markdown-body table.markdown-frontmatter th:empty {
|
|
262
|
+
display: none;
|
|
263
|
+
}
|
|
264
|
+
.markdown-body table.markdown-frontmatter th:empty + td {
|
|
265
|
+
grid-column: 1 / -1;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.markdown-body img {
|
|
269
|
+
max-width: 100%;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Code styling stays intentionally shallow: a registered renderer usually
|
|
273
|
+
replaces the <pre>, so these rules only carry the unrendered fallback
|
|
274
|
+
(T-31). */
|
|
275
|
+
.markdown-body code {
|
|
276
|
+
padding: 0.2em 0.4em;
|
|
277
|
+
border-radius: var(--radius-sm);
|
|
278
|
+
background-color: var(--muted);
|
|
279
|
+
font-size: 0.85em;
|
|
280
|
+
}
|
|
281
|
+
.markdown-body pre {
|
|
282
|
+
padding: 0.75rem;
|
|
283
|
+
border-radius: var(--radius-md);
|
|
284
|
+
background-color: var(--muted);
|
|
285
|
+
overflow-x: auto;
|
|
286
|
+
line-height: 1.45;
|
|
287
|
+
}
|
|
288
|
+
.markdown-body pre code {
|
|
289
|
+
padding: 0;
|
|
290
|
+
border-radius: 0;
|
|
291
|
+
background-color: transparent;
|
|
292
|
+
}
|
|
293
|
+
}
|