Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Customisable TS export names #468

Merged
merged 3 commits into from Nov 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Expand Up @@ -97,7 +97,12 @@ module.exports = {
// select what kind of types you want to generate (default `['enum', 'constant', 'literalId', 'literalKey']`)
types: ['constant', 'literalId'],
// render the types with `'` instead of `"` (default is `"`)
singleQuotes: true
singleQuotes: true,
// customise names used for the generated types and constants
enumName: 'MyIconType',
constantName: 'MY_CODEPOINTS'
// literalIdName: 'IconId',
// literalKeyName: 'IconKey'
}
},
// Use a custom Handlebars template
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -39,7 +39,7 @@
"prepublish": "build",
"dependencies": {
"change-case": "^4.1.2",
"cli-color": "^2.0.3",
"cli-color": "^2.0.2",
"commander": "^9.4.1",
"glob": "^8.0.3",
"handlebars": "^4.7.7",
Expand Down
Expand Up @@ -32,7 +32,7 @@ export const MY_ICONS_SET_CODEPOINTS: { [key in MyIconsSetKey]: string } = {
"
`;

exports[`\`TS\` asset generator generates no key string literal type if option passed like that 1`] = `
exports[`\`TS\` asset generator generates no key string literal type if option specifies it 1`] = `
"export enum MyIconsSet {
Foo = "foo",
Bar = "bar",
Expand Down
66 changes: 42 additions & 24 deletions src/generators/asset-types/__tests__/ts.ts
Expand Up @@ -33,42 +33,60 @@ const getCleanGen = async (options = {}) =>
);

describe('`TS` asset generator', () => {
test('renders expected TypeScript module content', async () => {
it('renders expected TypeScript module content', async () => {
expect(await tsGen.generate(mockOptions, null)).toMatchSnapshot();
});

test('correctly renders type declaration', async () => {
expect(await getCleanGen()).toContain(
'export type MyIconsSetId = | "foo" | "bar";'
it.each([
{ formatOptions: { ts: { literalIdName: undefined } } },
undefined,
{ formatOptions: { ts: { literalIdName: 'Foo' } } }
])('generates correct type declaration - config: %j', async options => {
expect(await getCleanGen({ ...mockOptions, ...options })).toContain(
`export type ${
options?.formatOptions?.ts?.literalIdName || 'MyIconsSetId'
} = | "foo" | "bar";`
);
});

test('correctly enum declaration', async () => {
expect(await getCleanGen()).toContain(
'export enum MyIconsSet { Foo = "foo", Bar = "bar", }'
it.each([
{ formatOptions: { ts: { enumName: undefined } } },
undefined,
{ formatOptions: { ts: { enumName: 'Foo' } } }
])('generates correct enum declaration - config: %j', async options => {
expect(await getCleanGen({ ...mockOptions, ...options })).toContain(
`export enum ${
options?.formatOptions?.ts?.enumName || 'MyIconsSet'
} { Foo = "foo", Bar = "bar", }`
);
});

test('correctly codepoints declaration', async () => {
expect(await getCleanGen()).toContain(
'export const MY_ICONS_SET_CODEPOINTS: { [key in MyIconsSet]: string }' +
' = { [MyIconsSet.Foo]: "4265", [MyIconsSet.Bar]: "1231", };'
);
});
it.each([
{ formatOptions: { ts: { constantName: undefined } } },
undefined,
{ formatOptions: { ts: { constantName: 'FOO' } } }
])(
'generates correct codepoints declaration - options: %j',
async options => {
expect(await getCleanGen({ ...mockOptions, ...options })).toContain(
`export const ${
options?.formatOptions?.ts?.constantName || 'MY_ICONS_SET_CODEPOINTS'
}: { [key in MyIconsSet]: string }` +
' = { [MyIconsSet.Foo]: "4265", [MyIconsSet.Bar]: "1231", };'
);
}
);

test('generates single quotes if format option passed', async () => {
it('generates single quotes if format option passed', async () => {
expect(
await tsGen.generate(
{
...mockOptions,
formatOptions: { ts: { singleQuotes: true } }
},
{ ...mockOptions, formatOptions: { ts: { singleQuotes: true } } },
null
)
).toMatchSnapshot();
});

test('generates no key string literal type if option passed like that', async () => {
it('generates no key string literal type if option specifies it', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand All @@ -87,7 +105,7 @@ describe('`TS` asset generator', () => {
);
});

test('generates constant with literalId if no enum generated', async () => {
it('generates constant with literalId if no enum generated', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand All @@ -108,7 +126,7 @@ describe('`TS` asset generator', () => {
expect(cleanResult).not.toContain('export enum MyIconsSet');
});

test('generates constant with literalKey if no enum generated', async () => {
it('generates constant with literalKey if no enum generated', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand All @@ -129,7 +147,7 @@ describe('`TS` asset generator', () => {
expect(cleanResult).not.toContain('export enum MyIconsSet');
});

test('generates constant only', async () => {
it('generates constant only', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand All @@ -150,7 +168,7 @@ describe('`TS` asset generator', () => {
expect(cleanResult).not.toContain('export enum MyIconsSet');
});

test('prevents enum keys that start with digits', async () => {
it('prevents enum keys that start with digits', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand All @@ -172,7 +190,7 @@ describe('`TS` asset generator', () => {
);
});

test('prevents enum keys that start with digits when digits and chars', async () => {
it('prevents enum keys that start with digits when digits and chars', async () => {
const result = await tsGen.generate(
{
...mockOptions,
Expand Down
16 changes: 8 additions & 8 deletions src/generators/asset-types/ts.ts
Expand Up @@ -27,7 +27,7 @@ const generateEnums = (
].join('\n');

const generateConstant = ({
codepointsName,
constantName,
enumName,
literalIdName,
literalKeyName,
Expand All @@ -36,7 +36,7 @@ const generateConstant = ({
quote = '"',
kind = {}
}: {
codepointsName: string;
constantName: string;
enumName: string;
literalIdName: string;
literalKeyName: string;
Expand All @@ -56,7 +56,7 @@ const generateConstant = ({
}

return [
`export const ${codepointsName}${varType} = {`,
`export const ${constantName}${varType} = {`,
Object.entries(enumKeys)
.map(([enumValue, enumKey]) => {
const key = kind.enum
Expand Down Expand Up @@ -95,11 +95,11 @@ const generator: FontGenerator = {
.map(kind => ({ [kind]: true }))
.reduce((prev, curr) => Object.assign(prev, curr), {});

const enumName = pascalCase(name);
const codepointsName = `${constantCase(name)}_CODEPOINTS`;
const literalIdName = `${pascalCase(name)}Id`;
const literalKeyName = `${pascalCase(name)}Key`;
const names = { enumName, codepointsName, literalIdName, literalKeyName };
const enumName = ts?.enumName || pascalCase(name);
const constantName = ts?.constantName || `${constantCase(name)}_CODEPOINTS`;
const literalIdName = ts?.literalIdName || `${pascalCase(name)}Id`;
const literalKeyName = ts?.literalKeyName || `${pascalCase(name)}Key`;
const names = { enumName, constantName, literalIdName, literalKeyName };

const enumKeys = generateEnumKeys(Object.keys(assets));

Expand Down
4 changes: 4 additions & 0 deletions src/types/format.ts
Expand Up @@ -17,6 +17,10 @@ interface JsonOptions {
interface TsOptions {
types?: ('enum' | 'constant' | 'literalId' | 'literalKey')[];
singleQuotes?: boolean;
enumName?: string;
constantName?: string;
literalIdName?: string;
literalKeyName?: string;
}

export interface FormatOptions {
Expand Down