@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wsxjs/wsx-marked-components",
3
- "version": "0.0.27",
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-logger": "0.0.27",
24
- "@wsxjs/wsx-core": "0.0.27"
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/eslint-plugin-wsx": "0.0.27",
35
- "@wsxjs/wsx-vite-plugin": "0.0.27"
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 { LightComponent, autoRegister, state } from "@wsxjs/wsx-core";
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[]): (HTMLElement | null)[] {
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): HTMLElement | null {
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): HTMLElement | null {
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
- tempContainer.appendChild(el);
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
- return <div>{htmlToken.text}</div>;
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, but if they appear as top-level 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
- return <span>{textToken.text || ""}</span>;
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 <div>{html}</div>;
258
+ return <>{parseHTMLToNodes(html)}</>;
247
259
  }
260
+ logger.warn(`[WSX-Markdown] Unknown token type: ${token.type}`);
248
261
  return null;
249
262
  }
250
263
  }
@@ -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
  }