Skip to content

Commit

Permalink
feat: Customisable TS export names (#468)
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Dependencies upgraded
  • Loading branch information
tancredi committed Nov 18, 2022
1 parent 0c5d532 commit 24cf632
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 36 deletions.
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

0 comments on commit 24cf632

Please sign in to comment.