Skip to content

Commit

Permalink
feat(stylesheet): select css stylesheet format
Browse files Browse the repository at this point in the history
* update styles
* add new webpack.config.js for css
* install postcss-scss only for scss format
  • Loading branch information
marcjulian committed Oct 23, 2020
1 parent ef07ab9 commit f8c026a
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 65 deletions.
21 changes: 11 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,21 @@ ng add @garygrossgarten/ngx-tailwind --tailwindVersion 1.9.5

All available flags:

| Flag |  Description | Type |  Default |
| ----------------------- | -------------------------------------------- | --------- | ------------------------- |
|  `ngxBuildPlusVersion` | The ngx-build-plus version to be installed. | `string` | `latest` |
|  `project` | The project to initialize with Tailwind CSS. | `string` | **First** Angular project |
|  `postcssImportVersion` | The postcss-import version to be installed. | `string` | `12.0.1` |
|  `postcssLoaderVersion` | The postcss-loader version to be installed. | `string` | `latest` |
|  `postcssScssVersion` | The postcss-scss version to be installed. | `string` | `latest` |
|  `skipTailwindInit` | Skip initializing Tailwind. | `boolean` | `false` |
|  `tailwindVersion` | The Tailwind version to be installed. | `string` | `latest` |
| Flag |  Description | Type |  Default |
| ----------------------- | ---------------------------------------------------------- | --------- | ------------------------- |
|  `cssFormat` | The file extension or preprocessor to use for style files. | `css` |  `scss` | `css` |
|  `ngxBuildPlusVersion` | The ngx-build-plus version to be installed. | `string` | `latest` |
|  `project` | The project to initialize with Tailwind CSS. | `string` | **First** Angular project |
|  `postcssImportVersion` | The postcss-import version to be installed. | `string` | `12.0.1` |
|  `postcssLoaderVersion` | The postcss-loader version to be installed. | `string` | `latest` |
|  `postcssScssVersion` | The postcss-scss version to be installed. | `string` | `latest` |
|  `skipTailwindInit` | Skip initializing Tailwind. | `boolean` | `false` |
|  `tailwindVersion` | The Tailwind version to be installed. | `string` | `latest` |

Advanced usage

```bash
ng add @garygrossgarten/ngx-tailwind --tailwindVersion 1.9.5 --ngxBuildPlusVersion 10.1.1 --postcssImportVersion 12.0.1 --postcssLoaderVersion 4.0.4 --postcssScssVersion 3.0.2
ng add @garygrossgarten/ngx-tailwind --cssFormat scss --tailwindVersion 1.9.5 --ngxBuildPlusVersion 10.1.1 --postcssImportVersion 12.0.1 --postcssLoaderVersion 4.0.4 --postcssScssVersion 3.0.2
```

## Developing
Expand Down
11 changes: 6 additions & 5 deletions angular-workspace/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"build": {
"builder": "ngx-build-plus:browser",
"options": {
"extraWebpackConfig": "webpack.config.js",
"outputPath": "dist/angular-workspace",
"index": "src/index.html",
"main": "src/main.ts",
Expand All @@ -30,8 +31,7 @@
"styles": [
"src/styles.scss"
],
"scripts": [],
"extraWebpackConfig": "./webpack.config.js"
"scripts": []
},
"configurations": {
"production": {
Expand Down Expand Up @@ -67,8 +67,8 @@
"serve": {
"builder": "ngx-build-plus:dev-server",
"options": {
"browserTarget": "angular-workspace:build",
"extraWebpackConfig": "./webpack.config.js"
"extraWebpackConfig": "webpack.config.js",
"browserTarget": "angular-workspace:build"
},
"configurations": {
"production": {
Expand All @@ -83,8 +83,9 @@
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"builder": "ngx-build-plus:karma",
"options": {
"extraWebpackConfig": "webpack.config.js",
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
Expand Down
4 changes: 3 additions & 1 deletion angular-workspace/src/styles.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
@import 'tailwindcss/base';

@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

@import 'tailwindcss/utilities';
/* You can add global styles to this file, and also import other style files */
22 changes: 22 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"dependencies": {
"@angular-devkit/core": "^10.1.2",
"@angular-devkit/schematics": "^10.1.2",
"@angular/cdk": "~10.2.5",
"@schematics/angular": "^10.1.2"
},
"devDependencies": {
Expand Down
169 changes: 120 additions & 49 deletions src/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {
mergeWith,
} from '@angular-devkit/schematics';
import { Schema } from './schema';
import {
getProjectFromWorkspace,
getProjectStyleFile,
getTargetsByBuilderName,
} from '@angular/cdk/schematics';
import {
NodePackageInstallTask,
RunSchematicTask,
Expand All @@ -17,37 +22,51 @@ import {
addPackageJsonDependency,
NodeDependencyType,
} from '@schematics/angular/utility/dependencies';
import { getWorkspace } from '@schematics/angular/utility/workspace';
import { ProjectDefinition } from '@angular-devkit/core/src/workspace';
import {
getWorkspace as getWorkspaceConfig,
updateWorkspace,
} from '@schematics/angular/utility/config';
import { InsertChange } from '@schematics/angular/utility/change';
import { Builders } from '@schematics/angular/utility/workspace-models';

const NGX_BUILD_PLUS_BUILDER_TARGET = 'ngx-build-plus:browser';
const NGX_BUILD_PLUS_DEV_BUILDER_TARGET = 'ngx-build-plus:dev-server';
const NGX_BUILD_PLUS_KARMA_BUILDER_TARGET = 'ngx-build-plus:karma';

export function ngAdd(_options: Schema): Rule {
return async (host: Tree) => {
const workspace = await getWorkspace(host);
const projectName =
_options.project || Array.from(workspace.projects)[0][0];
if (!projectName) {
throw new SchematicsException('Option "project" is required.');
}
console.log('project name', projectName);
const workspace = getWorkspaceConfig(host);
const project = getProjectFromWorkspace(workspace, _options.project);

const project = workspace.projects.get(projectName);
const projectName = _options.project || Object.keys(workspace.projects)[0];

if (!project) {
throw new SchematicsException(
`Project ${projectName} is not defined in this workspace.`,
);
}

if (project.extensions['projectType'] !== 'application') {
if (project.projectType !== 'application') {
throw new SchematicsException(
`@angular/elements requires a project type of "application" but ${projectName} isn't.`,
`ngx-tailwind requires a project type of "application" but ${projectName} isn't.`,
);
}

if (
_options.cssFormat === 'sass' ||
_options.cssFormat === 'less' ||
_options.cssFormat === 'styl'
) {
throw new SchematicsException(
`ngx-tailwind currently does not support your selected stylesheet ${_options.cssFormat}, try 'css' or 'scss'.`,
);
}

return chain([
addDependencies(_options),
updateStyles(project),
addWebpackConfig(),
updateAngularJSON(projectName),
updateStyles(_options),
addWebpackConfig(_options),
updateAngularJSON(_options),
install(),
tailwindInit(_options),
]);
Expand All @@ -60,11 +79,14 @@ function addDependencies(_options: Schema): Rule {
name: 'tailwindcss',
version: _options.tailwindVersion,
});
addPackageJsonDependency(host, {
type: NodeDependencyType.Dev,
name: 'postcss-scss',
version: _options.postcssScssVersion,
});

if (_options.cssFormat === 'scss') {
addPackageJsonDependency(host, {
type: NodeDependencyType.Dev,
name: 'postcss-scss',
version: _options.postcssScssVersion,
});
}

addPackageJsonDependency(host, {
type: NodeDependencyType.Dev,
Expand All @@ -86,20 +108,34 @@ function addDependencies(_options: Schema): Rule {
};
}

function updateStyles(project: ProjectDefinition): Rule {
return async (host: Tree) => {
const path = `${project.sourceRoot}/styles.scss`;
const recorder = host.beginUpdate(path);
recorder.insertLeft(
0,
`@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities'; \n`,
);
host.commitUpdate(recorder);
function updateStyles(options: Schema): Rule {
return (tree: Tree, context: SchematicContext) => {
const workspace = getWorkspaceConfig(tree);
const project = getProjectFromWorkspace(workspace, options.project);
const stylePath = getProjectStyleFile(project, options.cssFormat);

if (!stylePath) {
context.logger.error(
`Cannot update project styles file: Style path not found`,
);
return tree;
}

const insertion = new InsertChange(stylePath!, 0, getTailwindImports());
const recorder = tree.beginUpdate(stylePath!);
recorder.insertLeft(0, insertion.toAdd);
tree.commitUpdate(recorder);

return tree;
};
}

function getTailwindImports(): string {
return `@import 'tailwindcss/base';\n
@import 'tailwindcss/components';\n
@import 'tailwindcss/utilities';\n`;
}

function tailwindInit(_options: Schema): Rule {
return (_tree: Tree, context: SchematicContext) => {
if (!_options.skipTailwindInit) {
Expand All @@ -112,33 +148,68 @@ function tailwindInit(_options: Schema): Rule {
};
}

function addWebpackConfig(): Rule {
function addWebpackConfig(options: Schema): Rule {
return async (_host: Tree) => {
const sourceTemplates = url('./templates/webpack');
const sourceTemplates = url(`./templates/webpack/${options.cssFormat}`);
const sourceParametrizedTemplates = apply(sourceTemplates, []);
return mergeWith(sourceParametrizedTemplates);
};
}

function updateAngularJSON(project: string): Rule {
return async (host: Tree) => {
const angularConfig = host.read('/angular.json')?.toString();
if (angularConfig) {
const json = JSON.parse(angularConfig);
json.projects[project].architect.build.builder = 'ngx-build-plus:browser';
json.projects[project].architect.build.options = {
...json.projects[project].architect.build.options,
extraWebpackConfig: './webpack.config.js',
function updateAngularJSON(options: Schema): Rule {
return (tree: Tree, context: SchematicContext) => {
const workspace = getWorkspaceConfig(tree);
const project = getProjectFromWorkspace(workspace, options.project);

const browserTargets = getTargetsByBuilderName(project, Builders.Browser);
const devServerTargets = getTargetsByBuilderName(
project,
Builders.DevServer,
);
const karmaServerTargets = getTargetsByBuilderName(project, Builders.Karma);

browserTargets.forEach((browserTarget) => {
browserTarget.builder = NGX_BUILD_PLUS_BUILDER_TARGET;
browserTarget.options = {
extraWebpackConfig: 'webpack.config.js',
...(browserTarget.options as any),
};
json.projects[project].architect.serve.builder =
'ngx-build-plus:dev-server';
json.projects[project].architect.serve.options = {
...json.projects[project].architect.serve.options,
extraWebpackConfig: './webpack.config.js',
});
devServerTargets.forEach((browserTarget) => {
browserTarget.builder = NGX_BUILD_PLUS_DEV_BUILDER_TARGET;
browserTarget.options = {
extraWebpackConfig: 'webpack.config.js',
...(browserTarget.options as any),
};
});

host.overwrite('/angular.json', JSON.stringify(json, null, 2));
}
karmaServerTargets.forEach((browserTarget) => {
browserTarget.builder = NGX_BUILD_PLUS_KARMA_BUILDER_TARGET;
browserTarget.options = {
extraWebpackConfig: 'webpack.config.js',
...(browserTarget.options as any),
};
});

// const angularConfig = tree.read('/angular.json')?.toString();
// if (angularConfig) {
// const json = JSON.parse(angularConfig);
// json.projects[project].architect.build.builder = 'ngx-build-plus:browser';
// json.projects[project].architect.build.options = {
// ...json.projects[project].architect.build.options,
// extraWebpackConfig: './webpack.config.js',
// };
// json.projects[project].architect.serve.builder =
// 'ngx-build-plus:dev-server';
// json.projects[project].architect.serve.options = {
// ...json.projects[project].architect.serve.options,
// extraWebpackConfig: './webpack.config.js',
// };

// tree.overwrite('/angular.json', JSON.stringify(json, null, 2));
// }

return updateWorkspace(workspace)(tree, context);
};
}

Expand Down
32 changes: 32 additions & 0 deletions src/ng-add/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,38 @@
"type": "object",
"description": "Add Tailwind to Angular Workspace",
"properties": {
"cssFormat": {
"description": "The file extension or preprocessor to use for style files.",
"type": "string",
"default": "css",
"enum": ["css", "scss", "sass", "less", "styl"],
"x-prompt": {
"message": "Which stylesheet format are you using?",
"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 ]"
},
{
"value": "styl",
"label": "Stylus [ http://stylus-lang.com ]"
}
]
}
},
"ngxBuildPlusVersion": {
"type": "string",
"description": "The ngx-build-plus version to be installed.",
Expand Down
Loading

0 comments on commit f8c026a

Please sign in to comment.