@wsxjs/wsx-marked-components 0.0.18

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 ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "@wsxjs/wsx-marked-components",
3
+ "version": "0.0.18",
4
+ "description": "Markdown rendering components built with WSXJS for marked library",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "src",
17
+ "!**/__tests__",
18
+ "!**/test"
19
+ ],
20
+ "dependencies": {
21
+ "marked": "^12.0.0",
22
+ "@wsxjs/wsx-core": "0.0.18",
23
+ "@wsxjs/wsx-logger": "0.0.18"
24
+ },
25
+ "devDependencies": {
26
+ "@typescript-eslint/eslint-plugin": "^8.37.0",
27
+ "@typescript-eslint/parser": "^8.37.0",
28
+ "eslint": "^9.31.0",
29
+ "tsup": "^8.0.0",
30
+ "typescript": "^5.0.0",
31
+ "vite": "^5.4.19",
32
+ "@wsxjs/eslint-plugin-wsx": "0.0.18",
33
+ "@wsxjs/wsx-vite-plugin": "0.0.18"
34
+ },
35
+ "keywords": [
36
+ "wsx",
37
+ "web-components",
38
+ "markdown",
39
+ "marked",
40
+ "typescript",
41
+ "jsx"
42
+ ],
43
+ "author": "WSXJS Team",
44
+ "license": "MIT",
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/wsxjs/wsxjs.git",
48
+ "directory": "packages/marked-components"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public"
52
+ },
53
+ "scripts": {
54
+ "build": "vite build",
55
+ "build:dev": "NODE_ENV=development vite build",
56
+ "dev": "NODE_ENV=development vite build --watch",
57
+ "clean": "rm -rf dist",
58
+ "typecheck": "tsc --noEmit",
59
+ "lint": "eslint .",
60
+ "lint:fix": "eslint . --fix"
61
+ }
62
+ }
@@ -0,0 +1,12 @@
1
+ /* WSX Marked Blockquote Component Styles */
2
+ wsx-marked-blockquote {
3
+ display: block;
4
+ margin: 1rem 0;
5
+ padding: 1rem 1.5rem;
6
+ border-left: 4px solid var(--primary-red, #dc2626);
7
+ background: var(--bg-secondary, #f9f9f9);
8
+ border-radius: 4px;
9
+ font-style: italic;
10
+ color: var(--text-secondary, #666);
11
+ }
12
+
@@ -0,0 +1,26 @@
1
+ /** @jsxImportSource @wsxjs/wsx-core */
2
+ /**
3
+ * WSX Blockquote Component
4
+ * Custom blockquote component for markdown rendering
5
+ */
6
+
7
+ import { LightComponent, autoRegister } from "@wsxjs/wsx-core";
8
+ import styles from "./Blockquote.css?inline";
9
+
10
+ @autoRegister({ tagName: "wsx-marked-blockquote" })
11
+ export default class Blockquote extends LightComponent {
12
+ constructor() {
13
+ super({
14
+ styles,
15
+ styleName: "wsx-marked-blockquote",
16
+ });
17
+ }
18
+
19
+ render() {
20
+ return (
21
+ <blockquote>
22
+ <slot />
23
+ </blockquote>
24
+ );
25
+ }
26
+ }
package/src/Code.css ADDED
@@ -0,0 +1,34 @@
1
+ /* WSX Marked Code Component Styles */
2
+ wsx-marked-code {
3
+ display: block;
4
+ margin: 1rem 0;
5
+ }
6
+
7
+ wsx-marked-code pre {
8
+ background: var(--bg-secondary, #f5f5f5);
9
+ border: 1px solid var(--border-color, #e0e0e0);
10
+ border-radius: 8px;
11
+ padding: 1rem;
12
+ overflow-x: auto;
13
+ font-family: "Courier New", monospace;
14
+ font-size: 0.9rem;
15
+ line-height: 1.5;
16
+ }
17
+
18
+ wsx-marked-code code {
19
+ background: transparent;
20
+ padding: 0;
21
+ border: none;
22
+ font-family: inherit;
23
+ }
24
+
25
+ wsx-marked-code .language-label {
26
+ display: inline-block;
27
+ background: var(--primary-red, #dc2626);
28
+ color: white;
29
+ padding: 0.25rem 0.5rem;
30
+ font-size: 0.75rem;
31
+ border-radius: 4px 4px 0 0;
32
+ margin-bottom: -1px;
33
+ }
34
+
package/src/Code.wsx ADDED
@@ -0,0 +1,46 @@
1
+ /** @jsxImportSource @wsxjs/wsx-core */
2
+ /**
3
+ * WSX Code Component
4
+ * Custom code block component for markdown rendering
5
+ */
6
+
7
+ import { LightComponent, autoRegister } from "@wsxjs/wsx-core";
8
+ import styles from "./Code.css?inline";
9
+
10
+ @autoRegister({ tagName: "wsx-marked-code" })
11
+ export default class Code extends LightComponent {
12
+ private code: string = "";
13
+ private language: string = "";
14
+
15
+ constructor() {
16
+ super({
17
+ styles,
18
+ styleName: "wsx-marked-code",
19
+ });
20
+ }
21
+
22
+ static get observedAttributes() {
23
+ return ["code", "language"];
24
+ }
25
+
26
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
27
+ if (name === "code") {
28
+ this.code = newValue || "";
29
+ } else if (name === "language") {
30
+ this.language = newValue || "";
31
+ }
32
+ this.rerender();
33
+ }
34
+
35
+ render() {
36
+ return (
37
+ <div>
38
+ {this.language && <span class="language-label">{this.language}</span>}
39
+ <pre>
40
+ <code>{this.code}</code>
41
+ </pre>
42
+ </div>
43
+ );
44
+ }
45
+ }
46
+
package/src/Error.wsx ADDED
@@ -0,0 +1,34 @@
1
+ /** @jsxImportSource @wsxjs/wsx-core */
2
+ /**
3
+ * WSX Error Component
4
+ * Custom error component for markdown rendering
5
+ */
6
+
7
+ import { LightComponent, autoRegister } from "@wsxjs/wsx-core";
8
+
9
+ @autoRegister({ tagName: "wsx-marked-error" })
10
+ export default class Error extends LightComponent {
11
+ private message: string = "";
12
+
13
+ constructor() {
14
+ super({
15
+ styleName: "wsx-marked-error",
16
+ });
17
+ }
18
+
19
+ static get observedAttributes() {
20
+ return ["message"];
21
+ }
22
+
23
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
24
+ if (name === "message") {
25
+ this.message = newValue || "";
26
+ this.rerender();
27
+ }
28
+ }
29
+
30
+ render() {
31
+ return <div class="error">{this.message}</div>;
32
+ }
33
+ }
34
+
@@ -0,0 +1,37 @@
1
+ /* WSX Marked Heading Component Styles */
2
+ wsx-marked-heading {
3
+ display: block;
4
+ }
5
+
6
+ wsx-marked-heading h1 {
7
+ font-size: 2.5rem;
8
+ font-weight: 700;
9
+ margin: 1.5rem 0 1rem 0;
10
+ color: var(--text-primary, #2c3e50);
11
+ border-bottom: 2px solid var(--primary-red, #dc2626);
12
+ padding-bottom: 0.5rem;
13
+ }
14
+
15
+ wsx-marked-heading h2 {
16
+ font-size: 2rem;
17
+ font-weight: 600;
18
+ margin: 1.25rem 0 0.75rem 0;
19
+ color: var(--text-primary, #2c3e50);
20
+ }
21
+
22
+ wsx-marked-heading h3 {
23
+ font-size: 1.5rem;
24
+ font-weight: 600;
25
+ margin: 1rem 0 0.5rem 0;
26
+ color: var(--text-primary, #2c3e50);
27
+ }
28
+
29
+ wsx-marked-heading h4,
30
+ wsx-marked-heading h5,
31
+ wsx-marked-heading h6 {
32
+ font-size: 1.25rem;
33
+ font-weight: 600;
34
+ margin: 0.75rem 0 0.5rem 0;
35
+ color: var(--text-primary, #2c3e50);
36
+ }
37
+
@@ -0,0 +1,44 @@
1
+ /** @jsxImportSource @wsxjs/wsx-core */
2
+ /**
3
+ * WSX Heading Component
4
+ * Custom heading component for markdown rendering
5
+ */
6
+
7
+ import { LightComponent, autoRegister } from "@wsxjs/wsx-core";
8
+ import styles from "./Heading.css?inline";
9
+
10
+ @autoRegister({ tagName: "wsx-marked-heading" })
11
+ export default class Heading extends LightComponent {
12
+ private level: number = 1;
13
+ private text: string = "";
14
+
15
+ constructor() {
16
+ super({
17
+ styles,
18
+ styleName: "wsx-marked-heading",
19
+ });
20
+ }
21
+
22
+ static get observedAttributes() {
23
+ return ["level", "text"];
24
+ }
25
+
26
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
27
+ if (name === "level") {
28
+ this.level = parseInt(newValue, 10) || 1;
29
+ } else if (name === "text") {
30
+ this.text = newValue;
31
+ }
32
+ this.rerender();
33
+ }
34
+
35
+ render() {
36
+ // 使用 WSX JSX 语法,根据 level 渲染对应的标题
37
+ if (this.level === 1) return <h1>{this.text}</h1>;
38
+ if (this.level === 2) return <h2>{this.text}</h2>;
39
+ if (this.level === 3) return <h3>{this.text}</h3>;
40
+ if (this.level === 4) return <h4>{this.text}</h4>;
41
+ if (this.level === 5) return <h5>{this.text}</h5>;
42
+ return <h6>{this.text}</h6>;
43
+ }
44
+ }
package/src/List.wsx ADDED
@@ -0,0 +1,67 @@
1
+ /** @jsxImportSource @wsxjs/wsx-core */
2
+ /**
3
+ * WSX List Component
4
+ * Custom list component for markdown rendering
5
+ */
6
+
7
+ import { LightComponent, autoRegister, state } from "@wsxjs/wsx-core";
8
+
9
+ @autoRegister({ tagName: "wsx-marked-list" })
10
+ export default class List extends LightComponent {
11
+ @state private ordered: boolean = false;
12
+ @state private items: string[] = [];
13
+
14
+ constructor() {
15
+ super({
16
+ styleName: "wsx-marked-list",
17
+ });
18
+ }
19
+
20
+ static get observedAttributes() {
21
+ return ["ordered", "items"];
22
+ }
23
+
24
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
25
+ if (name === "ordered") {
26
+ this.ordered = newValue === "true";
27
+ } else if (name === "items") {
28
+ try {
29
+ // HTML 属性值会被浏览器自动解码,所以这里得到的是原始的 JSON 字符串
30
+ // JSON.parse 会解析出包含 HTML 字符串的数组
31
+ this.items = JSON.parse(newValue || "[]");
32
+ } catch {
33
+ this.items = [];
34
+ }
35
+ }
36
+ }
37
+
38
+ render() {
39
+ if (this.ordered) {
40
+ return (
41
+ <ol class="marked-list">
42
+ {this.items.map((item, index) => {
43
+ // JSX factory automatically detects HTML strings and converts them to DOM nodes
44
+ return (
45
+ <li key={index} class="marked-list-item">
46
+ {item}
47
+ </li>
48
+ );
49
+ })}
50
+ </ol>
51
+ );
52
+ } else {
53
+ return (
54
+ <ul class="marked-list">
55
+ {this.items.map((item, index) => {
56
+ // JSX factory automatically detects HTML strings and converts them to DOM nodes
57
+ return (
58
+ <li key={index} class="marked-list-item">
59
+ {item}
60
+ </li>
61
+ );
62
+ })}
63
+ </ul>
64
+ );
65
+ }
66
+ }
67
+ }
@@ -0,0 +1,66 @@
1
+ /* WSX Markdown Component Styles */
2
+ wsx-markdown {
3
+ display: block;
4
+ }
5
+
6
+ .marked-content {
7
+ line-height: 1.7;
8
+ color: var(--text-primary, #2c3e50);
9
+ }
10
+
11
+ .marked-content .marked-paragraph {
12
+ margin: 1rem 0;
13
+ line-height: 1.7;
14
+ }
15
+
16
+ .marked-content .marked-list {
17
+ margin: 1rem 0;
18
+ padding-left: 2rem;
19
+ }
20
+
21
+ .marked-content .marked-list-item {
22
+ margin: 0.5rem 0;
23
+ line-height: 1.6;
24
+ }
25
+
26
+ .marked-content a {
27
+ color: var(--primary-red, #dc2626);
28
+ text-decoration: none;
29
+ border-bottom: 1px solid transparent;
30
+ transition: border-color 0.2s ease;
31
+ }
32
+
33
+ .marked-content a:hover {
34
+ border-bottom-color: var(--primary-red, #dc2626);
35
+ }
36
+
37
+ .marked-content strong {
38
+ font-weight: 600;
39
+ color: var(--text-primary, #2c3e50);
40
+ }
41
+
42
+ .marked-content em {
43
+ font-style: italic;
44
+ }
45
+
46
+ .marked-content hr {
47
+ border: none;
48
+ border-top: 2px solid var(--border-color, #e0e0e0);
49
+ margin: 2rem 0;
50
+ }
51
+
52
+ .marked-content img {
53
+ max-width: 100%;
54
+ height: auto;
55
+ border-radius: 8px;
56
+ margin: 1rem 0;
57
+ }
58
+
59
+ .error {
60
+ color: #dc2626;
61
+ padding: 1rem;
62
+ background: #fee2e2;
63
+ border-radius: 6px;
64
+ border: 1px solid #fecaca;
65
+ }
66
+