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(react): add --directory option for React components #1729

Merged
merged 1 commit into from
Aug 16, 2019
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions docs/api-react/schematics/component.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,26 @@ ng generate component ...

### classComponent

Alias(es): C

Default: `false`

Type: `boolean`

Use class components instead of functional component
Use class components instead of functional component.

### directory

Alias(es): d

Type: `string`

Create the component under this directory (can be nested).

### export

Alias(es): e

Default: `false`

Type: `boolean`
Expand All @@ -35,14 +47,18 @@ The name of the component.

### pascalCaseFiles

Alias(es): P

Default: `false`

Type: `boolean`

Use pascal case component file name (e.g. App.tsx)
Use pascal case component file name (e.g. App.tsx).

### project

Alias(es): p

Type: `string`

The name of the project.
Expand All @@ -51,7 +67,7 @@ The name of the project.

Type: `boolean`

Generate library with routes
Generate a library with routes.

### skipTests

Expand All @@ -63,6 +79,8 @@ When true, does not create "spec.ts" test files for the new component.

### style

Alias(es): s

Default: `css`

Type: `string`
Expand Down
40 changes: 24 additions & 16 deletions packages/react/src/schematics/application/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,22 +76,8 @@ export default function(schema: Schema): Rule {
createApplicationFiles(options),
updateNxJson(options),
addProject(options),
options.e2eTestRunner === 'cypress'
? externalSchematic('@nrwl/cypress', 'cypress-project', {
...options,
name: options.name + '-e2e',
directory: options.directory,
project: options.projectName
})
: noop(),
options.unitTestRunner === 'jest'
? externalSchematic('@nrwl/jest', 'jest-project', {
project: options.projectName,
supportTsx: true,
skipSerializers: true,
setupFile: 'none'
})
: noop(),
addCypress(options),
addJest(options),
addStyledModuleDependencies(options),
addRouting(options, context),
addBabel(options),
Expand Down Expand Up @@ -215,6 +201,28 @@ function addProject(options: NormalizedSchema): Rule {
});
}

function addCypress(options: NormalizedSchema): Rule {
return options.e2eTestRunner === 'cypress'
? externalSchematic('@nrwl/cypress', 'cypress-project', {
...options,
name: options.name + '-e2e',
directory: options.directory,
project: options.projectName
})
: noop();
}

function addJest(options: NormalizedSchema): Rule {
return options.unitTestRunner === 'jest'
? externalSchematic('@nrwl/jest', 'jest-project', {
project: options.projectName,
supportTsx: true,
skipSerializers: true,
setupFile: 'none'
})
: noop();
}

function addStyledModuleDependencies(options: NormalizedSchema): Rule {
const extraDependencies = CSS_IN_JS_DEPENDENCIES[options.styledModule];

Expand Down
70 changes: 40 additions & 30 deletions packages/react/src/schematics/component/component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ describe('component', () => {
appTree
);

expect(tree.exists('libs/my-lib/src/lib/hello/hello.tsx')).toBeTruthy();
expect(
tree.exists('libs/my-lib/src/lib/hello/hello.spec.tsx')
).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello/hello.css')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello.spec.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello.css')).toBeTruthy();
});

it('should generate files for an app', async () => {
Expand All @@ -36,11 +34,9 @@ describe('component', () => {
appTree
);

expect(tree.exists('apps/my-app/src/app/hello/hello.tsx')).toBeTruthy();
expect(
tree.exists('apps/my-app/src/app/hello/hello.spec.tsx')
).toBeTruthy();
expect(tree.exists('apps/my-app/src/app/hello/hello.css')).toBeTruthy();
expect(tree.exists('apps/my-app/src/app/hello.tsx')).toBeTruthy();
expect(tree.exists('apps/my-app/src/app/hello.spec.tsx')).toBeTruthy();
expect(tree.exists('apps/my-app/src/app/hello.css')).toBeTruthy();
});

describe('--export', () => {
Expand All @@ -53,7 +49,7 @@ describe('component', () => {

const indexContent = tree.read('libs/my-lib/src/index.ts').toString();

expect(indexContent).toMatch(/lib\/hello\/hello/);
expect(indexContent).toMatch(/lib\/hello/);
});

it('should not export from an app', async () => {
Expand All @@ -65,7 +61,7 @@ describe('component', () => {

const indexContent = tree.read('libs/my-lib/src/index.ts').toString();

expect(indexContent).not.toMatch(/lib\/hello\/hello/);
expect(indexContent).not.toMatch(/lib\/hello/);
});
});

Expand All @@ -76,11 +72,9 @@ describe('component', () => {
{ name: 'hello', project: projectName, pascalCaseFiles: true },
appTree
);
expect(tree.exists('libs/my-lib/src/lib/hello/Hello.tsx')).toBeTruthy();
expect(
tree.exists('libs/my-lib/src/lib/hello/Hello.spec.tsx')
).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello/Hello.css')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/Hello.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/Hello.spec.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/Hello.css')).toBeTruthy();
});
});

Expand All @@ -93,13 +87,11 @@ describe('component', () => {
);

expect(
tree.exists('libs/my-lib/src/lib/hello/hello.styled-components')
tree.exists('libs/my-lib/src/lib/hello.styled-components')
).toBeFalsy();
expect(tree.exists('libs/my-lib/src/lib/hello/hello.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello.tsx')).toBeTruthy();

const content = tree
.read('libs/my-lib/src/lib/hello/hello.tsx')
.toString();
const content = tree.read('libs/my-lib/src/lib/hello.tsx').toString();
expect(content).toContain('styled-components');
expect(content).toContain('<StyledHello>');
});
Expand All @@ -125,13 +117,11 @@ describe('component', () => {
);

expect(
tree.exists('libs/my-lib/src/lib/hello/hello.@emotion/styled')
tree.exists('libs/my-lib/src/lib/hello.@emotion/styled')
).toBeFalsy();
expect(tree.exists('libs/my-lib/src/lib/hello/hello.tsx')).toBeTruthy();
expect(tree.exists('libs/my-lib/src/lib/hello.tsx')).toBeTruthy();

const content = tree
.read('libs/my-lib/src/lib/hello/hello.tsx')
.toString();
const content = tree.read('libs/my-lib/src/lib/hello.tsx').toString();
expect(content).toContain('@emotion/styled');
expect(content).toContain('<StyledHello>');
});
Expand All @@ -157,9 +147,7 @@ describe('component', () => {
appTree
);

const content = tree
.read('libs/my-lib/src/lib/hello/hello.tsx')
.toString();
const content = tree.read('libs/my-lib/src/lib/hello.tsx').toString();
expect(content).toContain('react-router-dom');
expect(content).toMatch(/<Route\s*path="\/"/);
expect(content).toMatch(/<Link\s*to="\/"/);
Expand All @@ -168,4 +156,26 @@ describe('component', () => {
expect(packageJSON.dependencies['react-router-dom']).toBeDefined();
});
});

describe('--directory', () => {
it('should create component under the directory', async () => {
const tree = await runSchematic(
'component',
{ name: 'hello', project: projectName, directory: 'components' },
appTree
);

expect(tree.exists('/libs/my-lib/src/lib/components/hello.tsx'));
});

it('should create with nested directories', async () => {
const tree = await runSchematic(
'component',
{ name: 'helloWorld', project: projectName, directory: 'foo' },
appTree
);

expect(tree.exists('/libs/my-lib/src/lib/foo/bar/faz/hello-world.tsx'));
});
});
});
24 changes: 21 additions & 3 deletions packages/react/src/schematics/component/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
url
} from '@angular-devkit/schematics';
import { Schema } from './schema';
import { getWorkspace, names, formatFiles } from '@nrwl/workspace';
import { formatFiles, getWorkspace, names } from '@nrwl/workspace';
import {
addDepsToPackageJson,
addGlobal,
Expand Down Expand Up @@ -108,7 +108,11 @@ function addExportsToBarrel(options: NormalizedSchema): Rule {
addGlobal(
indexSourceFile,
indexFilePath,
`export * from './lib/${options.name}/${options.fileName}';`
options.directory
? `export * from './lib/${options.directory}/${
options.fileName
}';`
: `export * from './lib/${options.fileName}';`
)
);
}
Expand Down Expand Up @@ -143,11 +147,25 @@ function normalizeOptions(
);
}

const slashes = ['/', '\\'];
slashes.forEach(s => {
if (componentFileName.indexOf(s) !== -1) {
const [name, ...rest] = componentFileName.split(s).reverse();
let suggestion = rest.map(x => x.toLowerCase()).join(s);
if (options.directory) {
suggestion = `${options.directory}${s}${suggestion}`;
}
throw new Error(
`Found "${s}" in the component name. Did you mean to use the --directory option (e.g. \`nx g c ${name} --directory ${suggestion}\`)?`
);
}
});

return {
...options,
directory: options.directory || '',
styledModule,
className,
name: fileName,
fileName: componentFileName,
projectSourceRoot
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class <%= className %> extends Component<<%= className %>Props> {
render() {
return (
<<%= wrapper %>>
<h1>Welcome to <%= name %> component!</h1>
<p>Welcome to <%= name %> component!</p>
<% if (routing) { %>
<ul>
<li><Link to="/"><%= name %> root</Link></li>
Expand Down
1 change: 1 addition & 0 deletions packages/react/src/schematics/component/schema.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export interface Schema {
project: string;
style?: string;
skipTests?: boolean;
directory?: string;
export?: boolean;
pascalCaseFiles?: boolean;
classComponent?: boolean;
Expand Down
18 changes: 14 additions & 4 deletions packages/react/src/schematics/component/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"project": {
"type": "string",
"description": "The name of the project.",
"alias": "p",
"$default": {
"$source": "projectName"
},
Expand All @@ -24,6 +25,7 @@
"style": {
"description": "The file extension to be used for style files.",
"type": "string",
"alias": "s",
"default": "css",
"x-prompt": {
"message": "Which stylesheet format would you like to use?",
Expand Down Expand Up @@ -58,25 +60,33 @@
"description": "When true, does not create \"spec.ts\" test files for the new component.",
"default": false
},
"directory": {
"type": "string",
"description": "Create the component under this directory (can be nested).",
"alias": "d"
},
"export": {
"type": "boolean",
"default": false,
"description": "When true, the component is exported from the project index.ts (if it exists).",
"alias": "e",
"default": false,
"x-prompt": "Should this component be exported in the project?"
},
"pascalCaseFiles": {
"type": "boolean",
"description": "Use pascal case component file name (e.g. App.tsx)",
"description": "Use pascal case component file name (e.g. App.tsx).",
"alias": "P",
"default": false
},
"classComponent": {
"type": "boolean",
"description": "Use class components instead of functional component",
"alias": "C",
"description": "Use class components instead of functional component.",
"default": false
},
"routing": {
"type": "boolean",
"description": "Generate library with routes"
"description": "Generate a library with routes."
}
},
"required": ["name", "project"]
Expand Down
Loading