Skip to content

Commit

Permalink
functionality to add tailwindcss packages to package.json file
Browse files Browse the repository at this point in the history
  • Loading branch information
Sanjiv Kumar committed Sep 16, 2020
1 parent f8e7acf commit 202e58e
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 53 deletions.
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "@ngx/tailwindcss",
"name": "@ngx/tailwindcss-schematic",
"version": "0.0.1",
"description": "Simple Angular Schematic to add tailwindcss to any Angular application",
"scripts": {
Expand All @@ -8,7 +8,9 @@
"test": "npm run build && jasmine src/**/*_spec.js"
},
"keywords": [
"schematics"
"angular",
"schematics",
"tailwindcss"
],
"author": "",
"license": "MIT",
Expand All @@ -24,4 +26,4 @@
"@types/jasmine": "~3.5.0",
"jasmine": "^3.5.0"
}
}
}
113 changes: 73 additions & 40 deletions src/ng-add/index.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,95 @@
import { normalize, strings } from '@angular-devkit/core';
import { workspace } from '@angular-devkit/core/src/experimental';
import {
apply,
chain,
mergeWith,
move,
Rule,
SchematicContext,
SchematicsException,
template,
Tree,
url,
} from '@angular-devkit/schematics';
import { chain, Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
import { addPackageJsonDependency, NodeDependency, NodeDependencyType } from '@schematics/angular/utility/dependencies';
import { Schema } from './schema';
import { tailwindcssDependencies } from './utils';

/** Rule factory: returns a rule (function) */
export default function (options: Schema): Rule {
// this is a rule (function). It takes a `tree` and returns updated `tree`.
return async (tree: Tree, _context: SchematicContext) => {
return (tree: Tree, context: SchematicContext) => {
console.log('schematic works', options);
// Read `angular.json` as buffer
const workspaceConfigBuffer = tree.read('angular.json');
if (!workspaceConfigBuffer) {
throw new SchematicsException('Could not find an Angular workspace configuration');
}
// parse config only when not null
const workspaceConfig: workspace.WorkspaceSchema = JSON.parse(workspaceConfigBuffer.toString());
// if project is not passed (--project), use default project name
if (!options.project && workspaceConfig.defaultProject) {
options.project = workspaceConfig.defaultProject;
}
const projectName = options.project as string;
// select project from projects array in `angular.json` file
const project: workspace.WorkspaceProject = workspaceConfig.projects[projectName];
if (!project) {
throw new SchematicsException(`Project ${projectName} is not defined in this workspace.`);
}
const projectType = project.projectType === 'application' ? 'app' : 'lib';
// // parse config only when not null
// const workspaceConfig: workspace.WorkspaceSchema = JSON.parse(workspaceConfigBuffer.toString());
// // if project is not passed (--project), use default project name
// if (!options.project && workspaceConfig.defaultProject) {
// options.project = workspaceConfig.defaultProject;
// }
// const projectName = options.project as string;
// const projectName = options.project as string;
// // select project from projects array in `angular.json` file
// const project: workspace.WorkspaceProject = workspaceConfig.projects[projectName];
// if (!project) {
// throw new SchematicsException(`Project ${projectName} is not defined in this workspace.`);
// }
// const projectType = project.projectType === 'application' ? 'app' : 'lib';
// Path to create the file
const defaultPath = `${project.sourceRoot}/${projectType}`;
// const defaultPath = `${project.sourceRoot}/${projectType}`;

// get hold of our templates files
const sourceTemplates = url('./files');
// const sourceTemplates = url('./files');
/**
* `template` rule processes templates and returns rule.
* The template helpers like `dasherize` or `classify` are available because we’re spreading `strings` object into the `options` objectand then we’re passing into the template
*/
const sourceParamteterizedTemplates = apply(sourceTemplates, [
template({
...options,
...strings,
name: options.name,
}),
// move file to resolved path
move(normalize(defaultPath as string)),
]);
// const sourceParamteterizedTemplates = apply(sourceTemplates, [
// template({
// ...options,
// ...strings,
// name: options.name,
// }),
// // move file to resolved path
// move(normalize(defaultPath as string)),
// ]);
// mergeWith returns a Rule so it can be called with tree and context (not required though)
// merge our template into tree.
return chain([mergeWith(sourceParamteterizedTemplates)]);
return chain([addDependencies(options)])(tree, context);
};
}

/**
* Add required dependencies to package.json file.
*/
function addDependencies(options: Schema): Rule {
const deps = [...tailwindcssDependencies];

if (options.cssType !== 'css') {
deps.push(`postcss-${options.cssType}`);
}
return (tree: Tree, context: SchematicContext) => {
deps.map((dependencyName: string) => {
const nodeDependency: NodeDependency = nodeDependencyFactory(dependencyName, options);
addPackageJsonDependency(tree, nodeDependency);
context.logger.info(`✅️ Added ${nodeDependency.name}@${nodeDependency.version} to ${nodeDependency.type}`);
return tree;
});
};
}

// Install dependencies
// function install(): Rule {
// return (tree: Tree, context: SchematicContext) => {
// // Install the dependency
// context.addTask(new NodePackageInstallTask());
// context.logger.info('✅️ Installed dependencies');
// return tree;
// };
// }

function nodeDependencyFactory(dependencyName: string, options: Schema): NodeDependency {
// default version : latest
let version = 'latest';
if (dependencyName === 'tailwindcss' && options.tailwindcssVersion) {
version = options.tailwindcssVersion;
}
return {
type: NodeDependencyType.Dev,
name: dependencyName,
version: version,
overwrite: false,
};
}
47 changes: 38 additions & 9 deletions src/ng-add/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,50 @@
"description": "Standalone schematic to add TailwindCSS to Angular application",
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "The name of the person.",
"$default": {
"$source": "argv",
"index": 0
},
"x-prompt": "Who you want to greet?"
},
"project": {
"type": "string",
"description": "The name of the project where we want to add files.",
"$default": {
"$source": "projectName"
}
},
"cssType": {
"description": "The file extension or preprocessor to use for style files.",
"type": "string",
"default": "css",
"enum": [
"css",
"scss",
"sass",
"less"
],
"x-prompt": {
"message": "Which stylesheet type would you like to use?",
"type": "list",
"items": [
{
"value": "css",
"label": "CSS"
},
{
"value": "scss",
"label": "SCSS [ https://sass-lang.com/documentation/syntax#scss]"
},
{
"value": "sass",
"label": "Sass [ https://sass-lang.com/documentation/syntax#the-indented-syntax]"
},
{
"value": "less",
"label": "Less [ http://lesscss.org]"
}
]
}
},
"tailwindcssVersion": {
"type": "string",
"description": "The TailwindCSS version to be installed.",
"default": "latest"
}
},
"required": []
Expand Down
13 changes: 12 additions & 1 deletion src/ng-add/schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
export interface Schema {
name: string;
/** Name of the project */
project: string;
/**
* preprocessor for css or type
* @default css
*/
cssType: cssType;
/**
* tailwindcss version to be installed
* @default latest
*/
tailwindcssVersion: string;
}

export type cssType = 'css' | 'scss' | 'sass' | 'less';
6 changes: 6 additions & 0 deletions src/ng-add/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const tailwindcssDependencies = [
'tailwindcss',
'postcss-import',
'postcss-loader',
'@angular-builders/custom-webpack',
];

0 comments on commit 202e58e

Please sign in to comment.