| import { parsableLanguages, themes } from "../libs"; | ||
| import { AsComponentProps, OverrideProps } from "./common"; | ||
| /** | ||
| * 用於表示語法高亮中每個 token 的語意分類,對應於 `<CodeToken />` 中的 `type`。 | ||
| * | ||
| * 每個類型會對應特定的顏色與用途,例如關鍵字、數字、字串、註解等, | ||
| * | ||
| * 類型分為以下幾大類: | ||
| * | ||
| * - `keyword1` / `keyword2`: 關鍵字,如 `const`/`return`、`import` 等,分顏色類別。 | ||
| * - `string`: 字串常值,如 `'text'`、`"value"`。 | ||
| * - `number`: 數字常值,如 `123`、`3.14`。 | ||
| * - `comment`: 註解內容,如 `//`。 | ||
| * - `type`: 類型定義,如 `interface`、`enum`、`type`。 | ||
| * - `variable`: 識別符號,如變數名、函式名、類別名。 | ||
| * - `constant`: 常數或靜態值,如 `PI`、`MAX_VALUE`。 | ||
| * - `brackets1 | brackets2 | brackets3`: 括號配對,區分不同層級的括號。 | ||
| * - `operator`: 運算符,如 `=`, `+`, `===`, `<`, `>=`。 | ||
| * - `default`: 其他符號,如 `;`, `,`, `.`, `?`, `"`, `'`。 | ||
| * | ||
| * @example | ||
| * const token: CodeTokenType = "keyword1"; | ||
| * const token2: CodeTokenType = "string"; | ||
| */ | ||
| export type CodeTokenType = | ||
| | `keyword${1 | 2}` // 關鍵字,分兩種樣式 | ||
| | "function" // 函式名 | ||
| | "string" // 字串常值:'abc'、"hello" | ||
| | "number" // 數值常量:123、3.14 | ||
| | "comment" // 註解內容:// 或 /* */ | ||
| | "type" // 類型定義:type、interface、enum | ||
| | "variable" // 變數名、函式名、類別名等識別符號 | ||
| | "constant" // 常數值:例如 enum 值、靜態屬性 | ||
| | `brackets${1 | 2 | 3}` // 括號,多層巢狀不同樣式:{[()]} | ||
| | "operator" // 運算符號:=、+、*、===、<、>= 等 | ||
| | "default"; // 其他符號:, ; . ? ! 等 | ||
| /** | ||
| * 表示可用的語法高亮主題名稱。 | ||
| * 對應 `themes` 陣列中定義的名稱,例如 `"vscode-dark"`。 | ||
| * | ||
| * @example | ||
| * const theme: CodeTheme = "vscode-dark"; | ||
| */ | ||
| export type CodeTheme = (typeof themes)[number]; | ||
| /** | ||
| * 單一語法 token 的屬性,用於 <CodeToken /> 元件。 | ||
| * | ||
| * @template T HTML 或客製元素,例如 span、a、Link 等 | ||
| */ | ||
| export type CodeTokenProps<T extends React.ElementType> = AsComponentProps< | ||
| T, | ||
| { | ||
| /** | ||
| * 語法 token 的語意類型,用於指定樣式顏色。 | ||
| */ | ||
| type?: CodeTokenType; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type CodeTokenBuilder = <T extends React.ElementType = "span">( | ||
| children: CodeTokenProps<T>["children"], | ||
| props?: CodeTokenProps<T> | ||
| ) => CodeTokenProps<T>; | ||
| /** | ||
| * 用於單一程式碼行的屬性,用在 <CodeLine /> 或類似元件中。 | ||
| */ | ||
| export type CodeLineProps<T extends React.ElementType> = OverrideProps< | ||
| React.HTMLAttributes<HTMLElement>, | ||
| { | ||
| /** | ||
| * 該行所包含的語法 token。 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <CodeLine tokens={[ | ||
| * { type: "keyword-blue", children: "const" }, | ||
| * { type: "variable", children: "myVar" }, | ||
| * { type: "operator", children: "=" }, | ||
| * { type: "string", children: "'Hello'" }, | ||
| * ]} /> | ||
| * ``` | ||
| */ | ||
| tokens: CodeTokenProps<T>[]; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type CodeBlockProps<T extends React.ElementType> = OverrideProps< | ||
| React.HTMLAttributes<HTMLPreElement>, | ||
| { | ||
| /** | ||
| * 所有程式碼行的 token 陣列。 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <CodeBlock tokenLines={[ | ||
| * [ | ||
| * { type: "keyword1", children: "const" }, | ||
| * { type: "variable", children: "x" }, | ||
| * { type: "operator", children: "=" }, | ||
| * { type: "number", children: "42" }, | ||
| * ], | ||
| * [ | ||
| * { type: "keyword2", children: "return" }, | ||
| * { type: "variable", children: "x" }, | ||
| * ], | ||
| * ]} /> | ||
| * ``` | ||
| */ | ||
| tokenLines: CodeTokenProps<T>[][]; | ||
| /** | ||
| * 是否顯示行號。 | ||
| * @default true | ||
| */ | ||
| showLineNumbers?: boolean; | ||
| /** | ||
| * 行號的樣式。 | ||
| * @default { color: "#888", fontSize: "0.8em" } | ||
| * @example | ||
| * ```tsx | ||
| * <CodeBlock lineNumberStyle={{ color: "#888", fontSize: "0.8em" }} /> | ||
| * ``` | ||
| * */ | ||
| lineNumberStyle?: React.CSSProperties; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "default-dark-modern" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type ParsableLanguage = (typeof parsableLanguages)[number]; |
@@ -10,3 +10,3 @@ import { parsableLanguages, themes } from "../libs"; | ||
| * | ||
| * - `keyword1` / `keyword2`: 關鍵字,如 `const`、`return`、`import` 等,分顏色類別。 | ||
| * - `keyword1` / `keyword2`: 關鍵字,如 `const`/`return`、`import` 等,分顏色類別。 | ||
| * - `string`: 字串常值,如 `'text'`、`"value"`。 | ||
@@ -84,3 +84,3 @@ * - `number`: 數字常值,如 `123`、`3.14`。 | ||
| * [ | ||
| * { type: "keyword-blue", children: "const" }, | ||
| * { type: "keyword1", children: "const" }, | ||
| * { type: "variable", children: "x" }, | ||
@@ -91,3 +91,3 @@ * { type: "operator", children: "=" }, | ||
| * [ | ||
| * { type: "keyword-purple", children: "return" }, | ||
| * { type: "keyword2", children: "return" }, | ||
| * { type: "variable", children: "x" }, | ||
@@ -115,3 +115,3 @@ * ], | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| * @default "default-dark-modern" | ||
| */ | ||
@@ -118,0 +118,0 @@ theme?: CodeTheme; |
+38
-13
| import React from "react"; | ||
| import { CodeTokenBuilder, CodeTokenProps, CodeTokenType } from "../types"; | ||
| /** | ||
| * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等), | ||
| * 透過 Proxy 生成對應的 `CodeTokenBuilder`。 | ||
| * `c063` 是一組語法高亮 token 建構器集合。 | ||
| * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等), | ||
| * 回傳對應的 `CodeTokenProps` 物件。 | ||
| * | ||
| * 使用方式: | ||
| * @example | ||
| * ```tsx | ||
| * c063.keyword1("const") // -> { type: "keyword1", children: "const" } | ||
| * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props | ||
| * const keyword = c063.keyword1("const"); | ||
| * const str = c063.string("'Hello'", { as: "code" }); | ||
| * ``` | ||
| * | ||
| * @example | ||
| * tokens.push(c063.keyword1("const")); | ||
| * tokens.push(c063.string("'Hello'")); | ||
| * | ||
| * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合 | ||
| * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。 | ||
| */ | ||
| declare const c063: Record<CodeTokenType, CodeTokenBuilder>; | ||
| export default c063; | ||
| /** | ||
| * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。 | ||
| * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。 | ||
| * | ||
| * @param count 空白字元數,預設為 1 | ||
| * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串 | ||
| * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " } | ||
| * ``` | ||
| */ | ||
| export declare const whiteSpace: (count?: number) => CodeTokenProps<"span">; | ||
| /** | ||
| * 抽取單個 `CodeTokenProps` 的純文字內容。 | ||
| * | ||
| * @param token 要處理的 token | ||
| * @returns 對應的文字內容 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * extractTokenContent(c063.keyword1("return")); // => "return" | ||
| * ``` | ||
| */ | ||
| export declare const extractTokenContent: <T extends React.ElementType>(token: CodeTokenProps<T>) => string; | ||
| export default c063; | ||
| /** | ||
| * 判斷兩個 token 是否相等(type 與內容皆相同)。 | ||
| * | ||
| * @param a 第一個 token | ||
| * @param b 第二個 token | ||
| * @returns 是否相等 | ||
| */ | ||
| export declare const isTokenEqual: <T extends React.ElementType>(a: CodeTokenProps<T>, b: CodeTokenProps<T>) => boolean; | ||
| /** | ||
| * 將 token 列表按語法類型分類。 | ||
| * | ||
| * @param lines 二維陣列,每行為一組 token | ||
| * @returns 分組後的 token 映射,key 為 `CodeTokenType` | ||
| */ | ||
| export declare const groupTokensByType: <T extends React.ElementType>(lines: CodeTokenProps<T>[][]) => Record<CodeTokenType, CodeTokenProps<T>[]>; |
+106
-28
| import React from "react"; | ||
| /** | ||
| * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等), | ||
| * 透過 Proxy 生成對應的 `CodeTokenBuilder`。 | ||
| * `c063` 是一組語法高亮 token 建構器集合。 | ||
| * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等), | ||
| * 回傳對應的 `CodeTokenProps` 物件。 | ||
| * | ||
| * 使用方式: | ||
| * @example | ||
| * ```tsx | ||
| * c063.keyword1("const") // -> { type: "keyword1", children: "const" } | ||
| * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props | ||
| * const keyword = c063.keyword1("const"); | ||
| * const str = c063.string("'Hello'", { as: "code" }); | ||
| * ``` | ||
| * | ||
| * @example | ||
| * tokens.push(c063.keyword1("const")); | ||
| * tokens.push(c063.string("'Hello'")); | ||
| * | ||
| * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合 | ||
| * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。 | ||
| */ | ||
| const c063 = new Proxy({}, { | ||
| get: (_, prop) => { | ||
| /** | ||
| * 建立指定語法類型的 CodeToken。 | ||
| * | ||
| * @param children 要包裹的 React 內容或字串 | ||
| * @param props 可選的額外屬性,如 `as` 或 `className` | ||
| * @returns 一個 CodeToken 物件 | ||
| */ | ||
| const builder = (children, props) => { | ||
@@ -30,35 +34,109 @@ return { | ||
| }); | ||
| export default c063; | ||
| /** | ||
| * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。 | ||
| * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。 | ||
| * | ||
| * @param count 空白字元數,預設為 1 | ||
| * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串 | ||
| * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " } | ||
| * ``` | ||
| */ | ||
| export const whiteSpace = (count = 1) => c063.default(" ".repeat(count)); | ||
| /** | ||
| * 遞迴抽取 ReactNode 中的純文字內容。 | ||
| * | ||
| * @param children ReactNode,可以是字串、數字、JSX 元素、陣列等 | ||
| * @returns 純文字內容字串 | ||
| */ | ||
| const _extractReactNode = (children) => { | ||
| if (typeof children === "string") | ||
| return children; | ||
| if (typeof children === "number") | ||
| return children.toString(); | ||
| if (Array.isArray(children)) | ||
| return children.map(_extractReactNode).join(""); | ||
| if (React.isValidElement(children)) { | ||
| return _extractReactNode(children.props.children); | ||
| } | ||
| if (typeof children === "object" && children !== null) { | ||
| return React.Children.toArray(children).map(_extractReactNode).join(""); | ||
| } | ||
| return ""; // 如果 children 是 null 或 undefined,則返回空字串 | ||
| }; | ||
| /** | ||
| * 抽取單個 `CodeTokenProps` 的純文字內容。 | ||
| * | ||
| * @param token 要處理的 token | ||
| * @returns 對應的文字內容 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * extractTokenContent(c063.keyword1("return")); // => "return" | ||
| * ``` | ||
| */ | ||
| export const extractTokenContent = (token) => { | ||
| const _extract = (children) => { | ||
| if (typeof children === "string") | ||
| return children; | ||
| if (typeof children === "number") | ||
| return children.toString(); | ||
| if (Array.isArray(children)) | ||
| return children.map(_extract).join(""); | ||
| if (React.isValidElement(children)) { | ||
| return _extract(children.props.children); | ||
| } | ||
| return ""; // 如果 children 是 null 或 undefined,則返回空字串 | ||
| return _extractReactNode(token.children); | ||
| }; | ||
| /** | ||
| * 判斷兩個 token 是否相等(type 與內容皆相同)。 | ||
| * | ||
| * @param a 第一個 token | ||
| * @param b 第二個 token | ||
| * @returns 是否相等 | ||
| */ | ||
| export const isTokenEqual = (a, b) => { | ||
| return a.type === b.type && extractTokenContent(a) === extractTokenContent(b); | ||
| }; | ||
| /** | ||
| * 將 token 列表按語法類型分類。 | ||
| * | ||
| * @param lines 二維陣列,每行為一組 token | ||
| * @returns 分組後的 token 映射,key 為 `CodeTokenType` | ||
| */ | ||
| export const groupTokensByType = (lines) => { | ||
| var _a; | ||
| const grouped = { | ||
| keyword1: [], | ||
| keyword2: [], | ||
| function: [], | ||
| string: [], | ||
| number: [], | ||
| comment: [], | ||
| type: [], | ||
| variable: [], | ||
| constant: [], | ||
| brackets1: [], | ||
| brackets2: [], | ||
| brackets3: [], | ||
| operator: [], | ||
| default: [], | ||
| }; | ||
| return _extract(token.children); | ||
| for (const token of lines.flat()) { | ||
| grouped[(_a = token.type) !== null && _a !== void 0 ? _a : "default"].push(token); | ||
| } | ||
| return grouped; | ||
| }; | ||
| export default c063; | ||
| /** | ||
| * 待實現 | ||
| * 待實作 | ||
| * `parseTokens` 是語法解析器的代理集合,用來解析特定語言的程式碼字串。 | ||
| * | ||
| * 每個 key 對應一種可解析語言(如 `"javascript"`、`"python"` 等), | ||
| * 傳入原始程式碼字串後,回傳解析後的 token 二維陣列(每行一組 token)。 | ||
| * | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const tokens = parseTokens.javascript("const x = 1;"); | ||
| * ``` | ||
| * | ||
| * @returns 語法高亮用的 `CodeTokenProps` 二維陣列 | ||
| */ | ||
| const _parseTokens = new Proxy({}, { | ||
| const parseTokens = new Proxy({}, { | ||
| get: (_, prop) => { | ||
| const parser = (content) => { | ||
| return []; | ||
| const result = []; | ||
| return result; | ||
| }; | ||
@@ -65,0 +143,0 @@ return parser; |
+1
-1
| { | ||
| "$schema": "https://json.schemastore.org/package.json", | ||
| "name": "c063", | ||
| "version": "1.4.9", | ||
| "version": "1.5.0", | ||
| "description": "A React component for displaying code snippets with syntax highlighting.", | ||
@@ -6,0 +6,0 @@ "main": "dist/index.js", |
+115
-27
@@ -10,16 +10,13 @@ import React from "react"; | ||
| /** | ||
| * 語法 token 的建構器集合,每個 key 對應一種語法類型(如 `keyword-blue`, `string`, `comment` 等), | ||
| * 透過 Proxy 生成對應的 `CodeTokenBuilder`。 | ||
| * `c063` 是一組語法高亮 token 建構器集合。 | ||
| * 每個 key 對應一種語法分類(如 `keyword1`, `string`, `comment` 等), | ||
| * 回傳對應的 `CodeTokenProps` 物件。 | ||
| * | ||
| * 使用方式: | ||
| * @example | ||
| * ```tsx | ||
| * c063.keyword1("const") // -> { type: "keyword1", children: "const" } | ||
| * c063.string("'hello'", { as: "code" }) // 可自訂 as 或其他 props | ||
| * const keyword = c063.keyword1("const"); | ||
| * const str = c063.string("'Hello'", { as: "code" }); | ||
| * ``` | ||
| * | ||
| * @example | ||
| * tokens.push(c063.keyword1("const")); | ||
| * tokens.push(c063.string("'Hello'")); | ||
| * | ||
| * @returns 一個以 `CodeTokenType` 為 key 的建構器函式集合 | ||
| * @returns 以 `CodeTokenType` 為 key 的建構器函式集合。 | ||
| */ | ||
@@ -30,5 +27,12 @@ const c063 = new Proxy( | ||
| get: (_, prop: CodeTokenType) => { | ||
| /** | ||
| * 建立指定語法類型的 CodeToken。 | ||
| * | ||
| * @param children 要包裹的 React 內容或字串 | ||
| * @param props 可選的額外屬性,如 `as` 或 `className` | ||
| * @returns 一個 CodeToken 物件 | ||
| */ | ||
| const builder = <T extends React.ElementType = "span">( | ||
| children: React.ReactNode, | ||
| props: CodeTokenProps<T> | ||
| props?: CodeTokenProps<T> | ||
| ) => { | ||
@@ -45,11 +49,14 @@ return { | ||
| ) as Record<CodeTokenType, CodeTokenBuilder>; | ||
| export default c063; | ||
| /** | ||
| * 產生指定空白數量的 CodeToken,用於程式碼中的縮排或空格。 | ||
| * 產生指定空白數量的 CodeToken,用於縮排、空格等用途。 | ||
| * | ||
| * @param count 空白字元數,預設為 1 | ||
| * @returns `CodeTokenProps` 物件,type 為 "default",children 為空白字串 | ||
| * @returns type 為 `"default"`、內容為空格的 `CodeTokenProps` | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * tokens.push(whiteSpace(2)); // -> { type: "default", children: " " } | ||
| * ``` | ||
| */ | ||
@@ -59,23 +66,102 @@ export const whiteSpace = (count: number = 1): CodeTokenProps<"span"> => | ||
| /** | ||
| * 遞迴抽取 ReactNode 中的純文字內容。 | ||
| * | ||
| * @param children ReactNode,可以是字串、數字、JSX 元素、陣列等 | ||
| * @returns 純文字內容字串 | ||
| */ | ||
| const _extractReactNode = (children: React.ReactNode): string => { | ||
| if (typeof children === "string") return children; | ||
| if (typeof children === "number") return children.toString(); | ||
| if (Array.isArray(children)) return children.map(_extractReactNode).join(""); | ||
| if (React.isValidElement(children)) { | ||
| return _extractReactNode((children as React.JSX.Element).props.children); | ||
| } | ||
| if (typeof children === "object" && children !== null) { | ||
| return React.Children.toArray(children).map(_extractReactNode).join(""); | ||
| } | ||
| return ""; // 如果 children 是 null 或 undefined,則返回空字串 | ||
| }; | ||
| /** | ||
| * 抽取單個 `CodeTokenProps` 的純文字內容。 | ||
| * | ||
| * @param token 要處理的 token | ||
| * @returns 對應的文字內容 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * extractTokenContent(c063.keyword1("return")); // => "return" | ||
| * ``` | ||
| */ | ||
| export const extractTokenContent = <T extends React.ElementType>( | ||
| token: CodeTokenProps<T> | ||
| ): string => { | ||
| const _extract = (children: React.ReactNode): string => { | ||
| if (typeof children === "string") return children; | ||
| if (typeof children === "number") return children.toString(); | ||
| if (Array.isArray(children)) return children.map(_extract).join(""); | ||
| if (React.isValidElement(children)) { | ||
| return _extract((children as React.JSX.Element).props.children); | ||
| } | ||
| return ""; // 如果 children 是 null 或 undefined,則返回空字串 | ||
| }; | ||
| return _extract(token.children); | ||
| return _extractReactNode(token.children); | ||
| }; | ||
| export default c063; | ||
| /** | ||
| * 判斷兩個 token 是否相等(type 與內容皆相同)。 | ||
| * | ||
| * @param a 第一個 token | ||
| * @param b 第二個 token | ||
| * @returns 是否相等 | ||
| */ | ||
| export const isTokenEqual = <T extends React.ElementType>( | ||
| a: CodeTokenProps<T>, | ||
| b: CodeTokenProps<T> | ||
| ): boolean => { | ||
| return a.type === b.type && extractTokenContent(a) === extractTokenContent(b); | ||
| }; | ||
| /** | ||
| * 待實現 | ||
| * 將 token 列表按語法類型分類。 | ||
| * | ||
| * @param lines 二維陣列,每行為一組 token | ||
| * @returns 分組後的 token 映射,key 為 `CodeTokenType` | ||
| */ | ||
| const _parseTokens = new Proxy( | ||
| export const groupTokensByType = <T extends React.ElementType>( | ||
| lines: CodeTokenProps<T>[][] | ||
| ): Record<CodeTokenType, CodeTokenProps<T>[]> => { | ||
| const grouped: Record<CodeTokenType, CodeTokenProps<T>[]> = { | ||
| keyword1: [], | ||
| keyword2: [], | ||
| function: [], | ||
| string: [], | ||
| number: [], | ||
| comment: [], | ||
| type: [], | ||
| variable: [], | ||
| constant: [], | ||
| brackets1: [], | ||
| brackets2: [], | ||
| brackets3: [], | ||
| operator: [], | ||
| default: [], | ||
| }; | ||
| for (const token of lines.flat()) { | ||
| grouped[token.type ?? "default"].push(token); | ||
| } | ||
| return grouped; | ||
| }; | ||
| /** | ||
| * 待實作 | ||
| * `parseTokens` 是語法解析器的代理集合,用來解析特定語言的程式碼字串。 | ||
| * | ||
| * 每個 key 對應一種可解析語言(如 `"javascript"`、`"python"` 等), | ||
| * 傳入原始程式碼字串後,回傳解析後的 token 二維陣列(每行一組 token)。 | ||
| * | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const tokens = parseTokens.javascript("const x = 1;"); | ||
| * ``` | ||
| * | ||
| * @returns 語法高亮用的 `CodeTokenProps` 二維陣列 | ||
| */ | ||
| const parseTokens = new Proxy( | ||
| {}, | ||
@@ -85,3 +171,5 @@ { | ||
| const parser = (content: string): CodeTokenProps<"span">[][] => { | ||
| return []; | ||
| const result: CodeTokenProps<"span">[][] = []; | ||
| return result; | ||
| }; | ||
@@ -88,0 +176,0 @@ return parser; |
| import { parsableLanguages, themes } from "../libs"; | ||
| import { AsComponentProps, OverrideProps } from "./common"; | ||
| /** | ||
| * 用於表示語法高亮中每個 token 的語意分類,對應於 `<CodeToken />` 中的 `type`。 | ||
| * | ||
| * 每個類型會對應特定的顏色與用途,例如關鍵字、數字、字串、註解等, | ||
| * | ||
| * 類型分為以下幾大類: | ||
| * | ||
| * - `keyword1` / `keyword2`: 關鍵字,如 `const`、`return`、`import` 等,分顏色類別。 | ||
| * - `string`: 字串常值,如 `'text'`、`"value"`。 | ||
| * - `number`: 數字常值,如 `123`、`3.14`。 | ||
| * - `comment`: 註解內容,如 `//`。 | ||
| * - `type`: 類型定義,如 `interface`、`enum`、`type`。 | ||
| * - `variable`: 識別符號,如變數名、函式名、類別名。 | ||
| * - `constant`: 常數或靜態值,如 `PI`、`MAX_VALUE`。 | ||
| * - `brackets1 | brackets2 | brackets3`: 括號配對,區分不同層級的括號。 | ||
| * - `operator`: 運算符,如 `=`, `+`, `===`, `<`, `>=`。 | ||
| * - `default`: 其他符號,如 `;`, `,`, `.`, `?`, `"`, `'`。 | ||
| * | ||
| * @example | ||
| * const token: CodeTokenType = "keyword1"; | ||
| * const token2: CodeTokenType = "string"; | ||
| */ | ||
| export type CodeTokenType = | ||
| | `keyword${1 | 2}` // 關鍵字,分兩種樣式 | ||
| | "function" // 函式名 | ||
| | "string" // 字串常值:'abc'、"hello" | ||
| | "number" // 數值常量:123、3.14 | ||
| | "comment" // 註解內容:// 或 /* */ | ||
| | "type" // 類型定義:type、interface、enum | ||
| | "variable" // 變數名、函式名、類別名等識別符號 | ||
| | "constant" // 常數值:例如 enum 值、靜態屬性 | ||
| | `brackets${1 | 2 | 3}` // 括號,多層巢狀不同樣式:{[()]} | ||
| | "operator" // 運算符號:=、+、*、===、<、>= 等 | ||
| | "default"; // 其他符號:, ; . ? ! 等 | ||
| /** | ||
| * 表示可用的語法高亮主題名稱。 | ||
| * 對應 `themes` 陣列中定義的名稱,例如 `"vscode-dark"`。 | ||
| * | ||
| * @example | ||
| * const theme: CodeTheme = "vscode-dark"; | ||
| */ | ||
| export type CodeTheme = (typeof themes)[number]; | ||
| /** | ||
| * 單一語法 token 的屬性,用於 <CodeToken /> 元件。 | ||
| * | ||
| * @template T HTML 或客製元素,例如 span、a、Link 等 | ||
| */ | ||
| export type CodeTokenProps<T extends React.ElementType> = AsComponentProps< | ||
| T, | ||
| { | ||
| /** | ||
| * 語法 token 的語意類型,用於指定樣式顏色。 | ||
| */ | ||
| type?: CodeTokenType; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type CodeTokenBuilder = <T extends React.ElementType = "span">( | ||
| children: CodeTokenProps<T>["children"], | ||
| props?: CodeTokenProps<T> | ||
| ) => CodeTokenProps<T>; | ||
| /** | ||
| * 用於單一程式碼行的屬性,用在 <CodeLine /> 或類似元件中。 | ||
| */ | ||
| export type CodeLineProps<T extends React.ElementType> = OverrideProps< | ||
| React.HTMLAttributes<HTMLElement>, | ||
| { | ||
| /** | ||
| * 該行所包含的語法 token。 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <CodeLine tokens={[ | ||
| * { type: "keyword-blue", children: "const" }, | ||
| * { type: "variable", children: "myVar" }, | ||
| * { type: "operator", children: "=" }, | ||
| * { type: "string", children: "'Hello'" }, | ||
| * ]} /> | ||
| * ``` | ||
| */ | ||
| tokens: CodeTokenProps<T>[]; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type CodeBlockProps<T extends React.ElementType> = OverrideProps< | ||
| React.HTMLAttributes<HTMLPreElement>, | ||
| { | ||
| /** | ||
| * 所有程式碼行的 token 陣列。 | ||
| * | ||
| * @example | ||
| * ```tsx | ||
| * <CodeBlock tokenLines={[ | ||
| * [ | ||
| * { type: "keyword-blue", children: "const" }, | ||
| * { type: "variable", children: "x" }, | ||
| * { type: "operator", children: "=" }, | ||
| * { type: "number", children: "42" }, | ||
| * ], | ||
| * [ | ||
| * { type: "keyword-purple", children: "return" }, | ||
| * { type: "variable", children: "x" }, | ||
| * ], | ||
| * ]} /> | ||
| * ``` | ||
| */ | ||
| tokenLines: CodeTokenProps<T>[][]; | ||
| /** | ||
| * 是否顯示行號。 | ||
| * @default true | ||
| */ | ||
| showLineNumbers?: boolean; | ||
| /** | ||
| * 行號的樣式。 | ||
| * @default { color: "#888", fontSize: "0.8em" } | ||
| * @example | ||
| * ```tsx | ||
| * <CodeBlock lineNumberStyle={{ color: "#888", fontSize: "0.8em" }} /> | ||
| * ``` | ||
| * */ | ||
| lineNumberStyle?: React.CSSProperties; | ||
| /** | ||
| * 語法主題名稱。 | ||
| * @default "vscode-dark" | ||
| */ | ||
| theme?: CodeTheme; | ||
| } | ||
| >; | ||
| export type ParsableLanguage = (typeof parsableLanguages)[number]; |
715569
0.73%1947
10.5%