版本

自訂格式器

自訂格式器可讓您以最符合您需求的格式顯示程式碼檢查結果,無論是特定檔案格式、特定顯示樣式,還是針對特定工具優化的格式。

ESLint 也有您可以使用的內建格式器

您可以直接在專案中包含自訂格式器,或建立 npm 套件來單獨發佈它們。

建立自訂格式器

每個格式器都是一個函式,它接收一個 results 物件和一個 context 作為參數,並返回一個字串。例如,以下是內建的JSON 格式器的實作方式

//my-awesome-formatter.js
module.exports = function(results, context) {
    return JSON.stringify(results, null, 2);
};

格式器也可以是異步函式 (從 ESLint v8.4.0 開始),以下顯示一個簡單的範例

//my-awesome-formatter.js
module.exports = async function(results) {
    const formatted = await asyncTask();
    return formatted;
};

要使用此格式器執行 ESLint,您可以使用 -f (或 --format) 命令列旗標。您必須以句點 (.) 開始本機定義的自訂格式器的路徑,例如 ./my-awesome-formatter.js../formatters/my-awesome-formatter.js

eslint -f ./my-awesome-formatter.js src/

本節的其餘部分包含有關如何使用自訂格式器函式的參考資訊。

results 參數

傳遞給格式器的 results 物件是一個 result 物件的陣列,其中包含個別檔案的程式碼檢查結果。以下是一個範例輸出

[
    {
        filePath: "/path/to/a/file.js",
        messages: [
            {
                ruleId: "curly",
                severity: 2,
                message: "Expected { after 'if' condition.",
                line: 2,
                column: 1,
                nodeType: "IfStatement"
            },
            {
                ruleId: "no-process-exit",
                severity: 2,
                message: "Don't use process.exit(); throw an error instead.",
                line: 3,
                column: 1,
                nodeType: "CallExpression"
            }
        ],
        errorCount: 2,
        warningCount: 0,
        fixableErrorCount: 0,
        fixableWarningCount: 0,
        source:
            "var err = doStuff();\nif (err) console.log('failed tests: ' + err);\nprocess.exit(1);\n"
    },
    {
        filePath: "/path/to/Gruntfile.js",
        messages: [],
        errorCount: 0,
        warningCount: 0,
        fixableErrorCount: 0,
        fixableWarningCount: 0
    }
]

result 物件

results 陣列中的每個物件都是一個 result 物件。每個 result 物件都包含已檢查程式碼的檔案路徑,以及有關所遇到程式碼檢查問題的資訊。以下是每個 result 物件上可用的屬性

  • filePath:已檢查程式碼的檔案的絕對路徑。
  • messagesmessage 物件的陣列。有關訊息的更多資訊,請參閱下文。
  • errorCount:給定檔案的錯誤數。
  • warningCount:給定檔案的警告數。
  • stats:只有在使用 stats 選項時才存在的選用 stats 物件。
  • source:給定檔案的原始程式碼。如果此檔案沒有錯誤/警告,或如果存在 output 屬性,則會省略此屬性。
  • output:給定檔案的原始程式碼,其中已應用盡可能多的修復。如果沒有可用的修復,則會省略此屬性。
message 物件

每個 message 物件都包含有關某些原始程式碼觸發的 ESLint 規則的資訊。每個 message 物件上可用的屬性為

  • ruleId:產生錯誤或警告的規則的 ID。如果錯誤或警告不是由規則產生的 (例如,如果是剖析錯誤),則此為 null
  • severity:失敗的嚴重性,1 代表警告,2 代表錯誤。
  • message:錯誤的人類可讀描述。
  • line:問題所在行的位置。
  • column:問題所在列的位置。
  • nodeType:(已過時: 此屬性將在未來版本的 ESLint 中移除。) AST 中的節點類型,如果問題與特定 AST 節點無關,則為 null

context 參數

格式器函式接收一個 context 物件作為其第二個參數。該物件具有以下屬性

  • cwd:目前的工作目錄。此值來自 ESLint 類別的 cwd 建構函式選項。
  • maxWarningsExceeded (選用):如果設定了 --max-warnings 並且警告數量超過了限制,則此屬性的值是一個包含兩個屬性的物件
    • maxWarnings--max-warnings 選項的值
    • foundWarnings:程式碼檢查警告的數量
  • rulesMeta:規則的 meta 屬性值。有關規則的更多資訊,請參閱自訂規則頁面。

例如,如果已執行 no-extra-semi 規則,則該物件會如下所示

{
    cwd: "/path/to/cwd",
    maxWarningsExceeded: {
        maxWarnings: 5,
        foundWarnings: 6
    },
    rulesMeta: {
        "no-extra-semi": {
            type: "suggestion",
            docs: {
                description: "disallow unnecessary semicolons",
                recommended: true,
                url: "https://eslint.dev.org.tw/docs/rules/no-extra-semi"
            },
            fixable: "code",
            schema: [],
            messages: {
                unexpected: "Unnecessary semicolon."
            }
        }
    },
}

注意:如果程式碼檢查是由已過時的 CLIEngine 類別執行的,則 context 參數可能是一個不同的值,因為它取決於 API 使用者。如果您想要支援舊版環境,請檢查 context 參數是否為預期值。

傳遞參數給格式器

雖然格式器函式除了 results 物件和 context 之外不接收參數,但可以使用以下描述的方法將其他資料傳遞到自訂格式器中。

使用環境變數

自訂格式器可以存取環境變數,因此可以根據環境變數資料變更其行為。

以下範例使用 FORMATTER_SKIP_WARNINGS 環境變數來判斷是否在結果中顯示警告

module.exports = function(results) {
    var skipWarnings = process.env.FORMATTER_SKIP_WARNINGS === "true";

    var results = results || [];
    var summary = results.reduce(
        function(seq, current) {
            current.messages.forEach(function(msg) {
                var logMessage = {
                    filePath: current.filePath,
                    ruleId: msg.ruleId,
                    message: msg.message,
                    line: msg.line,
                    column: msg.column
                };

                if (msg.severity === 1) {
                    logMessage.type = "warning";
                    seq.warnings.push(logMessage);
                }
                if (msg.severity === 2) {
                    logMessage.type = "error";
                    seq.errors.push(logMessage);
                }
            });
            return seq;
        },
        {
            errors: [],
            warnings: []
        }
    );

    if (summary.errors.length > 0 || summary.warnings.length > 0) {
        var warnings = !skipWarnings ? summary.warnings : []; // skip the warnings in that case

        var lines = summary.errors
            .concat(warnings)
            .map(function(msg) {
                return (
                    "\n" +
                    msg.type +
                    " " +
                    msg.ruleId +
                    "\n  " +
                    msg.filePath +
                    ":" +
                    msg.line +
                    ":" +
                    msg.column
                );
            })
            .join("\n");

        return lines + "\n";
    }
};

您將使用此自訂格式器和如下設定的環境變數執行 ESLint

FORMATTER_SKIP_WARNINGS=true eslint -f ./my-awesome-formatter.js src/

輸出將會是

error space-infix-ops
  src/configs/bundler.js:6:8

error semi
  src/configs/bundler.js:6:10

複雜的參數傳遞

如果您發現自訂格式器模式沒有為您想要格式化 ESLint 結果的方式提供足夠的選項,最好的選擇是使用 ESLint 的內建 JSON 格式器並將輸出傳送到第二個程式。例如

eslint -f json src/ | your-program-that-reads-JSON --option

在此範例中,your-program-that-reads-json 程式可以接受 ESLint 結果的原始 JSON 並在輸出其自己的結果格式之前處理它。您可以將盡可能多的命令列參數傳遞給該程式,以自訂輸出。

為終端機格式化

iTerm2Guake 這樣的現代終端機期望特定的結果格式在點擊時自動開啟檔案名稱。大多數終端機都支援此格式以達到此目的

file:line:column

打包自訂格式器

自訂格式器可以透過 npm 套件發佈。為此,請建立一個名稱為 eslint-formatter-* 格式的 npm 套件,其中 * 是您的格式器的名稱 (例如 eslint-formatter-awesome)。然後專案應該安裝套件並使用 -f (或 --format) 旗標使用自訂格式器,如下所示

eslint -f awesome src/

因為當指定的格式器不是以句點開頭時,ESLint 知道要尋找以 eslint-formatter- 開頭的套件,因此在使用已打包的自訂格式器時,您不需要輸入 eslint-formatter-

自訂格式器的 package.json 的提示

  • main 進入點必須是實作您的自訂格式器的 JavaScript 檔案。
  • 新增這些 keywords 來幫助使用者找到您的格式器
    • "eslint"
    • "eslint-formatter"
    • "eslintformatter"

請參閱 npm 上的所有自訂格式器

範例

摘要格式器

一個僅報告錯誤和警告總數的格式器看起來像這樣

module.exports = function(results, context) {
    // accumulate the errors and warnings
    var summary = results.reduce(
        function(seq, current) {
            seq.errors += current.errorCount;
            seq.warnings += current.warningCount;
            return seq;
        },
        { errors: 0, warnings: 0 }
    );

    if (summary.errors > 0 || summary.warnings > 0) {
        return (
            "Errors: " +
            summary.errors +
            ", Warnings: " +
            summary.warnings +
            "\n"
        );
    }

    return "";
};

使用上述摘要格式器執行 eslint

eslint -f ./my-awesome-formatter.js src/

將產生以下輸出

Errors: 2, Warnings: 4

詳細格式器

更複雜的報告可能如下所示

module.exports = function(results, context) {
    var results = results || [];

    var summary = results.reduce(
        function(seq, current) {
            current.messages.forEach(function(msg) {
                var logMessage = {
                    filePath: current.filePath,
                    ruleId: msg.ruleId,
                    ruleUrl: context.rulesMeta[msg.ruleId].docs.url,
                    message: msg.message,
                    line: msg.line,
                    column: msg.column
                };

                if (msg.severity === 1) {
                    logMessage.type = "warning";
                    seq.warnings.push(logMessage);
                }
                if (msg.severity === 2) {
                    logMessage.type = "error";
                    seq.errors.push(logMessage);
                }
            });
            return seq;
        },
        {
            errors: [],
            warnings: []
        }
    );

    if (summary.errors.length > 0 || summary.warnings.length > 0) {
        var lines = summary.errors
            .concat(summary.warnings)
            .map(function(msg) {
                return (
                    "\n" +
                    msg.type +
                    " " +
                    msg.ruleId + (msg.ruleUrl ? " (" + msg.ruleUrl + ")" : "") +
                    "\n  " +
                    msg.filePath +
                    ":" +
                    msg.line +
                    ":" +
                    msg.column
                );
            })
            .join("\n");

        return lines + "\n";
    }
};

當您使用此自訂格式器執行 ESLint 時

eslint -f ./my-awesome-formatter.js src/

輸出為

error space-infix-ops (https://eslint.dev.org.tw/docs/rules/space-infix-ops)
  src/configs/bundler.js:6:8
error semi (https://eslint.dev.org.tw/docs/rules/semi)
  src/configs/bundler.js:6:10
warning no-unused-vars (https://eslint.dev.org.tw/docs/rules/no-unused-vars)
  src/configs/bundler.js:5:6
warning no-unused-vars (https://eslint.dev.org.tw/docs/rules/no-unused-vars)
  src/configs/bundler.js:6:6
warning no-shadow (https://eslint.dev.org.tw/docs/rules/no-shadow)
  src/configs/bundler.js:65:32
warning no-unused-vars (https://eslint.dev.org.tw/docs/rules/no-unused-vars)
  src/configs/clean.js:3:6
變更語言