@mihalcan/shallow-render-schematics
Version:
Add shallow-render to an Angular CLI project
119 lines (102 loc) • 3.78 kB
text/typescript
// tslint:disable:linebreak-style
import { JsonObject, Path, strings } from '@angular-devkit/core';
import {
apply,
chain,
externalSchematic,
MergeStrategy,
mergeWith,
move,
Rule,
SchematicContext,
template,
Tree,
url,
} from '@angular-devkit/schematics';
import { Schema as ShallowComponentOptions } from '@schematics/angular/component/schema';
import { getWorkspace, buildDefaultPath } from '@schematics/angular/utility/workspace';
import * as findModule from '@schematics/angular/utility/find-module';
import { parseName } from '@schematics/angular/utility/parse-name';
interface ModuleDetails {
moduleName: string;
relativePath: string;
}
export const defaultModuleDetails: ModuleDetails = {
moduleName: '',
relativePath: '',
};
// tslint:disable-next-line:no-default-export
export default function (options: ShallowComponentOptions): Rule {
return async (host: Tree, context: SchematicContext) => {
// no reason to continue if spec file is not required
if (options.skipTests) {
return externalSchematic('@schematics/angular', 'component', options);
}
const workspace = await getWorkspace(host);
const project = workspace.projects.get(options.project as string);
if (options.path === undefined && project) {
options.path = buildDefaultPath(project);
}
const parsedPath = parseName(options.path as string, options.name);
options.name = parsedPath.name;
options.path = parsedPath.path;
options.selector = options.selector || buildSelector(options, project && project.prefix || '');
const moduleDetails = options.skipImport
? defaultModuleDetails
: getModuleDetails(options, host);
const templateSource = apply(url('./files'), [
template({
...strings,
'if-flat': (s: string) => (options.flat ? '' : s),
...options,
...moduleDetails,
}),
move(parsedPath.path),
]);
const angularComponentOptions = {
...options,
...getAngularComponentExtensions(workspace.extensions),
...getAngularComponentExtensions(project?.extensions)
};
return chain([
externalSchematic('@schematics/angular', 'component', {
...angularComponentOptions,
skipTests: true
}),
mergeWith(templateSource, MergeStrategy.Default),
]);
};
}
function getModuleDetails(
options: ShallowComponentOptions,
host: Tree
): ModuleDetails {
const modulePath = findModule.findModuleFromOptions(host, options) as Path;
// tslint:disable-next-line:prefer-template
const componentPath =
`/${options.path}/` +
(options.flat ? '' : strings.dasherize(options.name) + '/') +
strings.dasherize(options.name) +
'.component';
const relativePath = findModule.buildRelativePath(componentPath, modulePath);
const moduleFileName = modulePath.split('/').pop() as string;
const moduleName = moduleFileName.replace('.module.ts', '')
const moduleRelativePath = relativePath.replace('.module.ts', '');
return { relativePath: moduleRelativePath, moduleName };
}
function getAngularComponentExtensions(extensions: any) {
if (extensions?.schematics && extensions.schematics['@schematics/angular:component'])
{
return extensions.schematics['@schematics/angular:component']
}
return {};
}
function buildSelector(options: ShallowComponentOptions, projectPrefix: string) {
let selector = strings.dasherize(options.name);
if (options.prefix) {
selector = `${options.prefix}-${selector}`;
} else if (options.prefix === undefined && projectPrefix) {
selector = `${projectPrefix}-${selector}`;
}
return selector;
}