diff --git a/src/core/post-process.js b/src/core/post-process.js index 22ec19690a..ad4a4ae338 100644 --- a/src/core/post-process.js +++ b/src/core/post-process.js @@ -9,7 +9,7 @@ * want to be using a new module with your own profile. * - afterEnd: final thing that is called. */ -import { showError } from "./utils.js"; +import { makePluginUtils, showError } from "./utils.js"; export const name = "core/post-process"; @@ -24,9 +24,11 @@ export async function run(config) { } return isFunction; }) - .map(async f => { + .map(async (f, i) => { + const fnName = `${name}/${f.name || `[${i}]`}`; + const utils = makePluginUtils(fnName); try { - return await f(config, document); + return await f(config, document, utils); } catch (err) { const msg = `Function ${f.name} threw an error during \`postProcess\`.`; const hint = "See developer console."; diff --git a/src/core/pre-process.js b/src/core/pre-process.js index d55701160e..5eb830a721 100644 --- a/src/core/pre-process.js +++ b/src/core/pre-process.js @@ -8,7 +8,7 @@ * tested. Use with care, if you know what you're doing. Chances are you really * want to be using a new module with your own profile */ -import { showError } from "./utils.js"; +import { makePluginUtils, showError } from "./utils.js"; export const name = "core/pre-process"; @@ -23,9 +23,11 @@ export async function run(config) { } return isFunction; }) - .map(async f => { + .map(async (f, i) => { + const fnName = `${name}/${f.name || `[${i}]`}`; + const utils = makePluginUtils(fnName); try { - return await f(config, document); + return await f(config, document, utils); } catch (err) { const msg = `Function ${f.name} threw an error during \`preProcess\`.`; const hint = "See developer console."; diff --git a/src/core/utils.js b/src/core/utils.js index da6f86994f..373e7fc66b 100644 --- a/src/core/utils.js +++ b/src/core/utils.js @@ -896,6 +896,21 @@ export function showWarning(message, pluginName, options = {}) { pub("warn", new RespecError(message, pluginName, opts)); } +/** + * Creates showError, showWarning utilities for use in custom pre-process and + * post-process plugins. + * @param {string} pluginName + */ +export function makePluginUtils(pluginName) { + /** @typedef {Parameters[2]} Options */ + return { + /** @type {(message: string, options?: Options) => void} */ + showError: (msg, options) => showError(msg, pluginName, options), + /** @type {(message: string, options?: Options) => void} */ + showWarning: (msg, options) => showWarning(msg, pluginName, options), + }; +} + /** * Makes a string `coded`. * diff --git a/tests/spec/core/pre-process-spec.html b/tests/spec/core/pre-process-spec.html index 16724fd35f..f08ca1a7a5 100644 --- a/tests/spec/core/pre-process-spec.html +++ b/tests/spec/core/pre-process-spec.html @@ -15,6 +15,11 @@ }); } +function preWithWarning(_conf, _doc, utils) { + document.getElementById("pre-warning").innerHTML = "pass"; + utils.showWarning("This is a warning"); +} + function postSyncFunc() { document.getElementById("post-sync").innerHTML = "pass"; } @@ -28,6 +33,17 @@ }); } +function postWithDetailedError(_conf, _doc, utils) { + const el = document.getElementById("post-error"); + el.innerHTML = "pass"; + utils.showError("This is an error", { + hint: "This is a hint", + title: "This is a title", + details: "This is a detailed error message", + elements: [el], + }); +} + function afterEnd() { return new Promise(resolve => { setTimeout(() => { @@ -50,11 +66,13 @@ preSyncFunc, preAsyncFunc, noOp, {}, + preWithWarning ]; respecConfig.postProcess = [ postSyncFunc, postAsyncFunc, + postWithDetailedError, noOp, {}, ]; respecConfig.afterEnd = afterEnd; @@ -72,7 +90,9 @@

FAIL

FAIL

+

FAIL

FAIL

+

FAIL

FAIL

FAIL

diff --git a/tests/spec/core/pre-process-spec.js b/tests/spec/core/pre-process-spec.js index 5150c844c7..f0e091ca70 100644 --- a/tests/spec/core/pre-process-spec.js +++ b/tests/spec/core/pre-process-spec.js @@ -16,6 +16,35 @@ describe("Core - preProcess, postProcess, afterEnd", () => { expect(doc.getElementById("pre-async").innerHTML).toBe("pass"); expect(doc.getElementById("post-sync").innerHTML).toBe("pass"); expect(doc.getElementById("post-async").innerHTML).toBe("pass"); + expect(doc.getElementById("pre-warning").innerHTML).toBe("pass"); + expect(doc.getElementById("post-error").innerHTML).toBe("pass"); + }); + + it("can show warnings and errors", () => { + const warnings = doc.respec.warnings.filter(warn => + warn.plugin.startsWith("core/pre-process") + ); + expect(warnings).toHaveSize(1); + expect(warnings[0].plugin).toBe("core/pre-process/preWithWarning"); + expect(warnings[0].message).toBe("This is a warning"); + + const errors = doc.respec.errors.filter( + err => + err.plugin.startsWith("core/post-process") && + !err.message.startsWith("Every item") + ); + expect(errors).toHaveSize(1); + expect(errors[0]).toEqual( + jasmine.objectContaining({ + plugin: "core/post-process/postWithDetailedError", + message: "This is an error", + details: "This is a detailed error message", + hint: "This is a hint", + title: "This is a title", + name: "ReSpecError", + elements: [doc.getElementById("post-error")], + }) + ); }); it("runs afterEnd method", () => {