@wsxjs/wsx-marked-components 0.0.27 → 0.0.30
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/dist/index.cjs +3 -3
- package/dist/index.js +451 -447
- package/package.json +5 -5
- package/src/Markdown.wsx +28 -15
- package/src/marked-utils.ts +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wsxjs/wsx-marked-components",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.30",
|
|
4
4
|
"description": "Markdown rendering components built with WSXJS for marked library",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"marked": "^12.0.0",
|
|
22
22
|
"prismjs": "^1.30.0",
|
|
23
|
-
"@wsxjs/wsx-
|
|
24
|
-
"@wsxjs/wsx-
|
|
23
|
+
"@wsxjs/wsx-core": "0.0.30",
|
|
24
|
+
"@wsxjs/wsx-logger": "0.0.30"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/prismjs": "^1.26.5",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"tsup": "^8.0.0",
|
|
32
32
|
"typescript": "^5.0.0",
|
|
33
33
|
"vite": "^5.4.19",
|
|
34
|
-
"@wsxjs/
|
|
35
|
-
"@wsxjs/
|
|
34
|
+
"@wsxjs/wsx-vite-plugin": "0.0.30",
|
|
35
|
+
"@wsxjs/eslint-plugin-wsx": "0.0.30"
|
|
36
36
|
},
|
|
37
37
|
"keywords": [
|
|
38
38
|
"wsx",
|
package/src/Markdown.wsx
CHANGED
|
@@ -11,7 +11,13 @@
|
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
LightComponent,
|
|
16
|
+
autoRegister,
|
|
17
|
+
state,
|
|
18
|
+
type JSXChildren,
|
|
19
|
+
parseHTMLToNodes,
|
|
20
|
+
} from "@wsxjs/wsx-core";
|
|
15
21
|
import { createLogger } from "@wsxjs/wsx-logger";
|
|
16
22
|
import { marked } from "marked";
|
|
17
23
|
import type { Tokens } from "marked";
|
|
@@ -111,21 +117,19 @@ export default class Markdown extends LightComponent {
|
|
|
111
117
|
/**
|
|
112
118
|
* Convert marked tokens to WSX JSX elements
|
|
113
119
|
*/
|
|
114
|
-
private renderTokens(tokens: Tokens.Generic[]):
|
|
115
|
-
return tokens
|
|
116
|
-
.map((token) => this.renderToken(token))
|
|
117
|
-
.filter((el): el is HTMLElement => el !== null);
|
|
120
|
+
private renderTokens(tokens: Tokens.Generic[]): JSXChildren[] {
|
|
121
|
+
return tokens.map((token) => this.renderToken(token)).filter((el) => el !== null);
|
|
118
122
|
}
|
|
119
123
|
|
|
120
124
|
/**
|
|
121
125
|
* Render a single token to WSX JSX element
|
|
122
126
|
* Supports custom renderers for extensibility
|
|
123
127
|
*/
|
|
124
|
-
private renderToken(token: Tokens.Generic):
|
|
128
|
+
private renderToken(token: Tokens.Generic): JSXChildren {
|
|
125
129
|
// Check for custom renderer first
|
|
126
130
|
const customRenderer = this.customRenderers[token.type];
|
|
127
131
|
if (customRenderer) {
|
|
128
|
-
const result = customRenderer(token, () => this.defaultRenderToken(token));
|
|
132
|
+
const result = customRenderer(token, () => this.defaultRenderToken(token) as any);
|
|
129
133
|
if (result !== null) {
|
|
130
134
|
return result;
|
|
131
135
|
}
|
|
@@ -139,7 +143,7 @@ export default class Markdown extends LightComponent {
|
|
|
139
143
|
* Default token rendering logic
|
|
140
144
|
* This is the core rendering implementation
|
|
141
145
|
*/
|
|
142
|
-
private defaultRenderToken(token: Tokens.Generic):
|
|
146
|
+
private defaultRenderToken(token: Tokens.Generic): JSXChildren {
|
|
143
147
|
switch (token.type) {
|
|
144
148
|
case "heading": {
|
|
145
149
|
const headingToken = token as Tokens.Heading;
|
|
@@ -195,7 +199,13 @@ export default class Markdown extends LightComponent {
|
|
|
195
199
|
const tempContainer = document.createElement("div");
|
|
196
200
|
renderedElements.forEach((el) => {
|
|
197
201
|
if (el) {
|
|
198
|
-
|
|
202
|
+
if (typeof el === "string" || typeof el === "number") {
|
|
203
|
+
tempContainer.appendChild(document.createTextNode(String(el)));
|
|
204
|
+
} else if (el instanceof HTMLElement || el instanceof SVGElement) {
|
|
205
|
+
tempContainer.appendChild(el.cloneNode(true));
|
|
206
|
+
} else if (el instanceof DocumentFragment) {
|
|
207
|
+
tempContainer.appendChild(el.cloneNode(true));
|
|
208
|
+
}
|
|
199
209
|
}
|
|
200
210
|
});
|
|
201
211
|
const html = tempContainer.innerHTML;
|
|
@@ -215,7 +225,8 @@ export default class Markdown extends LightComponent {
|
|
|
215
225
|
|
|
216
226
|
case "html": {
|
|
217
227
|
const htmlToken = token as Tokens.HTML;
|
|
218
|
-
|
|
228
|
+
// 使用 Fragment 包裹解析后的节点,支持 Raw HTML
|
|
229
|
+
return <>{parseHTMLToNodes(htmlToken.text)}</>;
|
|
219
230
|
}
|
|
220
231
|
|
|
221
232
|
case "hr": {
|
|
@@ -228,23 +239,25 @@ export default class Markdown extends LightComponent {
|
|
|
228
239
|
}
|
|
229
240
|
|
|
230
241
|
case "text": {
|
|
231
|
-
// Text tokens are inline tokens
|
|
232
|
-
// render them directly as text nodes wrapped in a span
|
|
242
|
+
// Text tokens are inline tokens
|
|
233
243
|
const textToken = token as Tokens.Text;
|
|
234
|
-
|
|
244
|
+
if (textToken.tokens && textToken.tokens.length > 0) {
|
|
245
|
+
return <>{this.renderTokens(textToken.tokens)}</>;
|
|
246
|
+
}
|
|
247
|
+
return textToken.text || "";
|
|
235
248
|
}
|
|
236
249
|
|
|
237
250
|
default: {
|
|
238
251
|
// For other types, use default marked renderer
|
|
239
|
-
// Note: marked.Renderer() only handles block-level tokens, not inline tokens
|
|
240
252
|
const renderer = new marked.Renderer();
|
|
241
253
|
const renderMethod = (
|
|
242
254
|
renderer as unknown as Record<string, (token: unknown) => string>
|
|
243
255
|
)[token.type];
|
|
244
256
|
const html = renderMethod?.(token) || "";
|
|
245
257
|
if (html) {
|
|
246
|
-
return
|
|
258
|
+
return <>{parseHTMLToNodes(html)}</>;
|
|
247
259
|
}
|
|
260
|
+
logger.warn(`[WSX-Markdown] Unknown token type: ${token.type}`);
|
|
248
261
|
return null;
|
|
249
262
|
}
|
|
250
263
|
}
|
package/src/marked-utils.ts
CHANGED
|
@@ -41,6 +41,7 @@ export function extractInlineTokens(tokens: Tokens.Generic[] | undefined): Token
|
|
|
41
41
|
token.type === "em" ||
|
|
42
42
|
token.type === "link" ||
|
|
43
43
|
token.type === "code" ||
|
|
44
|
+
token.type === "codespan" ||
|
|
44
45
|
token.type === "br"
|
|
45
46
|
) {
|
|
46
47
|
// If it's already an inline token, add it directly
|
|
@@ -98,6 +99,10 @@ export function renderInlineTokens(tokens: Tokens.Generic[] | undefined): string
|
|
|
98
99
|
const codeToken = token as Tokens.Code;
|
|
99
100
|
return `<code>${escapeHtml(codeToken.text || "")}</code>`;
|
|
100
101
|
}
|
|
102
|
+
case "codespan": {
|
|
103
|
+
const codeToken = token as Tokens.Codespan;
|
|
104
|
+
return `<code>${escapeHtml(codeToken.text || "")}</code>`;
|
|
105
|
+
}
|
|
101
106
|
case "br": {
|
|
102
107
|
return "<br>";
|
|
103
108
|
}
|