honey-css-modules/ADR/exportされるトークンの抽出は postcss-modules を使わずに自前でやる
公開日: 2024/11/18
ステータス
Accepted (2024/11/18)
背景
happy-css-modules では*.module.cssから export されるトークンを特定するために、postcss-modules を使っていた
code:js
import { default as postcss, parse, type Rule, type AtRule, type Root, type Node } from 'postcss';
import modules from 'postcss-modules';
function getExportedLocalTokenNames(ast: Root): string[] {
class EmptyLoader {
async fetch(_file: string, _relativeTo: string, _depTrace: string): Promise<{ key: string: string }> { // Return an empty object because we do not want to load external tokens in getExportedLocalTokenNames.
return Promise.resolve({});
}
}
return new Promise((resolve, reject) => {
postcss
.use(
modules({
// @import, @value, and composes can read tokens from external files.
// However, we want to collect only local tokens. So we will fake that
// an empty token is exported from the external file.
Loader: EmptyLoader,
getJSON: (_cssFileName, json) => {
resolve(Object.keys(json));
},
}),
)
// NOTE: process modifies ast, so clone it.
.process(ast.clone())
.catch(reject);
});
}
const ast = parse(code, { from: filename });
const localTokenNames: string = getExportedLocalTokenNames(ast);
const localTokenlocations: Location[] = collectLocalTokenLocations(ast, localTokenNames);
まず postcss-modules で export されるトークンのうち、ファイル内で定義されているトークン (local token) の名前を抽出してる
その後、collectLocalTokenLocations という utility で AST を再トラバースして、localTokenNamesに含まれるトークンの位置情報を取得してる
しかし、このアプローチでは以下のような問題があった
AST を2回トラバースしていて無駄
postcss-modules で local token の名前を抽出するために1回、そのトークンの位置情報を取得するために1回
理想的には1回だけで十分なはず
パースだけでなく、トランスパイルもしていて無駄
postcss.process(ast)は AST をトランスパイルする API
別にトークンに関する情報が欲しいだけなので、トランスパイルはしなくて良い
local token ではないノードの位置情報が、誤って local token の位置情報として収集されてしまう
.local_token :global(.local_token) {}という CSS Module ファイルでは、本来local_tokenという local token は[{start: 1, end: 12}]という位置情報を持つはず
:global(...)で囲まれた.local_tokenはexportされないので、その位置情報は含まれないはず
しかし実際には[{start: 1, end: 12}, {start: 22, end: 33}]という位置情報が返されてしまう
:global(...)で囲まれた.local_tokenが、誤って export されると判定されて、位置情報が収集されてる
これはcollectLocalTokenLocationsの内部で:local, :globalのハンドリングをせず、とにかくlocalTokenNamesに含まれるクラスの位置情報を全て収集しているために発生している
これらの問題を解決したい
決定事項
exportされるトークンの抽出は postcss-modules を使わずに自前でやる
:local, :globalのハンドリングをしつつ、AST をトラバースし、local token の名前と位置情報を収集するロジックを実装する