4

ディレクトリのセットからLESSファイルをロードするリソースビルドシステムをまとめようとしています:

Common
├─┬ sub
│ ├── A
│ └── B
├── C
└── ...

最下層の各ディレクトリには、index.less というエントリ ポイントがあります。インデックス ファイルには @import、たとえば@import "colors.less";.

私がしたいことは次のとおりです。

  • インポートしたファイルが現在のディレクトリに存在する場合は、それを使用します。
  • ファイルが存在しない場合は、親ディレクトリにある同じ名前のファイルをルートまで再帰的に使用します。

したがって、解析するとき/Common/sub/A/index.lessは、colors.less を で、A次に で探します。subCommon

2 段階のビルド プロセスの前半は既に開発済みです。

  1. ディレクトリ構造全体をスキャンし、すべてのファイルをオブジェクトにロードします。

    common = { files: { "colors.less": "/* LESS file contents */", ... },
               sub: {
                   files: { ... },
                   A: { files: { "index.less": "@import 'colors.less';", ... } },
                   B: { files: { "index.less": "@import 'colors.less';", ... } }
               },
               C: { files: { "index.less": "@import 'colors.less';", ... } }
              }
    
  2. 最下位ディレクトリごとに結果の CSS ファイルを作成します。

フェーズ 2 では、いくつかの問題に遭遇しました。まず、パーサーを作成します。

var parser = new less.Parser({
    filename: 'index.less'
});

次に、ファイルを解析します。

parser.parse(common.sub.A.files['index.less'], function(e, tree) {
    // `tree` is the AST
});

これにより、コールバックに配信される抽象構文ツリー (AST) が取得されます。問題は、LESS パーサー@importが独自のファイル インポーターで見つけたすべてのステートメントを解決し、インポートされたファイルを現在の AST にマージすることです。

これを回避するために、現在インポーターをオーバーロードしてパスを書き換えています。

// before starting anything:

var importer = less.Parser.importer;
less.Parser.importer = function(path, currentFileInfo, callback, env) {
    var newPath;

    // here, use the object from phase 1 to resolve the path nearest file
    // matching `path` (which is really just a filename), and set `newPath`

    importer(newPath, currentFileInfo, callback, env);
};

ただし、LESS インポーターは引き続きディスクからファイルを読み取ります。これは、(A) ファイルの内容が既にメモリ内にあり、(B) 多数の下位レベルのディレクトリがあるため、パフォーマンスの観点からは悪いことです。したがって、同じ共通ファイルを再ロードして再解析する必要があります。ファイルを複数回。

私がやりたいことは、フェーズ 1 ですべての LESS ファイルを解析し、フェーズ 2 で必要に応じて AST をマージすることです。

これを行うには、@import解析中に LESS がノードを評価しないようにする必要があります。次に、フェーズ 2 で、AST 内のノードを手動で見つけて@import、既に解析済みの AST にマージします (独自@importの を含めることができるため、再帰的に)。

4

1 に答える 1

0

興味深い問題です。Less パーサーの実装を深く掘り下げずに (現時点では私と同じように避けたいと思います)、単純に事前解析ステップを追加しないでください: すべての .less ファイルを読み取り、インポートをコメントアウトしますか?

したがって、パーサーを介して less ファイルを実行する直前に、自分でファイルを読み取ってファイルに書き込み、@import の行をコメントアウトして、メモを取ることができます。次に、パーサーを介して実行すると、以前に取得したインポート情報を添付できる AST が取得されます。

これで、すでに計画していた方法ですべての AST を組み合わせることができます。

より少ないファイルを見つけた状態に保つようにしてください。これらの行のコメントを解除するか、作業する各ファイルをコピーし、インポートをコメントアウトし、解析してから削除することをお勧めします。これにより、元のファイルを汚染する心配がなくなります。

問題を回避する簡単な方法のようです。@import トークンを無視するように less パーサー自体に指示するようなことをしたくない場合を除きます。(ここでランダムに突き刺すだけですが、おそらく lib/less/parser.js の 1252 行目の「インポート」関数を編集して返す と、すべてのトークンがコメントとしてnew(tree.Comment)(dir);解析されるだけかもしれません。@import

于 2013-03-22T03:27:19.843 に答える