Skip to content

parseDesignTokens

从 Excel 设计规范文件解析设计令牌,支持基础颜色、组合颜色、圆角、字体、字号、行高、文字、阴影、间距等多种令牌类型。

前置依赖

依赖参数

参数名类型说明
deps.XLSXXLSXLibraryXLSX 库实例,用于读取和解析 Excel 文件
deps.mixColors(baseColor: string, overlayColor: string, overlayOpacity: number) => string混合颜色计算函数,用于处理颜色叠加表达式

环境要求

  • xlsx: Excel 文件解析库
  • 设计令牌模块: mixColors 函数(同模块内)
bash
npm install xlsx
# mixColors 来自 shared/functions/design-tokens/mixColors

函数签名

typescript
import type { XLSXLibrary } from '../../../references/xlsx.d'

export type TokenMap = Record<string, string>

export type Logger = {
  /** 日志输出函数 */
  log: (message: string) => void
}

/**
 * 解析设计令牌的依赖接口
 */
export interface ParseDesignTokensDeps {
  /** XLSX 库实例,用于读取Excel文件 */
  XLSX: XLSXLibrary
  /** 混合颜色计算函数 */
  mixColors: (baseColor: string, overlayColor: string, overlayOpacity: number) => string
}

/**
 * 解析设计令牌Excel文件
 * 
 * 从Excel文件中解析设计令牌,支持基础颜色、组合颜色、圆角、字体、字号、行高、文字、阴影、间距等多种令牌类型。
 * 
 * @param filePath - Excel文件路径
 * @param deps - 环境依赖,包含XLSX库和颜色混合函数
 * @param logger - 可选的日志记录器,用于输出解析过程信息
 * @returns 解析后的令牌映射对象,键为令牌名称,值为令牌值(颜色为8位hex格式)
 * 
 * @example
 * ```typescript
 * import * as XLSX from 'xlsx'
 * import { mixColors } from 'zcw-shared/functions/design-tokens/mixColors'
 * import { parseDesignTokens } from 'zcw-shared/functions/design-tokens/parseDesignTokens'
 * 
 * const tokens = parseDesignTokens('/path/to/design-tokens.xlsx', {
 *   XLSX,
 *   mixColors
 * }, {
 *   log: console.log
 * })
 * 
 * console.log('解析的令牌数量:', Object.keys(tokens).length)
 * console.log('品牌色:', tokens['brand-color'])  // "#0077FFFF"
 * ```
 */
export function parseDesignTokens(
  filePath: string,
  deps: ParseDesignTokensDeps,
  logger?: Logger
): TokenMap

参数

参数名类型必填说明
filePathstringExcel 文件的绝对或相对路径
depsParseDesignTokensDeps环境依赖,包含 XLSX 库和颜色混合函数
loggerLogger可选的日志记录器,输出详细的解析过程信息

返回值

类型说明
TokenMap解析后的设计令牌映射对象,格式为 { [tokenName: string]: string }

令牌值格式

  • 颜色值:8 位十六进制格式(如 #0077FFFF
  • 尺寸值:CSS 单位(如 4px1.5
  • 复合样式:JSON 字符串(如 {"fontWeight":"400","fontSize":"16px"}
  • CSS 变量引用var(--token-name) 格式

工作原理

解析流程

  1. 文件读取:使用 deps.XLSX.readFile 读取 Excel 文件
  2. 工作表枚举:遍历所有工作表(Sheet),识别令牌类型
  3. 名称标准化:处理工作表命名变体(如 字号-pc文字_m字号
  4. 类型识别:根据工作表名选择解析策略
  5. 数据提取:使用 XLSX.utils.sheet_to_json 转换为行数据
  6. 令牌解析
    • 基础类型:直接键值对映射
    • 颜色处理:RGBA 转 8 位 hex,混合表达式计算
    • 复合类型:构建 JSON 对象(如文字样式)
  7. 指针解析:递归解析 var(--token-name) 引用
  8. 结果返回:完整的 TokenMap 对象

支持的工作表格式

工作表名称数据格式示例输出格式
基础颜色两列(令牌名, 色值)brand-color-1 | #0077FF
brand-color-2 | brand-color-1 + #000000 20%
#0077FFFF
#005CB3FF
组合颜色三列(令牌名, 描述, 引用)primary | 主色 | brand-color-6
hover-primary | 悬停色 | primary + #000000 10%
var(--brand-color-6)
#0066E6FF
圆角两列(令牌名, 尺寸)radius-small | 4px
radius-large | 16px
4px
16px
字体两列(令牌名, 字体族)font-family-base | -apple-system, BlinkMacSystemFont-apple-system, BlinkMacSystemFont
字号两列(令牌名, 尺寸)font-size-xs | 12px
font-size-xl | 24px
12px
24px
行高两列(令牌名, 倍数值)line-height-normal | 1.5
line-height-tight | 1.2
1.5
1.2
文字四列(令牌名, 字重, 字号引用, 行高引用)text-body | 400 | font-size-base | line-height-normal{"fontWeight":"400","fontSize":"var(--font-size-base)","lineHeight":"var(--line-height-normal)"}
阴影两列(令牌名, 阴影描述)shadow-sm | 0 1px 2px rgba(0,0,0,0.05)0 1px 2px rgba(0,0,0,0.05)
间距两列(令牌名, 尺寸)spacer-xs | 4px
spacer-xl | 32px
4px
32px

工作表名称兼容性

  • 支持平台后缀:字号pc文字-m基础颜色_h5
  • 支持分隔符:基础颜色_移动端字号_PC版
  • 自动标准化为规范名称(如 基础颜色字号

特殊处理

颜色混合表达式

支持在基础颜色工作表中使用混合表达式:

  • brand-color-dark: brand-color-base + #000000 30% → 计算后为 8 位 hex
  • overlay-color: #0077FF 80% → 转换为 rgba(0, 119, 255, 80%) 或 8 位 hex

指针解析

支持嵌套的 var 引用解析:

  • primaryvar(--brand-color-6)#0077FF
  • hover-primaryvar(--primary) + #000000 10% → 计算混合色

复合文字样式

文字工作表支持多列复合格式:

  • 列 1:令牌名称(如 text-button
  • 列 2:字重(如 500
  • 列 3:字号引用(如 font-size-md
  • 列 4:行高引用(如 line-height-normal

异常

错误类型触发条件错误信息
ErrormixColors 计算失败通过 logger 输出,函数返回原始表达式
Warning未知工作表类型通过 logger 警告,跳过该工作表
Warning混合颜色格式错误通过 logger 警告,返回原始值
Warning指针解析循环引用通过 visited Set 检测,返回当前值

错误恢复策略

  • 宽容解析:无效数据行会被过滤,函数继续处理其他工作表
  • 日志记录:所有异常通过 logger 输出详细信息
  • 部分成功:单个工作表解析失败不影响其他工作表

使用示例

基础用法

typescript
import * as XLSX from 'xlsx'
import { mixColors } from 'zcw-shared/functions/design-tokens/mixColors'
import { parseDesignTokens } from 'zcw-shared/functions/design-tokens/parseDesignTokens'

// 基础解析
const tokens = parseDesignTokens('./design-tokens.xlsx', {
  XLSX,
  mixColors
})

// 查看解析结果
console.log('所有令牌:', tokens)
console.log('品牌色:', tokens['brand-color'])  // "#0077FFFF"
console.log('圆角小:', tokens['radius-small'])  // "4px"
console.log('文字样式:', tokens['text-body'])   // JSON 字符串

详细日志模式

typescript
import * as XLSX from 'xlsx'
import { mixColors } from 'zcw-shared/functions/design-tokens/mixColors'
import { parseDesignTokens } from 'zcw-shared/functions/design-tokens/parseDesignTokens'

// 启用详细日志
const tokens = parseDesignTokens('./design-tokens.xlsx', {
  XLSX,
  mixColors
}, {
  log: (message: string) => {
    if (message.includes('正在解析工作表:')) {
      console.log(`📋 ${message}`)
    } else if (message.includes('解析完成')) {
      console.log(`🎉 ${message}`)
    } else if (message.includes('混合结果')) {
      console.log(`🎨 ${message}`)
    }
  }
})

// 输出示例:
/*
📋 正在解析工作表: 基础颜色
🎨 解析基础混合颜色: brand-color-2 -> #005CB3FF
📋 正在解析工作表: 圆角
📝 存储圆角: radius-small = 4px
...
🎉 设计令牌解析完成,总计 45 个令牌
*/

与 buildTokens 集成

typescript
import * as XLSX from 'xlsx'
import * as fs from 'fs'
import * as path from 'path'
import { mixColors } from 'zcw-shared/functions/design-tokens/mixColors'
import { parseDesignTokens } from 'zcw-shared/functions/design-tokens/parseDesignTokens'
import { generateCSSVariables, generateJSVariables } from 'zcw-shared/functions/design-tokens/generateVariables'

// 手动解析流程(不使用文件系统)
const tokens = parseDesignTokens('./design-tokens.xlsx', {
  XLSX,
  mixColors
})

// 生成 CSS
const cssContent = generateCSSVariables(tokens, 'manual')
fs.writeFileSync('./manual-tokens.css', cssContent)

// 生成 JS
const jsContent = generateJSVariables(tokens, 'manualTokens')
fs.writeFileSync('./manual-tokens.js', jsContent)

console.log('手动解析完成,生成 2 个文件')
console.log('令牌示例:', {
  brandColor: tokens['brand-color'],
  primaryColor: tokens['primary'],
  radiusSmall: tokens['radius-small']
})

错误处理示例

typescript
import * as XLSX from 'xlsx'
import { mixColors } from 'zcw-shared/functions/design-tokens/mixColors'
import { parseDesignTokens } from 'zcw-shared/functions/design-tokens/parseDesignTokens'

try {
  // 无效的 Excel 文件
  const tokens = parseDesignTokens('./invalid-file.xlsx', {
    XLSX,
    mixColors
  })
} catch (error) {
  // 应该捕获到文件读取错误
  console.error('文件读取失败:', error)
}

// 解析过程错误(格式错误的工作表)
const tokens = parseDesignTokens('./design-tokens.xlsx', {
  XLSX,
  mixColors
}, {
  log: (message: string) => {
    if (message.includes('⚠️') || message.includes('❌')) {
      console.warn(message)  // 警告:未知工作表或混合格式错误
    }
  }
})

// 解析仍然成功,但 logger 会显示警告信息
console.log('解析完成,尽管有格式警告:', Object.keys(tokens).length)

日志输出示例

当启用详细日志时,解析过程会输出:

🔍 开始解析设计令牌文件: ./design-tokens.xlsx
📖 Excel文件读取成功
📊 发现工作表: 基础颜色, 组合颜色, 圆角, 字号, 文字

📋 正在解析工作表: 基础颜色
🎨 解析基础颜色...
📝 存储基础颜色: brand-color-1 = #0077FF
🎨 计算混合颜色: brand-color-1 + #000000 20%
✅ 混合结果: #005CB3FF
🎨 解析基础混合颜色: brand-color-2 -> #005CB3FF

📋 正在解析工作表: 组合颜色
🔗 解析组合颜色...
🔄 解析组合颜色: primary -> var(--brand-color-6)
🔍 指针解析路径: brand-color-6 -> #0077FF
🔄 解析组合颜色: primary -> var(--brand-color-6)

📋 正在解析工作表: 圆角
📐 解析圆角令牌...
📝 存储圆角: radius-small = 4px

📊 工作表 圆角 共有 5 行数据

🎉 设计令牌解析完成,总计 45 个令牌

日志级别说明

  • 📖:基本信息(如文件读取成功)
  • 📊:结构信息(如工作表数量)
  • 🎨:颜色处理(如混合计算)
  • 📝:数据存储(如令牌映射)
  • 🔍:指针解析(如引用链路)
  • ⚠️:警告(如格式不匹配)
  • :错误(如计算失败)

parseDesignTokens 是设计令牌模块的核心解析引擎,支持复杂的 Excel 格式和智能的令牌类型识别,确保设计规范能够准确转换为可用的 TokenMap。