Skip to content

Commit

Permalink
feat: Add ability to customise type displays
Browse files Browse the repository at this point in the history
  • Loading branch information
Sidnioulz committed Nov 28, 2022
1 parent 4433a20 commit 1cd7f74
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 10 deletions.
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,43 @@ export default function (plop) {
});
};
```
## setActionTypeDisplay
`setActionTypeDisplay` allows you to change the characters shown on the output of a specific action. For instance, the `add` action's output is prefixed with `++`.

You may need to write a custom action that fetches a file from an API and adds it, and you may want to use the `++` prefix for consistency. This could be done with the following:

``` javascript
import chalk from 'chalk';

export default function (plop) {
// Define your custom action that asynchronously adds a file
plop.setActionType('fetchAndAddAsync', function (answers, config, plop) {
return new Promise((resolve, reject) => {
if (success) {
resolve('success status message');
} else {
reject('error message');
}
});
});

// Use the same action type as 'add' for consistency
plop.setActionTypeDisplay('fetchAndAddAsync', chalk.green('++'));
};
```

By default, the following type displays are set:

``` javascript
const typeDisplay = {
function: chalk.yellow("->"),
add: chalk.green("++"),
addMany: chalk.green("+!"),
modify: `${chalk.green("+")}${chalk.red("-")}`,
append: chalk.green("_+"),
skip: chalk.green("--"),
};
```

## setPrompt
[Inquirer](https://github.com/SBoudrias/Inquirer.js) provides many types of prompts out of the box, but it also allows developers to build prompt plugins. If you'd like to use a prompt plugin, you can register it with `setPrompt`. For more details see the [Inquirer documentation for registering prompts](https://github.com/SBoudrias/Inquirer.js#inquirerregisterpromptname-prompt). Also check out the [plop community driven list of custom prompts](https://github.com/plopjs/awesome-plop#inquirer-prompts).
Expand Down
20 changes: 18 additions & 2 deletions packages/node-plop/src/node-plop.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
const generators = {};
const partials = {};
const actionTypes = {};
const actionTypeDisplays = {};
const helpers = Object.assign(
{
pkg: (propertyPath) => _get(pkgJson, propertyPath, ""),
Expand All @@ -38,10 +39,13 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
};
const setPartial = (name, str) => {
partials[name] = str;
};
}
const setActionTypeDisplay = (name, typeDisplay) => {
actionTypeDisplays[name] = typeDisplay;
}
const setActionType = (name, fn) => {
actionTypes[name] = fn;
};
}

function renderString(template, data) {
Object.keys(helpers).forEach((h) =>
Expand All @@ -57,6 +61,7 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
const getHelper = (name) => helpers[name];
const getPartial = (name) => partials[name];
const getActionType = (name) => actionTypes[name];
const getActionTypeDisplay = (name) => actionTypeDisplays[name];
const getGenerator = (name) => generators[name];
function setGenerator(name = "", config = {}) {
// if no name is provided, use a default
Expand All @@ -75,6 +80,7 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
Object.keys(helpers).filter((h) => !baseHelpers.includes(h));
const getPartialList = () => Object.keys(partials);
const getActionTypeList = () => Object.keys(actionTypes);
const getActionTypeDisplayList = () => Object.keys(actionTypeDisplays);
function getGeneratorList() {
return Object.keys(generators).map(function (name) {
const { description } = generators[name];
Expand Down Expand Up @@ -118,6 +124,7 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
helpers: false,
partials: false,
actionTypes: false,
actionTypeDisplays: false,
},
includeCfg
);
Expand Down Expand Up @@ -147,6 +154,12 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
setActionType,
proxy.getActionType
);
loadAsset(
proxy.getActionTypeDisplayList(),
includeCfg === true || include.actionTypeDisplays,
setActionTypeDisplay,
proxy.getActionTypeDisplay
);
})
);
}
Expand Down Expand Up @@ -202,6 +215,9 @@ async function nodePlop(plopfilePath = "", plopCfg = {}) {
setActionType,
getActionType,
getActionTypeList,
setActionTypeDisplay,
getActionTypeDisplay,
getActionTypeDisplayList,

// path context methods
setPlopfilePath,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,5 +61,25 @@ describe("imported-custom-action", function () {
expect(results.failures[0].error.startsWith("Path does not exist")).toBe(
true
);
});
})

test("imported custom action can define a custom type display string", async function () {
const plop = await nodePlop()
const testFilePath = path.resolve(testSrcPath, "test.txt")
plop.setActionType("custom-del", customAction)
plop.setActionTypeDisplay("custom-del", "><")

// add the file
const addTestFile = { type: "add", path: testFilePath }
// remove the file
const deleteTestFile = { type: "custom-del", path: testFilePath }

const generator = plop.setGenerator("", {
actions: [addTestFile, deleteTestFile],
})

expect(typeof plop.getActionType("custom-del")).toBe("function")
expect(typeof plop.getActionTypeDisplay("custom-del")).toBe("string")
expect(plop.getActionTypeDisplay("custom-del")).toBe("><")
})
});
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,23 @@ describe("load-assets-from-plopfile", function () {
helpers: true,
partials: true,
actionTypes: true,
actionTypeDisplays: true,
}
);

const gNameList = plop.getGeneratorList().map((g) => g.name);
expect(gNameList.length).toBe(3);
expect(plop.getHelperList().length).toBe(3);
expect(plop.getPartialList().length).toBe(3);
expect(plop.getActionTypeList().length).toBe(1);
expect(plop.getActionTypeList().length).toBe(2);
expect(plop.getActionTypeDisplayList().length).toBe(1);
expect(gNameList.includes("test-generator1")).toBe(true);
expect(plop.getHelperList().includes("test-helper2")).toBe(true);
expect(plop.getPartialList().includes("test-partial3")).toBe(true);
expect(plop.getActionTypeList().includes("test-actionType1")).toBe(true);
expect(plop.getActionTypeList().includes("test-actionType2")).toBe(true);
expect(plop.getActionTypeDisplayList().includes("test-actionType1")).toBe(false);
expect(plop.getActionTypeDisplayList().includes("test-actionType2")).toBe(true);
});

test("plop.load passes a config option that can be used to include all the plopfile output", async function () {
Expand All @@ -101,11 +106,15 @@ describe("load-assets-from-plopfile", function () {
expect(gNameList.length).toBe(3);
expect(plop.getHelperList().length).toBe(3);
expect(plop.getPartialList().length).toBe(3);
expect(plop.getActionTypeList().length).toBe(1);
expect(plop.getActionTypeList().length).toBe(2);
expect(plop.getActionTypeDisplayList().length).toBe(1);
expect(gNameList.includes("test-generator1")).toBe(true);
expect(plop.getHelperList().includes("test-helper2")).toBe(true);
expect(plop.getPartialList().includes("test-partial3")).toBe(true);
expect(plop.getActionTypeList().includes("test-actionType1")).toBe(true);
expect(plop.getActionTypeList().includes("test-actionType2")).toBe(true);
expect(plop.getActionTypeDisplayList().includes("test-actionType1")).toBe(false);
expect(plop.getActionTypeDisplayList().includes("test-actionType2")).toBe(true);
});

test("plop.load should import functioning assets", async function () {
Expand All @@ -124,6 +133,7 @@ describe("load-assets-from-plopfile", function () {
expect(plop.getHelper("test-helper2")("test")).toBe("helper 2: test");
expect(plop.getPartial("test-partial3")).toBe("partial 3: {{name}}");
expect(plop.getActionType("test-actionType1")()).toBe("test");
expect(plop.getActionType("test-actionType2")()).toBe("test");
});

test("plop.load can include only helpers", async function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export default function (plop, config = {}) {
plop.setPartial(`${cfg.prefix}partial3`, "partial 3: {{name}}");

plop.setActionType(`${cfg.prefix}actionType1`, () => "test");
plop.setActionType(`${cfg.prefix}actionType2`, () => "test");
plop.setActionTypeDisplay(`${cfg.prefix}actionType2`, "><");

const generatorObject = {
actions: [{ type: "add", path: "src/{{name}}.txt" }],
Expand Down
Empty file modified packages/plop/bin/plop.js
100644 → 100755
Empty file.
6 changes: 6 additions & 0 deletions packages/plop/src/console-out.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ const typeDisplay = {
append: chalk.green("_+"),
skip: chalk.green("--"),
};

const addToTypeDisplay = (name, characters) => {
typeDisplay[name] = characters
}

const typeMap = (name, noMap) => {
const dimType = chalk.dim(name);
return noMap ? dimType : typeDisplay[name] || dimType;
Expand All @@ -126,6 +131,7 @@ export {
chooseOptionFromList,
displayHelpScreen,
createInitPlopfile,
addToTypeDisplay,
typeMap,
getHelpMessage,
};
6 changes: 5 additions & 1 deletion packages/plop/src/plop.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ async function run(env, _, passArgsBeforeDashes) {
const { generatorName, bypassArr, plopArgV } = getBypassAndGenerator(
plop,
passArgsBeforeDashes
);
)
const actionTypeDisplays = plop.getActionTypeDisplayList();
actionTypeDisplays.forEach((type) => {
out.addToTypeDisplay(type, plop.getActionTypeDisplay(type));
});

// look up a generator and run it with calculated bypass data
const runGeneratorByName = (name) => {
Expand Down
24 changes: 20 additions & 4 deletions packages/plop/tests/actions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ test("Plop to add and rename files", async () => {

const data = fs.readFileSync(expectedFilePath, "utf8");

expect(data).toMatch(/Hello/);
expect(data).toMatch(/Hello/)
expect(await findByText("++ /output/new-output.txt")).toBeInTheConsole()
});

test("Plop to add and change file contents", async () => {
Expand All @@ -38,7 +39,7 @@ test("Plop to add and change file contents", async () => {
cwd: resolve(__dirname, "./examples/add-action"),
});

expect(await findByText("What's your name?")).toBeInTheConsole();
expect(await findByText("What's your name?")).toBeInTheConsole()

userEvent.keyboard("Corbin");
userEvent.keyboard("[Enter]");
Expand All @@ -47,10 +48,25 @@ test("Plop to add and change file contents", async () => {

const data = await fs.promises.readFile(expectedFilePath, "utf8");

expect(data).toMatch(/Hi Corbin!/);
expect(data).toMatch(/Hi Corbin!/)
expect(await findByText("++ /output/new-output.txt")).toBeInTheConsole()
});

test.todo("Test modify");
test.todo("Test append");
test.todo("Test built-in helpers");
test.todo("Test custom helpers");
test.todo("Test custom helpers")

test("Plop to display a custom string for a given action type", async () => {
const expectedFilePath = await getFilePath(
"./examples/custom-action-display/output/out.txt"
)

const { findByText } = await renderPlop(["addFile"], {
cwd: resolve(__dirname, "./examples/custom-action-display"),
})

await waitFor(() => fs.promises.stat(expectedFilePath))

expect(await findByText(">< /output/out.txt")).toBeInTheConsole()
})
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"name": "plop-example-custom-action-display",
"type": "module",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
}
14 changes: 14 additions & 0 deletions packages/plop/tests/examples/custom-action-display/plopfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function (plop) {
plop.setActionTypeDisplay("add", "><");
plop.setGenerator("addFile", {
description: "Add a file",
prompts: [],
actions: [
{
type: "add",
path: "./output/out.txt",
templateFile: "./templates/to-add.txt",
},
],
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello

0 comments on commit 1cd7f74

Please sign in to comment.