Skip to content

Commit

Permalink
feat(schematics): add fix icon schematic (#2238)
Browse files Browse the repository at this point in the history
  • Loading branch information
hsuanxyz committed Oct 9, 2018
1 parent e0d9987 commit 8861beb
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 15 deletions.
7 changes: 6 additions & 1 deletion components/icon/doc/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ hasPageDemo: true

Semantic vector graphics.

<blockquote style="border-color: orange;">
<p><strong>If the icon cannot be displayed or the console has an error, please run the following command to fix it <code>ng g ng-zorro-antd:fix-icon</code>.</strong></p>
<p>See <a href="/components/icon/en#static-loading-and-dynamic-loading">Static loading and dynamic loading</a> for details.</p>
</blockquote>

## List of icons

> Click the icon and copy the code.
Expand Down Expand Up @@ -101,7 +106,7 @@ Dynamic importing. This way would not increase your bundle's size. When NG-ZORRO
}
```

We provide a schematic to fix this. Just simply run `{{ hsuanlee }}` and we would add this config above for you!
We provide a schematic to fix this. Just simply run `ng g ng-zorro-antd:fix-icon` and we would add this config above for you!

You can call `changeAssetsSource()` of `NzIconService` to change the location of your icon assets, so that you can deploy these icon assets to cdn. The parameter you passed would be add in front of `assets/`.

Expand Down
7 changes: 6 additions & 1 deletion components/icon/doc/index.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ hasPageDemo: true

语义化的矢量图形。

<blockquote style="border-color: orange;">
<p><strong>如遇图标无法显示或控制台出现相关错误,请在项目下执行 <code>ng g ng-zorro-antd:fix-icon</code> 命令修复。</strong></p>
<p>详情请查看 <a href="/components/icon/zh#%E9%9D%99%E6%80%81%E5%8A%A0%E8%BD%BD%E4%B8%8E%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD">静态加载与动态加载</a> 部分。</p>
</blockquote>

## 图标列表

> 点击图标即可复制代码
Expand Down Expand Up @@ -102,7 +107,7 @@ export class AppComponent implements OnInit, AfterViewInit {
}
```

我们为你提供了一条指令,升级到 1.7.0 之后,执行 `{{ hsuanlee }}` 命令,就会自动添加以上配置。
我们为你提供了一条指令,升级到 1.7.0 之后,执行 `ng g ng-zorro-antd:fix-icon` 命令,就会自动添加以上配置。

你可以通过 `NzIconService``changeAssetsSource()` 方法来修改图标资源的位置,这样你就可以部署这些资源到 cdn 上。你的参数会被直接添加到 `assets/` 的前面。

Expand Down
2 changes: 1 addition & 1 deletion docs/changelog.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ timeline: true
* 支持多色图标。
* 对于内建图标的更换可以提供更多 API,而不需要进行样式覆盖。

我们尽可能地在不增加包体积的前提下对旧的 API 进行了兼容,你无需修改代码,但可能需要进行一些配置。关于 icon 的更多信息,请阅读 Icon API 的[“Svg 图标”](/components/icon/zh#svg-图标)[“静态加载与动态加载”两节](/components/icon/zh#静态加载与动态加载)
我们尽可能地在不增加包体积的前提下对旧的 API 进行了兼容,你无需修改代码,但可能需要进行一些配置。关于 icon 的更多信息,请阅读 Icon API 的[“Svg 图标”](/components/icon/zh#svg-图标)[“静态加载与动态加载”](/components/icon/zh#静态加载与动态加载)两节

---

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"node": ">=10.0.0"
},
"scripts": {
"start": "ng serve -port 0",
"start": "ng serve --port 0",
"build": "node ./scripts/site/generate-site init && ng build",
"test": "ng test --watch=false --code-coverage",
"lint": "tslint -c tslint.json 'components/*/*.ts'",
Expand Down
5 changes: 5 additions & 0 deletions schematics/collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
"description": "add NG-ZORRO",
"factory": "./ng-add",
"schema": "./ng-add/schema.json"
},
"fix-icon": {
"description": "fix icon",
"factory": "./fix-icon",
"schema": "./fix-icon/schema.json"
}
}
}
54 changes: 54 additions & 0 deletions schematics/fix-icon/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { chain, Rule, Tree } from '@angular-devkit/schematics';
import { getProjectFromWorkspace, getWorkspace } from '../utils/devkit-utils/config';
import { getProjectTargetOptions } from '../utils/project-targets';
import { Schema } from './schema';

const ICON_ASSET_CONFIG = {
'glob' : '**/*',
'input' : './node_modules/@ant-design/icons/inline-svg/',
'output': '/assets/'
};

export default function (options: Schema): Rule {
return chain([
addIconToAssets(options)
]);
}

function addIconToAssets(options: Schema): (host: Tree) => Tree {
return (host: Tree) => {
const workspace = getWorkspace(host);
const project = getProjectFromWorkspace(workspace, options.project);
const targetOptions = getProjectTargetOptions(project, 'build');

if (!targetOptions.assets) {
targetOptions.assets = [ { ...ICON_ASSET_CONFIG } ];
} else {
let hasIconAssetConfig = false;

// tslint:disable-next-line
for (let i = 0; i < targetOptions.assets.length; i++) {
const asset = targetOptions.assets[ i ];
if (typeof asset === 'object' && equals(ICON_ASSET_CONFIG, asset)) {
hasIconAssetConfig = true;
break;
}
}

if (!hasIconAssetConfig) {
targetOptions.assets.push({ ...ICON_ASSET_CONFIG });
}
}
host.overwrite('angular.json', JSON.stringify(workspace, null, 2));
return host;
};
}

function equals(obj1: object, obj2: object): boolean {
Object.keys(obj1).forEach(k => {
if (!obj2.hasOwnProperty(k) || obj1[ k ] !== obj2[ k ]) {
return false;
}
});
return true;
}
12 changes: 12 additions & 0 deletions schematics/fix-icon/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/schema",
"id": "fixIcon",
"title": "fix icon",
"type": "object",
"properties": {
"project": {
"type": "string",
"description": "Name of the project to target."
}
}
}
6 changes: 6 additions & 0 deletions schematics/fix-icon/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

export interface Schema {
/** Name of the project to target. */
project?: string;

}
27 changes: 16 additions & 11 deletions schematics/ng-add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import { addPackageToPackageJson } from '../utils/package';
import { getProjectTargetOptions } from '../utils/project-targets';
import { Schema } from './schema';

import schematicsFixIcon from '../fix-icon/index';

const ADD_CONFIG = {
LESS_VERSION: '^2.7.3',
CUSTOM_THEME_PATH: 'src/theme.less',
LESS_VERSION : '^2.7.3',
CUSTOM_THEME_PATH : 'src/theme.less',
COMPILED_THEME_PATH: 'node_modules/ng-zorro-antd/ng-zorro-antd.min.css',
BOOT_PAGE_PATH: 'src/app/app.component.html',
BOOT_PAGE_HTML: `<!-- NG-ZORRO -->
BOOT_PAGE_PATH : 'src/app/app.component.html',
BOOT_PAGE_HTML : `<!-- NG-ZORRO -->
<a href="https://github.com/NG-ZORRO/ng-zorro-antd" target="_blank" style="display: flex;align-items: center;justify-content: center;height: 100%;width: 100%;">
<img height="300" src="https://img.alicdn.com/tfs/TB1NvvIwTtYBeNjy1XdXXXXyVXa-89-131.svg">
</a>`
Expand All @@ -37,7 +39,8 @@ export default function (options: Schema): Rule {
addThemeToAppStyles(options),
addModulesToAppModule(options),
addI18n(options),
(options && !options.skipPackageJson) || (options && !options.theme) ? installNodeDeps() : noop()
(options && !options.skipPackageJson) || (options && !options.theme) ? installNodeDeps() : noop(),
schematicsFixIcon(options)
]);
}

Expand All @@ -49,7 +52,7 @@ function addI18n(options: Schema): (host: Tree) => Tree {
const modulePath = getAppModulePath(host, getProjectTargetOptions(project, 'build').main);
const moduleSource = getSourceFile(host, modulePath);
const locale = options.i18n;
const localePrefix = locale.split('_')[0];
const localePrefix = locale.split('_')[ 0 ];

if (!moduleSource) {
throw new SchematicsException(`Module not found: ${modulePath}`);
Expand Down Expand Up @@ -90,7 +93,7 @@ function insertI18nTokenProvide(moduleSource: ts.SourceFile, modulePath: string,
const metadataField = 'providers';
const nodes = getDecoratorMetadata(moduleSource, 'NgModule', '@angular/core');
const addProvide = addSymbolToNgModuleMetadata(moduleSource, modulePath, 'providers', `{ provide: NZ_I18N, useValue: ${locale} }`, null);
let node: any = nodes[0]; // tslint:disable-line:no-any
let node: any = nodes[ 0 ]; // tslint:disable-line:no-any

if (!node) {
return [];
Expand All @@ -116,7 +119,7 @@ function insertI18nTokenProvide(moduleSource: ts.SourceFile, modulePath: string,
}

if (matchingProperties.length) {
const assignment = matchingProperties[0] as ts.PropertyAssignment;
const assignment = matchingProperties[ 0 ] as ts.PropertyAssignment;
if (assignment.initializer.kind !== ts.SyntaxKind.ArrayLiteralExpression) {
return [];
}
Expand All @@ -142,11 +145,11 @@ function registerLocaleData(moduleSource: ts.SourceFile, modulePath: string, loc
const allFun = findNodes(moduleSource, ts.SyntaxKind.ExpressionStatement);
const registerLocaleDataFun = allFun.filter(node => {
const fun = node.getChildren();
return fun[0].getChildren()[0] && fun[0].getChildren()[0].getText() === 'registerLocaleData';
return fun[ 0 ].getChildren()[ 0 ] && fun[ 0 ].getChildren()[ 0 ].getText() === 'registerLocaleData';
});
return registerLocaleDataFun.length === 0
return registerLocaleDataFun.length === 0
? insertAfterLastOccurrence(allImports, `\n\nregisterLocaleData(${locale});`, modulePath, 0)
: new ReplaceChange(modulePath, registerLocaleDataFun[0].getStart(), registerLocaleDataFun[0].getText(), `registerLocaleData(${locale});`);
: new ReplaceChange(modulePath, registerLocaleDataFun[ 0 ].getStart(), registerLocaleDataFun[ 0 ].getText(), `registerLocaleData(${locale});`);
}

/** 降级 less */
Expand Down Expand Up @@ -207,6 +210,7 @@ function insertCustomTheme(project: Project, host: Tree, workspace: Workspace):
host.create(themePath, createCustomTheme());
}

// tslint:disable-next-line:no-any
if ((project as any).targets || project.architect) {
addStyleToTarget('build', host, workspace, project, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
addStyleToTarget('test', host, workspace, project, themePath, ADD_CONFIG.COMPILED_THEME_PATH);
Expand Down Expand Up @@ -235,6 +239,7 @@ function installNodeDeps(): (host: Tree, context: SchematicContext) => void {
function insertCompiledTheme(project: Project, host: Tree, workspace: Workspace): void {
const themePath = ADD_CONFIG.COMPILED_THEME_PATH;

// tslint:disable-next-line:no-any
if ((project as any).targets || project.architect) {
addStyleToTarget('build', host, workspace, project, themePath);
addStyleToTarget('test', host, workspace, project, themePath);
Expand Down
4 changes: 4 additions & 0 deletions schematics/ng-add/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
"type": "boolean",
"default": false,
"description": "add theme.less"
},
"project": {
"type": "string",
"description": "Name of the project to target."
}
},
"required": []
Expand Down
6 changes: 6 additions & 0 deletions schematics/utils/devkit-utils/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export interface Workspace {
projects: {
[k: string]: Project;
};
defaultProject?: string;
}

/**
Expand Down Expand Up @@ -105,12 +106,17 @@ export function getProjectFromWorkspace(config: Workspace, projectName?: string)
// If there is exactly one non-e2e project, use that. Otherwise, require that a specific
// project be specified.
const allProjectNames = Object.keys(config.projects).filter(p => !p.includes('e2e'));
const defaultProjectName = config.defaultProject;
if (allProjectNames.length === 1) {
const project = config.projects[allProjectNames[0]];
// Set a non-enumerable project name to the project. We need the name for schematics
// later on, but don't want to write it back out to the config file.
Object.defineProperty(project, 'name', {enumerable: false, value: projectName});
return project;
} else if (config.projects[defaultProjectName]) {
const project = config.projects[defaultProjectName];
Object.defineProperty(project, 'name', {enumerable: false, value: projectName});
return project;
} else {
throw new SchematicsException('Multiple projects are defined; please specify a project name');
}
Expand Down

0 comments on commit 8861beb

Please sign in to comment.