c063 1.4.9 → 1.5.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.
@@ -7,7 +7,7 @@ import { AsComponentProps, OverrideProps } from "./common";
7
7
  *
8
8
  * 類型分為以下幾大類:
9
9
  *
10
- * - `keyword1` / `keyword2`: 關鍵字,如 `const`、`return`、`import` 等,分顏色類別。
10
+ * - `keyword1` / `keyword2`: 關鍵字,如 `const`/`return`、`import` 等,分顏色類別。
11
11
  * - `string`: 字串常值,如 `'text'`、`"value"`。
12
12
  * - `number`: 數字常值,如 `123`、`3.14`。
13
13
  * - `comment`: 註解內容,如 `//`。
@@ -80,13 +80,13 @@ export type CodeBlockProps<T extends React.ElementType> = OverrideProps<React.HT
80
80
  * ```tsx
81
81
  * <CodeBlock tokenLines={[
82
82
  * [
83
- * { type: "keyword-blue", children: "const" },
83
+ * { type: "keyword1", children: "const" },
84
84
  * { type: "variable", children: "x" },
85
85
  * { type: "operator", children: "=" },
86
86
  * { type: "number", children: "42" },
87
87
  * ],
88
88
  * [
89
- * { type: "keyword-purple", children: "return" },
89
+ * { type: "keyword2", children: "return" },
90
90
  * { type: "variable", children: "x" },
91
91
  * ],
92
92
  * ]} />
@@ -109,7 +109,7 @@ export type CodeBlockProps<T extends React.ElementType> = OverrideProps<React.HT
109
109
  lineNumberStyle?: React.CSSProperties;
110
110
  /**
111
111
  * 語法主題名稱。
112
- * @default "vscode-dark"
112
+ * @default "default-dark-modern"
113
113
  */
114
114
  theme?: CodeTheme;
115
115
  }>;
@@ -1,31 +1,56 @@
1
1
  import React from "react";
2
2
  import { CodeTokenBuilder, CodeTokenProps, CodeTokenType } from "../types";
3
3
  /**
4
- * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等),
5
- * 透過 Proxy 生成對應的 `CodeTokenBuilder`。
4
+ * `c063` 是一組語法高亮 token 建構器集合。
5
+ * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等),
6
+ * 回傳對應的 `CodeTokenProps` 物件。
6
7
  *
7
- * 使用方式:
8
+ * @example
8
9
  * ```tsx
9
- * c063.keyword1("const") // -> { type: "keyword1", children: "const" }
10
- * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props
10
+ * const keyword = c063.keyword1("const");
11
+ * const str = c063.string("'Hello'", { as: "code" });
11
12
  * ```
12
13
  *
13
- * @example
14
- * tokens.push(c063.keyword1("const"));
15
- * tokens.push(c063.string("'Hello'"));
16
- *
17
- * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合
14
+ * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。
18
15
  */
19
16
  declare const c063: Record<CodeTokenType, CodeTokenBuilder>;
17
+ export default c063;
20
18
  /**
21
- * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。
19
+ * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。
22
20
  *
23
21
  * @param count 空白字元數,預設為 1
24
- * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串
22
+ * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps`
25
23
  *
26
24
  * @example
25
+ * ```tsx
27
26
  * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " }
27
+ * ```
28
28
  */
29
29
  export declare const whiteSpace: (count?: number) => CodeTokenProps<"span">;
30
+ /**
31
+ * 抽取單個 `CodeTokenProps` 的純文字內容。
32
+ *
33
+ * @param token 要處理的 token
34
+ * @returns 對應的文字內容
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * extractTokenContent(c063.keyword1("return")); // => "return"
39
+ * ```
40
+ */
30
41
  export declare const extractTokenContent: <T extends React.ElementType>(token: CodeTokenProps<T>) => string;
31
- export default c063;
42
+ /**
43
+ * 判斷兩個 token 是否相等(type 與內容皆相同)。
44
+ *
45
+ * @param a 第一個 token
46
+ * @param b 第二個 token
47
+ * @returns 是否相等
48
+ */
49
+ export declare const isTokenEqual: <T extends React.ElementType>(a: CodeTokenProps<T>, b: CodeTokenProps<T>) => boolean;
50
+ /**
51
+ * 將 token 列表按語法類型分類。
52
+ *
53
+ * @param lines 二維陣列,每行為一組 token
54
+ * @returns 分組後的 token 映射,key 為 `CodeTokenType`
55
+ */
56
+ export declare const groupTokensByType: <T extends React.ElementType>(lines: CodeTokenProps<T>[][]) => Record<CodeTokenType, CodeTokenProps<T>[]>;
@@ -1,22 +1,26 @@
1
1
  import React from "react";
2
2
  /**
3
- * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等),
4
- * 透過 Proxy 生成對應的 `CodeTokenBuilder`。
3
+ * `c063` 是一組語法高亮 token 建構器集合。
4
+ * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等),
5
+ * 回傳對應的 `CodeTokenProps` 物件。
5
6
  *
6
- * 使用方式:
7
+ * @example
7
8
  * ```tsx
8
- * c063.keyword1("const") // -> { type: "keyword1", children: "const" }
9
- * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props
9
+ * const keyword = c063.keyword1("const");
10
+ * const str = c063.string("'Hello'", { as: "code" });
10
11
  * ```
11
12
  *
12
- * @example
13
- * tokens.push(c063.keyword1("const"));
14
- * tokens.push(c063.string("'Hello'"));
15
- *
16
- * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合
13
+ * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。
17
14
  */
18
15
  const c063 = new Proxy({}, {
19
16
  get: (_, prop) => {
17
+ /**
18
+ * 建立指定語法類型的 CodeToken。
19
+ *
20
+ * @param children 要包裹的 React 內容或字串
21
+ * @param props 可選的額外屬性,如 `as` 或 `className`
22
+ * @returns 一個 CodeToken 物件
23
+ */
20
24
  const builder = (children, props) => {
21
25
  return {
22
26
  children,
@@ -27,39 +31,113 @@ const c063 = new Proxy({}, {
27
31
  return builder;
28
32
  },
29
33
  });
34
+ export default c063;
30
35
  /**
31
- * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。
36
+ * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。
32
37
  *
33
38
  * @param count 空白字元數,預設為 1
34
- * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串
39
+ * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps`
35
40
  *
36
41
  * @example
42
+ * ```tsx
37
43
  * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " }
44
+ * ```
38
45
  */
39
46
  export const whiteSpace = (count = 1) => c063.default(" ".repeat(count));
47
+ /**
48
+ * 遞迴抽取 ReactNode 中的純文字內容。
49
+ *
50
+ * @param children ReactNode,可以是字串、數字、JSX 元素、陣列等
51
+ * @returns 純文字內容字串
52
+ */
53
+ const _extractReactNode = (children) => {
54
+ if (typeof children === "string")
55
+ return children;
56
+ if (typeof children === "number")
57
+ return children.toString();
58
+ if (Array.isArray(children))
59
+ return children.map(_extractReactNode).join("");
60
+ if (React.isValidElement(children)) {
61
+ return _extractReactNode(children.props.children);
62
+ }
63
+ if (typeof children === "object" && children !== null) {
64
+ return React.Children.toArray(children).map(_extractReactNode).join("");
65
+ }
66
+ return ""; // 如果 children 是 null 或 undefined,則返回空字串
67
+ };
68
+ /**
69
+ * 抽取單個 `CodeTokenProps` 的純文字內容。
70
+ *
71
+ * @param token 要處理的 token
72
+ * @returns 對應的文字內容
73
+ *
74
+ * @example
75
+ * ```tsx
76
+ * extractTokenContent(c063.keyword1("return")); // => "return"
77
+ * ```
78
+ */
40
79
  export const extractTokenContent = (token) => {
41
- const _extract = (children) => {
42
- if (typeof children === "string")
43
- return children;
44
- if (typeof children === "number")
45
- return children.toString();
46
- if (Array.isArray(children))
47
- return children.map(_extract).join("");
48
- if (React.isValidElement(children)) {
49
- return _extract(children.props.children);
50
- }
51
- return ""; // 如果 children null 或 undefined,則返回空字串
80
+ return _extractReactNode(token.children);
81
+ };
82
+ /**
83
+ * 判斷兩個 token 是否相等(type 與內容皆相同)。
84
+ *
85
+ * @param a 第一個 token
86
+ * @param b 第二個 token
87
+ * @returns 是否相等
88
+ */
89
+ export const isTokenEqual = (a, b) => {
90
+ return a.type === b.type && extractTokenContent(a) === extractTokenContent(b);
91
+ };
92
+ /**
93
+ * 將 token 列表按語法類型分類。
94
+ *
95
+ * @param lines 二維陣列,每行為一組 token
96
+ * @returns 分組後的 token 映射,key 為 `CodeTokenType`
97
+ */
98
+ export const groupTokensByType = (lines) => {
99
+ var _a;
100
+ const grouped = {
101
+ keyword1: [],
102
+ keyword2: [],
103
+ function: [],
104
+ string: [],
105
+ number: [],
106
+ comment: [],
107
+ type: [],
108
+ variable: [],
109
+ constant: [],
110
+ brackets1: [],
111
+ brackets2: [],
112
+ brackets3: [],
113
+ operator: [],
114
+ default: [],
52
115
  };
53
- return _extract(token.children);
116
+ for (const token of lines.flat()) {
117
+ grouped[(_a = token.type) !== null && _a !== void 0 ? _a : "default"].push(token);
118
+ }
119
+ return grouped;
54
120
  };
55
- export default c063;
56
121
  /**
57
- * 待實現
122
+ * 待實作
123
+ * `parseTokens` 是語法解析器的代理集合,用來解析特定語言的程式碼字串。
124
+ *
125
+ * 每個 key 對應一種可解析語言(如 `"javascript"`、`"python"` 等),
126
+ * 傳入原始程式碼字串後,回傳解析後的 token 二維陣列(每行一組 token)。
127
+ *
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * const tokens = parseTokens.javascript("const x = 1;");
132
+ * ```
133
+ *
134
+ * @returns 語法高亮用的 `CodeTokenProps` 二維陣列
58
135
  */
59
- const _parseTokens = new Proxy({}, {
136
+ const parseTokens = new Proxy({}, {
60
137
  get: (_, prop) => {
61
138
  const parser = (content) => {
62
- return [];
139
+ const result = [];
140
+ return result;
63
141
  };
64
142
  return parser;
65
143
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "c063",
4
- "version": "1.4.9",
4
+ "version": "1.5.0",
5
5
  "description": "A React component for displaying code snippets with syntax highlighting.",
6
6
  "main": "dist/index.js",
7
7
  "types": "dist/index.d.ts",
@@ -7,7 +7,7 @@ import { AsComponentProps, OverrideProps } from "./common";
7
7
  *
8
8
  * 類型分為以下幾大類:
9
9
  *
10
- * - `keyword1` / `keyword2`: 關鍵字,如 `const`、`return`、`import` 等,分顏色類別。
10
+ * - `keyword1` / `keyword2`: 關鍵字,如 `const`/`return`、`import` 等,分顏色類別。
11
11
  * - `string`: 字串常值,如 `'text'`、`"value"`。
12
12
  * - `number`: 數字常值,如 `123`、`3.14`。
13
13
  * - `comment`: 註解內容,如 `//`。
@@ -107,13 +107,13 @@ export type CodeBlockProps<T extends React.ElementType> = OverrideProps<
107
107
  * ```tsx
108
108
  * <CodeBlock tokenLines={[
109
109
  * [
110
- * { type: "keyword-blue", children: "const" },
110
+ * { type: "keyword1", children: "const" },
111
111
  * { type: "variable", children: "x" },
112
112
  * { type: "operator", children: "=" },
113
113
  * { type: "number", children: "42" },
114
114
  * ],
115
115
  * [
116
- * { type: "keyword-purple", children: "return" },
116
+ * { type: "keyword2", children: "return" },
117
117
  * { type: "variable", children: "x" },
118
118
  * ],
119
119
  * ]} />
@@ -137,7 +137,7 @@ export type CodeBlockProps<T extends React.ElementType> = OverrideProps<
137
137
  lineNumberStyle?: React.CSSProperties;
138
138
  /**
139
139
  * 語法主題名稱。
140
- * @default "vscode-dark"
140
+ * @default "default-dark-modern"
141
141
  */
142
142
  theme?: CodeTheme;
143
143
  }
@@ -7,28 +7,32 @@ import {
7
7
  } from "../types";
8
8
 
9
9
  /**
10
- * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等),
11
- * 透過 Proxy 生成對應的 `CodeTokenBuilder`。
10
+ * `c063` 是一組語法高亮 token 建構器集合。
11
+ * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等),
12
+ * 回傳對應的 `CodeTokenProps` 物件。
12
13
  *
13
- * 使用方式:
14
+ * @example
14
15
  * ```tsx
15
- * c063.keyword1("const") // -> { type: "keyword1", children: "const" }
16
- * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props
16
+ * const keyword = c063.keyword1("const");
17
+ * const str = c063.string("'Hello'", { as: "code" });
17
18
  * ```
18
19
  *
19
- * @example
20
- * tokens.push(c063.keyword1("const"));
21
- * tokens.push(c063.string("'Hello'"));
22
- *
23
- * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合
20
+ * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。
24
21
  */
25
22
  const c063 = new Proxy(
26
23
  {},
27
24
  {
28
25
  get: (_, prop: CodeTokenType) => {
26
+ /**
27
+ * 建立指定語法類型的 CodeToken。
28
+ *
29
+ * @param children 要包裹的 React 內容或字串
30
+ * @param props 可選的額外屬性,如 `as` 或 `className`
31
+ * @returns 一個 CodeToken 物件
32
+ */
29
33
  const builder = <T extends React.ElementType = "span">(
30
34
  children: React.ReactNode,
31
- props: CodeTokenProps<T>
35
+ props?: CodeTokenProps<T>
32
36
  ) => {
33
37
  return {
34
38
  children,
@@ -40,45 +44,129 @@ const c063 = new Proxy(
40
44
  },
41
45
  }
42
46
  ) as Record<CodeTokenType, CodeTokenBuilder>;
47
+ export default c063;
43
48
 
44
49
  /**
45
- * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。
50
+ * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。
46
51
  *
47
52
  * @param count 空白字元數,預設為 1
48
- * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串
53
+ * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps`
49
54
  *
50
55
  * @example
56
+ * ```tsx
51
57
  * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " }
58
+ * ```
52
59
  */
53
60
  export const whiteSpace = (count: number = 1): CodeTokenProps<"span"> =>
54
61
  c063.default(" ".repeat(count));
55
62
 
63
+ /**
64
+ * 遞迴抽取 ReactNode 中的純文字內容。
65
+ *
66
+ * @param children ReactNode,可以是字串、數字、JSX 元素、陣列等
67
+ * @returns 純文字內容字串
68
+ */
69
+ const _extractReactNode = (children: React.ReactNode): string => {
70
+ if (typeof children === "string") return children;
71
+ if (typeof children === "number") return children.toString();
72
+ if (Array.isArray(children)) return children.map(_extractReactNode).join("");
73
+ if (React.isValidElement(children)) {
74
+ return _extractReactNode((children as React.JSX.Element).props.children);
75
+ }
76
+ if (typeof children === "object" && children !== null) {
77
+ return React.Children.toArray(children).map(_extractReactNode).join("");
78
+ }
79
+
80
+ return ""; // 如果 children 是 null 或 undefined,則返回空字串
81
+ };
82
+
83
+ /**
84
+ * 抽取單個 `CodeTokenProps` 的純文字內容。
85
+ *
86
+ * @param token 要處理的 token
87
+ * @returns 對應的文字內容
88
+ *
89
+ * @example
90
+ * ```tsx
91
+ * extractTokenContent(c063.keyword1("return")); // => "return"
92
+ * ```
93
+ */
56
94
  export const extractTokenContent = <T extends React.ElementType>(
57
95
  token: CodeTokenProps<T>
58
96
  ): string => {
59
- const _extract = (children: React.ReactNode): string => {
60
- if (typeof children === "string") return children;
61
- if (typeof children === "number") return children.toString();
62
- if (Array.isArray(children)) return children.map(_extract).join("");
63
- if (React.isValidElement(children)) {
64
- return _extract((children as React.JSX.Element).props.children);
65
- }
66
- return ""; // 如果 children 是 null 或 undefined,則返回空字串
67
- };
68
- return _extract(token.children);
97
+ return _extractReactNode(token.children);
69
98
  };
70
99
 
71
- export default c063;
100
+ /**
101
+ * 判斷兩個 token 是否相等(type 與內容皆相同)。
102
+ *
103
+ * @param a 第一個 token
104
+ * @param b 第二個 token
105
+ * @returns 是否相等
106
+ */
107
+ export const isTokenEqual = <T extends React.ElementType>(
108
+ a: CodeTokenProps<T>,
109
+ b: CodeTokenProps<T>
110
+ ): boolean => {
111
+ return a.type === b.type && extractTokenContent(a) === extractTokenContent(b);
112
+ };
72
113
 
73
114
  /**
74
- * 待實現
115
+ * 將 token 列表按語法類型分類。
116
+ *
117
+ * @param lines 二維陣列,每行為一組 token
118
+ * @returns 分組後的 token 映射,key 為 `CodeTokenType`
75
119
  */
76
- const _parseTokens = new Proxy(
120
+ export const groupTokensByType = <T extends React.ElementType>(
121
+ lines: CodeTokenProps<T>[][]
122
+ ): Record<CodeTokenType, CodeTokenProps<T>[]> => {
123
+ const grouped: Record<CodeTokenType, CodeTokenProps<T>[]> = {
124
+ keyword1: [],
125
+ keyword2: [],
126
+ function: [],
127
+ string: [],
128
+ number: [],
129
+ comment: [],
130
+ type: [],
131
+ variable: [],
132
+ constant: [],
133
+ brackets1: [],
134
+ brackets2: [],
135
+ brackets3: [],
136
+ operator: [],
137
+ default: [],
138
+ };
139
+
140
+ for (const token of lines.flat()) {
141
+ grouped[token.type ?? "default"].push(token);
142
+ }
143
+
144
+ return grouped;
145
+ };
146
+
147
+ /**
148
+ * 待實作
149
+ * `parseTokens` 是語法解析器的代理集合,用來解析特定語言的程式碼字串。
150
+ *
151
+ * 每個 key 對應一種可解析語言(如 `"javascript"`、`"python"` 等),
152
+ * 傳入原始程式碼字串後,回傳解析後的 token 二維陣列(每行一組 token)。
153
+ *
154
+ *
155
+ * @example
156
+ * ```ts
157
+ * const tokens = parseTokens.javascript("const x = 1;");
158
+ * ```
159
+ *
160
+ * @returns 語法高亮用的 `CodeTokenProps` 二維陣列
161
+ */
162
+ const parseTokens = new Proxy(
77
163
  {},
78
164
  {
79
165
  get: (_, prop: ParsableLanguage) => {
80
166
  const parser = (content: string): CodeTokenProps<"span">[][] => {
81
- return [];
167
+ const result: CodeTokenProps<"span">[][] = [];
168
+
169
+ return result;
82
170
  };
83
171
  return parser;
84
172
  },