diff --git a/components/icon/doc/index.en-US.md b/components/icon/doc/index.en-US.md index 02ce2b6cfc7..07d2ebefc0f 100755 --- a/components/icon/doc/index.en-US.md +++ b/components/icon/doc/index.en-US.md @@ -7,6 +7,11 @@ hasPageDemo: true Semantic vector graphics. +
+

If the icon cannot be displayed or the console has an error, Please run the following command to fix it ng g ng-zorro-antd:fix-icon.

+

See Static loading and dynamic loading for details.

+
+ ## List of icons > Click the icon and copy the code. @@ -103,7 +108,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/`. diff --git a/components/icon/doc/index.zh-CN.md b/components/icon/doc/index.zh-CN.md index 19490b6096a..667edb4fe71 100755 --- a/components/icon/doc/index.zh-CN.md +++ b/components/icon/doc/index.zh-CN.md @@ -8,6 +8,11 @@ hasPageDemo: true 语义化的矢量图形。 +
+

如遇图标无法显示或控制台出现相关错误,请在项目下执行 ng g ng-zorro-antd:fix-icon 命令修复。

+

详情请查看 静态加载与动态加载 部分。

+
+ ## 图标列表 > 点击图标即可复制代码 @@ -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/` 的前面。 diff --git a/docs/changelog.zh-CN.md b/docs/changelog.zh-CN.md index 1de6cd571c6..5d0d2dbb121 100755 --- a/docs/changelog.zh-CN.md +++ b/docs/changelog.zh-CN.md @@ -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#静态加载与动态加载)两节。 --- diff --git a/package.json b/package.json index 12869d74ff2..6d29bf8d438 100644 --- a/package.json +++ b/package.json @@ -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'", diff --git a/schematics/collection.json b/schematics/collection.json index 60cc27039f6..e66da4e4269 100644 --- a/schematics/collection.json +++ b/schematics/collection.json @@ -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" } } } diff --git a/schematics/fix-icon/index.ts b/schematics/fix-icon/index.ts new file mode 100644 index 00000000000..86e047be9b3 --- /dev/null +++ b/schematics/fix-icon/index.ts @@ -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; +} diff --git a/schematics/fix-icon/schema.json b/schematics/fix-icon/schema.json new file mode 100644 index 00000000000..b66287f3df7 --- /dev/null +++ b/schematics/fix-icon/schema.json @@ -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." + } + } +} \ No newline at end of file diff --git a/schematics/fix-icon/schema.ts b/schematics/fix-icon/schema.ts new file mode 100644 index 00000000000..cfd8a4a1f2b --- /dev/null +++ b/schematics/fix-icon/schema.ts @@ -0,0 +1,6 @@ + +export interface Schema { + /** Name of the project to target. */ + project?: string; + +} diff --git a/schematics/ng-add/index.ts b/schematics/ng-add/index.ts index d6ecd8d8fc0..ecb2e8f8017 100644 --- a/schematics/ng-add/index.ts +++ b/schematics/ng-add/index.ts @@ -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: ` + BOOT_PAGE_PATH : 'src/app/app.component.html', + BOOT_PAGE_HTML : ` ` @@ -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) ]); } @@ -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}`); @@ -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 []; @@ -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 []; } @@ -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 */ @@ -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); @@ -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); diff --git a/schematics/ng-add/schema.json b/schematics/ng-add/schema.json index 763e9c03513..4bfc2d77d13 100644 --- a/schematics/ng-add/schema.json +++ b/schematics/ng-add/schema.json @@ -19,6 +19,10 @@ "type": "boolean", "default": false, "description": "add theme.less" + }, + "project": { + "type": "string", + "description": "Name of the project to target." } }, "required": [] diff --git a/schematics/utils/devkit-utils/config.ts b/schematics/utils/devkit-utils/config.ts index 838e44a3dca..3b496c6ea41 100755 --- a/schematics/utils/devkit-utils/config.ts +++ b/schematics/utils/devkit-utils/config.ts @@ -40,6 +40,7 @@ export interface Workspace { projects: { [k: string]: Project; }; + defaultProject?: string; } /** @@ -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'); }