igniteui-cli 13.0.2 → 13.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/lib/commands/add.js +17 -5
  2. package/lib/commands/new.js +4 -1
  3. package/lib/commands/start.js +11 -6
  4. package/lib/templates/IgniteUIForReactTemplate.d.ts +2 -2
  5. package/lib/templates/IgniteUIForReactTemplate.js +36 -12
  6. package/package.json +3 -3
  7. package/templates/angular/index.js +1 -1
  8. package/templates/react/ReactTypeScriptFileUpdate.d.ts +50 -0
  9. package/templates/react/ReactTypeScriptFileUpdate.js +333 -0
  10. package/templates/react/igr-es6/index.js +1 -1
  11. package/templates/react/igr-ts/bullet-graph/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  12. package/templates/react/igr-ts/bullet-graph/default/files/src/app/__path__/__filePrefix__.tsx +56 -0
  13. package/templates/react/igr-ts/bullet-graph/default/files/src/app/__path__/style.module.css +12 -0
  14. package/templates/react/igr-ts/bullet-graph/default/index.d.ts +1 -0
  15. package/templates/react/igr-ts/bullet-graph/default/index.js +18 -0
  16. package/templates/react/igr-ts/bullet-graph/index.d.ts +1 -0
  17. package/templates/react/igr-ts/bullet-graph/index.js +15 -0
  18. package/templates/react/igr-ts/category-chart/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  19. package/templates/react/igr-ts/category-chart/default/files/src/app/__path__/__filePrefix__.tsx +41 -0
  20. package/templates/react/igr-ts/category-chart/default/files/src/app/__path__/style.module.css +9 -0
  21. package/templates/react/igr-ts/category-chart/default/index.d.ts +1 -0
  22. package/templates/react/igr-ts/category-chart/default/index.js +19 -0
  23. package/templates/react/igr-ts/category-chart/index.d.ts +1 -0
  24. package/templates/react/igr-ts/category-chart/index.js +16 -0
  25. package/templates/react/igr-ts/doughnut-chart/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  26. package/templates/react/igr-ts/doughnut-chart/default/files/src/app/__path__/__filePrefix__.tsx +63 -0
  27. package/templates/react/igr-ts/doughnut-chart/default/files/src/app/__path__/style.module.css +9 -0
  28. package/templates/react/igr-ts/doughnut-chart/default/index.d.ts +1 -0
  29. package/templates/react/igr-ts/doughnut-chart/default/index.js +18 -0
  30. package/templates/react/igr-ts/doughnut-chart/index.d.ts +1 -0
  31. package/templates/react/igr-ts/doughnut-chart/index.js +15 -0
  32. package/templates/react/igr-ts/financial-chart/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  33. package/templates/react/igr-ts/financial-chart/default/files/src/app/__path__/__filePrefix__.tsx +49 -0
  34. package/templates/react/igr-ts/financial-chart/default/files/src/app/__path__/style.module.css +10 -0
  35. package/templates/react/igr-ts/financial-chart/default/index.d.ts +1 -0
  36. package/templates/react/igr-ts/financial-chart/default/index.js +20 -0
  37. package/templates/react/igr-ts/financial-chart/index.d.ts +1 -0
  38. package/templates/react/igr-ts/financial-chart/index.js +16 -0
  39. package/templates/react/igr-ts/grid/basic/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  40. package/templates/react/igr-ts/grid/basic/files/src/app/__path__/__filePrefix__.tsx +58 -0
  41. package/templates/react/igr-ts/grid/basic/files/src/app/__path__/data.tsx +46 -0
  42. package/templates/react/igr-ts/grid/basic/files/src/app/__path__/style.module.css +17 -0
  43. package/templates/react/igr-ts/grid/basic/index.d.ts +1 -0
  44. package/templates/react/igr-ts/grid/basic/index.js +23 -0
  45. package/templates/react/igr-ts/grid/index.d.ts +1 -0
  46. package/templates/react/igr-ts/grid/index.js +15 -0
  47. package/templates/react/igr-ts/groups.json +5 -0
  48. package/templates/react/igr-ts/index.d.ts +1 -0
  49. package/templates/react/igr-ts/index.js +17 -0
  50. package/templates/react/igr-ts/linear-gauge/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  51. package/templates/react/igr-ts/linear-gauge/default/files/src/app/__path__/__filePrefix__.tsx +59 -0
  52. package/templates/react/igr-ts/linear-gauge/default/files/src/app/__path__/style.module.css +12 -0
  53. package/templates/react/igr-ts/linear-gauge/default/index.d.ts +1 -0
  54. package/templates/react/igr-ts/linear-gauge/default/index.js +18 -0
  55. package/templates/react/igr-ts/linear-gauge/index.d.ts +1 -0
  56. package/templates/react/igr-ts/linear-gauge/index.js +15 -0
  57. package/templates/react/igr-ts/pie-chart/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  58. package/templates/react/igr-ts/pie-chart/default/files/src/app/__path__/__filePrefix__.tsx +57 -0
  59. package/templates/react/igr-ts/pie-chart/default/files/src/app/__path__/style.module.css +9 -0
  60. package/templates/react/igr-ts/pie-chart/default/index.d.ts +1 -0
  61. package/templates/react/igr-ts/pie-chart/default/index.js +18 -0
  62. package/templates/react/igr-ts/pie-chart/index.d.ts +1 -0
  63. package/templates/react/igr-ts/pie-chart/index.js +15 -0
  64. package/templates/react/igr-ts/projects/_base/files/README.md +48 -0
  65. package/templates/react/igr-ts/projects/_base/files/__dot__eslintrc.cjs +18 -0
  66. package/templates/react/igr-ts/projects/_base/files/__dot__gitignore +23 -0
  67. package/templates/react/igr-ts/projects/_base/files/ignite-ui-cli.json +16 -0
  68. package/templates/react/igr-ts/projects/_base/files/index.html +28 -0
  69. package/templates/react/igr-ts/projects/_base/files/package.json +51 -0
  70. package/templates/react/igr-ts/projects/_base/files/public/favicon.ico +0 -0
  71. package/templates/react/igr-ts/projects/_base/files/src/app/App.test.tsx +8 -0
  72. package/templates/react/igr-ts/projects/_base/files/src/app/App.tsx +12 -0
  73. package/templates/react/igr-ts/projects/_base/files/src/app/app-routes.tsx +3 -0
  74. package/templates/react/igr-ts/projects/_base/files/src/index.css +14 -0
  75. package/templates/react/igr-ts/projects/_base/files/src/main.tsx +25 -0
  76. package/templates/react/igr-ts/projects/_base/files/src/setupTests.ts +5 -0
  77. package/templates/react/igr-ts/projects/_base/files/tsconfig.json +26 -0
  78. package/templates/react/igr-ts/projects/_base/files/vite.config.ts +23 -0
  79. package/templates/react/igr-ts/projects/_base/index.d.ts +29 -0
  80. package/templates/react/igr-ts/projects/_base/index.js +58 -0
  81. package/templates/react/igr-ts/projects/_base_with_home/files/public/logo.svg +7 -0
  82. package/templates/react/igr-ts/projects/_base_with_home/files/src/app/app-routes.tsx +5 -0
  83. package/templates/react/igr-ts/projects/_base_with_home/files/src/app/home/home.tsx +24 -0
  84. package/templates/react/igr-ts/projects/_base_with_home/files/src/app/home/style.module.css +36 -0
  85. package/templates/react/igr-ts/projects/_base_with_home/index.d.ts +14 -0
  86. package/templates/react/igr-ts/projects/_base_with_home/index.js +22 -0
  87. package/templates/react/igr-ts/projects/base/index.d.ts +14 -0
  88. package/templates/react/igr-ts/projects/base/index.js +22 -0
  89. package/templates/react/igr-ts/projects/empty/index.d.ts +14 -0
  90. package/templates/react/igr-ts/projects/empty/index.js +22 -0
  91. package/templates/react/igr-ts/projects/top-nav/files/src/app/App.css +62 -0
  92. package/templates/react/igr-ts/projects/top-nav/files/src/app/App.tsx +18 -0
  93. package/templates/react/igr-ts/projects/top-nav/files/src/components/navigation-header/index.tsx +29 -0
  94. package/templates/react/igr-ts/projects/top-nav/index.d.ts +14 -0
  95. package/templates/react/igr-ts/projects/top-nav/index.js +22 -0
  96. package/templates/react/igr-ts/radial-gauge/default/files/src/app/__path__/__filePrefix__.test.tsx +8 -0
  97. package/templates/react/igr-ts/radial-gauge/default/files/src/app/__path__/__filePrefix__.tsx +60 -0
  98. package/templates/react/igr-ts/radial-gauge/default/files/src/app/__path__/style.module.css +12 -0
  99. package/templates/react/igr-ts/radial-gauge/default/index.d.ts +1 -0
  100. package/templates/react/igr-ts/radial-gauge/default/index.js +19 -0
  101. package/templates/react/igr-ts/radial-gauge/index.d.ts +1 -0
  102. package/templates/react/igr-ts/radial-gauge/index.js +16 -0
  103. package/templates/react/index.js +1 -0
@@ -109,11 +109,23 @@ command = {
109
109
  addTemplate(fileName, template, options) {
110
110
  return __awaiter(this, void 0, void 0, function* () {
111
111
  if (!options) {
112
- options = {
113
- parentName: "app",
114
- parentRoutingModulePath: "src/app/app-routing.ts",
115
- selector: "app-" + template.id
116
- };
112
+ if (template.framework === "react") {
113
+ options = {
114
+ parentName: "app",
115
+ className: cli_core_1.Util.className(fileName),
116
+ modulePath: `src/app/${cli_core_1.Util.lowerDashed(fileName)}`
117
+ };
118
+ options["parentRoutingModulePath"] = template.projectType === "igr-ts"
119
+ ? "src/app/app-routes.tsx"
120
+ : "./src/routes.json";
121
+ }
122
+ else {
123
+ options = {
124
+ parentName: "app",
125
+ parentRoutingModulePath: "src/app/app-routing.ts",
126
+ selector: "app-" + template.id
127
+ };
128
+ }
117
129
  }
118
130
  fileName = fileName.trim();
119
131
  const name = cli_core_1.Util.nameFromPath(fileName);
@@ -107,7 +107,10 @@ command = {
107
107
  }
108
108
  }
109
109
  const theme = projectLib.themes[themeIndex];
110
- const projectTemplate = argv.template || projectLib.projectIds[0];
110
+ const indexOfEmptyOrFirst = projectLib.projectIds.indexOf("empty") !== -1
111
+ ? projectLib.projectIds.indexOf("empty")
112
+ : 0;
113
+ const projectTemplate = argv.template || projectLib.projectIds[indexOfEmptyOrFirst];
111
114
  cli_core_1.Util.log(`Project Name: ${argv.name}, framework ${argv.framework}, type ${projectLib.projectType}, theme ${theme}`);
112
115
  const projTemplate = projectLib.getProject(projectTemplate);
113
116
  if (projTemplate == null) {
@@ -81,12 +81,17 @@ command = {
81
81
  break;
82
82
  case "react":
83
83
  if (port) {
84
- // https://facebook.github.io/create-react-app/docs/advanced-configuration
85
- // react-scripts start "--port=dafaultPort" is not a valid command for all environments.
86
- // .env file is included and used by both igr-es6 and es6 now,
87
- // to specify the port for all environments (Windows, Mac, etc)
88
- process.env.PORT = `${port}`;
89
- port = null;
84
+ if (projectType === "igr-ts") {
85
+ execSyncNpmStart(port, options);
86
+ }
87
+ else {
88
+ // https://facebook.github.io/create-react-app/docs/advanced-configuration
89
+ // react-scripts start "--port=dafaultPort" is not a valid command for all environments.
90
+ // .env file is included and used by both igr-es6 and es6 now,
91
+ // to specify the port for all environments (Windows, Mac, etc)
92
+ process.env.PORT = `${port}`;
93
+ port = null;
94
+ }
90
95
  }
91
96
  /* falls through */
92
97
  case "angular":
@@ -15,7 +15,6 @@ export declare class IgniteUIForReactTemplate implements Template {
15
15
  packages: any[];
16
16
  delimiters: import("@igniteui/cli-core").TemplateDelimiters;
17
17
  protected widget: string;
18
- private configFile;
19
18
  /**
20
19
  * Base ReactTemplate constructor
21
20
  * @param rootPath The template folder path. Pass in `__dirname`
@@ -25,10 +24,11 @@ export declare class IgniteUIForReactTemplate implements Template {
25
24
  generateConfig(name: string, options: {}): {
26
25
  [key: string]: any;
27
26
  };
28
- registerInProject(projectPath: string, name: string, options?: AddTemplateArgs): void;
27
+ registerInProject(projectPath: string, name: string, options?: AddTemplateArgs, defaultPath?: boolean): void;
29
28
  getExtraConfiguration(): ControlExtraConfiguration[];
30
29
  setExtraConfiguration(extraConfigKeys: {}): void;
31
30
  protected folderName(pathName: string): string;
31
+ protected registerJSONRoute(projectPath: string, name: string, routingModulePath: string): void;
32
32
  protected getViewLink(name: string): string;
33
33
  protected getToolbarLink(name: string): string;
34
34
  }
@@ -4,6 +4,7 @@ exports.IgniteUIForReactTemplate = void 0;
4
4
  const cli_core_1 = require("@igniteui/cli-core");
5
5
  const fs = require("fs-extra");
6
6
  const path = require("path");
7
+ const ReactTypeScriptFileUpdate_1 = require("../../templates/react/ReactTypeScriptFileUpdate");
7
8
  class IgniteUIForReactTemplate {
8
9
  /**
9
10
  * Base ReactTemplate constructor
@@ -15,11 +16,9 @@ class IgniteUIForReactTemplate {
15
16
  this.listInCustomTemplates = false;
16
17
  this.dependencies = [];
17
18
  this.framework = "react";
18
- this.projectType = "igr-es6";
19
19
  this.hasExtraConfiguration = false;
20
20
  this.packages = [];
21
21
  this.delimiters = cli_core_1.defaultDelimiters;
22
- this.configFile = "./src/routes.json";
23
22
  }
24
23
  get templatePaths() {
25
24
  return [path.join(this.rootPath, "files")];
@@ -32,6 +31,7 @@ class IgniteUIForReactTemplate {
32
31
  config["path"] = this.folderName(name); //folder name allowed spaces, any casing
33
32
  config["name"] = cli_core_1.Util.nameFromPath(name); // this name should not have restrictions
34
33
  config["ClassName"] = cli_core_1.Util.className(cli_core_1.Util.nameFromPath(name)); //first letter capital, no spaces and no dashes,
34
+ config["filePrefix"] = cli_core_1.Util.lowerDashed(cli_core_1.Util.nameFromPath(name));
35
35
  config["cliVersion"] = cli_core_1.Util.version();
36
36
  if (this.widget) {
37
37
  config["widget"] = this.widget;
@@ -42,18 +42,32 @@ class IgniteUIForReactTemplate {
42
42
  }
43
43
  return config;
44
44
  }
45
- registerInProject(projectPath, name, options) {
46
- if (options && options.skipRoute) {
45
+ registerInProject(projectPath, name, options, defaultPath = false) {
46
+ if (!options.parentName) {
47
47
  return;
48
48
  }
49
- const configFile = fs.readFileSync(path.join(projectPath, this.configFile), "utf8");
50
- const viewsArr = JSON.parse(configFile);
51
- viewsArr.push({
52
- componentPath: this.getViewLink(name),
53
- path: "/" + this.folderName(cli_core_1.Util.nameFromPath(name)),
54
- text: this.getToolbarLink(name)
55
- });
56
- fs.writeFileSync(path.join(projectPath, this.configFile), JSON.stringify(viewsArr, null, 4));
49
+ if (this.projectType === "igr-es6") {
50
+ this.registerJSONRoute(projectPath, name, options.parentRoutingModulePath);
51
+ return;
52
+ }
53
+ const routeModulePath = options.parentRoutingModulePath;
54
+ if (!(options && options.skipRoute)
55
+ && cli_core_1.App.container.get(cli_core_1.FS_TOKEN).fileExists(routeModulePath)) {
56
+ let nameFromPath = cli_core_1.Util.nameFromPath(name);
57
+ let lowerDashed = cli_core_1.Util.lowerDashed(nameFromPath);
58
+ let filePath = path.posix.join(projectPath, options.modulePath, `${lowerDashed}.tsx`);
59
+ const routingModule = new ReactTypeScriptFileUpdate_1.ReactTypeScriptFileUpdate(path.join(projectPath, routeModulePath));
60
+ if (defaultPath) {
61
+ routingModule.addRoute("", options.className, nameFromPath, filePath, options.routerChildren, undefined);
62
+ }
63
+ routingModule.addRoute(lowerDashed, options.className, nameFromPath, filePath, options.routerChildren, undefined);
64
+ if (options.hasChildren) {
65
+ nameFromPath = cli_core_1.Util.nameFromPath(`${options.modulePath}-routes.tsx`);
66
+ lowerDashed = cli_core_1.Util.lowerDashed(nameFromPath);
67
+ filePath = path.posix.join(projectPath, options.modulePath, nameFromPath);
68
+ routingModule.addRoute(lowerDashed, options.className, nameFromPath, filePath, options.routerChildren, options.importAlias);
69
+ }
70
+ }
57
71
  }
58
72
  getExtraConfiguration() {
59
73
  throw new Error("Method not implemented.");
@@ -81,6 +95,16 @@ class IgniteUIForReactTemplate {
81
95
  }
82
96
  return cli_core_1.Util.lowerDashed(folderName);
83
97
  }
98
+ registerJSONRoute(projectPath, name, routingModulePath) {
99
+ const configFile = fs.readFileSync(path.join(projectPath, routingModulePath), "utf8");
100
+ const viewsArr = JSON.parse(configFile);
101
+ viewsArr.push({
102
+ componentPath: this.getViewLink(name),
103
+ path: "/" + this.folderName(cli_core_1.Util.nameFromPath(name)),
104
+ text: this.getToolbarLink(name)
105
+ });
106
+ fs.writeFileSync(path.join(projectPath, routingModulePath), JSON.stringify(viewsArr, null, 4));
107
+ }
84
108
  getViewLink(name) {
85
109
  const filePath = "./views/" + this.folderName(name);
86
110
  return filePath;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "igniteui-cli",
3
- "version": "13.0.2",
3
+ "version": "13.1.0-beta.0",
4
4
  "description": "CLI tool for creating Ignite UI projects",
5
5
  "keywords": [
6
6
  "CLI",
@@ -72,8 +72,8 @@
72
72
  "all": true
73
73
  },
74
74
  "dependencies": {
75
- "@igniteui/angular-templates": "~17.0.1302",
76
- "@igniteui/cli-core": "~13.0.2",
75
+ "@igniteui/angular-templates": "~17.1.1310-beta.0",
76
+ "@igniteui/cli-core": "~13.1.0-beta.0",
77
77
  "chalk": "^2.3.2",
78
78
  "fs-extra": "^3.0.1",
79
79
  "glob": "^7.1.2",
@@ -4,7 +4,7 @@ class AngularFramework {
4
4
  this.id = "angular";
5
5
  this.name = "Angular";
6
6
  this.projectLibraries = [];
7
- this.projectLibraries.push(require("@igniteui/angular-templates").default);
7
+ this.projectLibraries.push(...require("@igniteui/angular-templates").default);
8
8
  this.projectLibraries.push(require("./ig-ts"));
9
9
  }
10
10
  }
@@ -0,0 +1,50 @@
1
+ import * as ts from "typescript";
2
+ /**
3
+ * Apply various updates to typescript files using AST
4
+ */
5
+ export declare class ReactTypeScriptFileUpdate {
6
+ private targetPath;
7
+ protected formatOptions: {
8
+ spaces: boolean;
9
+ indentSize: number;
10
+ singleQuotes: boolean;
11
+ };
12
+ private fileSystem;
13
+ private targetSource;
14
+ private importsMeta;
15
+ private requestedImports;
16
+ private createdStringLiterals;
17
+ /** Create updates for a file. Use `add<X>` methods to add transformations and `finalize` to apply and save them. */
18
+ constructor(targetPath: string);
19
+ /** Applies accumulated transforms, saves and formats the file */
20
+ finalize(): void;
21
+ addRoute(path: string, component: string, name: string, filePath: string, routerChildren: string, importAlias: string, routesVariable?: string): void;
22
+ /** Initializes existing imports info, [re]sets import and `NgModule` edits */
23
+ protected initState(): void;
24
+ protected loadImportsMeta(): {
25
+ lastIndex: number;
26
+ modulePaths: any[];
27
+ };
28
+ protected addRouteModuleEntry(path: string, component: string, name: string, filePath: string, routerChildren: string, importAlias: string, routesVariable?: string): void;
29
+ protected requestImport(modulePath: string, routerAlias: string, componentName: string): void;
30
+ /** Add `import` statements not previously found in the file */
31
+ protected addNewFileImports(): void;
32
+ protected createIdentifierImport(importPath: string, as: string, component: string): ts.ImportDeclaration;
33
+ /** Transformation to apply edits to existing named import declarations */
34
+ protected importsTransformer: ts.TransformerFactory<ts.Node>;
35
+ /** Format a TS source file, very TBD */
36
+ protected formatFile(filePath: string): void;
37
+ /** Try and parse formatting from project `.editorconfig` / `tslint.json` */
38
+ protected readFormatConfigs(): void;
39
+ /**
40
+ * Apply formatting changes (position based) in reverse
41
+ * from https://github.com/Microsoft/TypeScript/issues/1651#issuecomment-69877863
42
+ */
43
+ private applyChanges;
44
+ /** Return source file formatting options */
45
+ private getFormattingOptions;
46
+ /** Get language service host, sloppily */
47
+ private getLanguageHost;
48
+ private createVisitor;
49
+ private createRouteEntry;
50
+ }
@@ -0,0 +1,333 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReactTypeScriptFileUpdate = void 0;
4
+ const cli_core_1 = require("@igniteui/cli-core");
5
+ const ts = require("typescript");
6
+ const DEFAULT_ROUTES_VARIABLE = "routes";
7
+ /**
8
+ * Apply various updates to typescript files using AST
9
+ */
10
+ class ReactTypeScriptFileUpdate {
11
+ /** Create updates for a file. Use `add<X>` methods to add transformations and `finalize` to apply and save them. */
12
+ constructor(targetPath) {
13
+ this.targetPath = targetPath;
14
+ this.formatOptions = { spaces: false, indentSize: 4, singleQuotes: false };
15
+ //#region ts.TransformerFactory
16
+ /** Transformation to apply edits to existing named import declarations */
17
+ this.importsTransformer = (context) => (rootNode) => {
18
+ const editImports = this.requestedImports.filter(x => x.edit);
19
+ // https://github.com/Microsoft/TypeScript/issues/14419#issuecomment-307256171
20
+ const visitor = (node) => {
21
+ if (node.kind === ts.SyntaxKind.ImportDeclaration &&
22
+ editImports.find(x => x.from === node.moduleSpecifier.text)) {
23
+ // visit just the source file main array (second visit)
24
+ return visitImport(node);
25
+ }
26
+ else {
27
+ node = ts.visitEachChild(node, visitor, context);
28
+ }
29
+ return node;
30
+ };
31
+ function visitImport(node) {
32
+ node = ts.visitEachChild(node, visitImport, context);
33
+ return node;
34
+ }
35
+ return ts.visitNode(rootNode, visitor);
36
+ };
37
+ this.fileSystem = cli_core_1.App.container.get(cli_core_1.FS_TOKEN);
38
+ this.initState();
39
+ }
40
+ /** Applies accumulated transforms, saves and formats the file */
41
+ finalize() {
42
+ // add new import statements after visitor walks:
43
+ this.addNewFileImports();
44
+ cli_core_1.TypeScriptUtils.saveFile(this.targetPath, this.targetSource);
45
+ this.formatFile(this.targetPath);
46
+ // reset state in case of further updates
47
+ this.initState();
48
+ }
49
+ addRoute(path, component, name, filePath, routerChildren, importAlias, routesVariable = DEFAULT_ROUTES_VARIABLE) {
50
+ this.addRouteModuleEntry(path, component, name, filePath, routerChildren, importAlias, routesVariable);
51
+ }
52
+ //#region File state
53
+ /** Initializes existing imports info, [re]sets import and `NgModule` edits */
54
+ initState() {
55
+ this.targetSource = cli_core_1.TypeScriptUtils.getFileSource(this.targetPath);
56
+ this.importsMeta = this.loadImportsMeta();
57
+ this.requestedImports = [];
58
+ this.createdStringLiterals = [];
59
+ }
60
+ /* load some metadata about imports */
61
+ loadImportsMeta() {
62
+ const meta = { lastIndex: 0, modulePaths: [] };
63
+ for (let i = 0; i < this.targetSource.statements.length; i++) {
64
+ const statement = this.targetSource.statements[i];
65
+ switch (statement.kind) {
66
+ case ts.SyntaxKind.ImportDeclaration:
67
+ const importStmt = statement;
68
+ if (importStmt.importClause && importStmt.importClause.namedBindings &&
69
+ importStmt.importClause.namedBindings.kind !== ts.SyntaxKind.NamespaceImport) {
70
+ // don't add imports without named (e.g. `import $ from "JQuery"` or `import "./my-module.js";`)
71
+ // don't add namespace imports (`import * as fs`) as available for editing, maybe in the future
72
+ meta.modulePaths.push(importStmt.moduleSpecifier.text);
73
+ }
74
+ // don't add equals imports (`import url = require("url")`) as available for editing, maybe in the future
75
+ case ts.SyntaxKind.ImportEqualsDeclaration:
76
+ meta.lastIndex = i + 1;
77
+ break;
78
+ default:
79
+ break;
80
+ }
81
+ }
82
+ return meta;
83
+ }
84
+ //#endregion File state
85
+ addRouteModuleEntry(path, component, name, filePath, routerChildren, importAlias, routesVariable = DEFAULT_ROUTES_VARIABLE) {
86
+ const isRouting = path.indexOf("routes") >= 0;
87
+ if (isRouting && this.targetSource.text.indexOf(path.slice(0, -4)) > 0) {
88
+ return;
89
+ }
90
+ if (path) {
91
+ const relativePath = cli_core_1.Util.relativePath(this.targetPath, filePath, true, true);
92
+ this.requestImport(relativePath, importAlias, component);
93
+ }
94
+ // https://github.com/Microsoft/TypeScript/issues/14419#issuecomment-307256171
95
+ const transformer = (context) => (rootNode) => {
96
+ // the visitor that should be used when adding routes to the main route array
97
+ const conditionalVisitor = (node) => {
98
+ if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {
99
+ const newObject = this.createRouteEntry(path, component, name, routerChildren);
100
+ const array = node;
101
+ this.createdStringLiterals.push(path, name);
102
+ const notFoundWildCard = ".*";
103
+ const nodes = ts.visitNodes(array.elements, visitor);
104
+ const errorRouteNode = nodes.filter(element => element.getText().includes(notFoundWildCard))[0];
105
+ let resultNodes = null;
106
+ if (errorRouteNode) {
107
+ resultNodes = nodes
108
+ .slice(0, nodes.indexOf(errorRouteNode))
109
+ .concat(newObject)
110
+ .concat(errorRouteNode);
111
+ }
112
+ else {
113
+ resultNodes = nodes
114
+ .concat(newObject);
115
+ }
116
+ const elements = ts.factory.createNodeArray([
117
+ ...resultNodes
118
+ ]);
119
+ return ts.factory.updateArrayLiteralExpression(array, elements);
120
+ }
121
+ else {
122
+ return ts.visitEachChild(node, conditionalVisitor, context);
123
+ }
124
+ };
125
+ let visitCondition;
126
+ if (!isRouting) {
127
+ visitCondition = (node) => {
128
+ return node.kind === ts.SyntaxKind.VariableDeclaration &&
129
+ node.name.getText() === routesVariable;
130
+ // no type currently
131
+ //(node as ts.VariableDeclaration).type.getText() === "Route[]";
132
+ };
133
+ }
134
+ else {
135
+ visitCondition = (node) => {
136
+ return undefined;
137
+ };
138
+ }
139
+ const visitor = this.createVisitor(conditionalVisitor, visitCondition, context);
140
+ context.enableSubstitution(ts.SyntaxKind.ClassDeclaration);
141
+ return ts.visitNode(rootNode, visitor);
142
+ };
143
+ this.targetSource = ts.transform(this.targetSource, [transformer], {
144
+ pretty: true // oh well..
145
+ }).transformed[0];
146
+ this.finalize();
147
+ }
148
+ requestImport(modulePath, routerAlias, componentName) {
149
+ const existing = this.requestedImports.find(x => x.from === modulePath);
150
+ if (!existing) {
151
+ // new imports, check if already exists in file
152
+ this.requestedImports.push({
153
+ as: routerAlias,
154
+ from: modulePath,
155
+ component: componentName,
156
+ edit: this.importsMeta.modulePaths.indexOf(modulePath) !== -1
157
+ });
158
+ }
159
+ else {
160
+ return;
161
+ }
162
+ }
163
+ /** Add `import` statements not previously found in the file */
164
+ addNewFileImports() {
165
+ const newImports = this.requestedImports.filter(x => !x.edit);
166
+ if (!newImports.length) {
167
+ return;
168
+ }
169
+ const newStatements = ts.factory.createNodeArray([
170
+ ...this.targetSource.statements.slice(0, this.importsMeta.lastIndex),
171
+ ...newImports.map(x => this.createIdentifierImport(x.from, x.as, x.component)),
172
+ ...this.targetSource.statements.slice(this.importsMeta.lastIndex)
173
+ ]);
174
+ newImports.forEach(x => this.createdStringLiterals.push(x.from));
175
+ this.targetSource = ts.factory.updateSourceFile(this.targetSource, newStatements);
176
+ }
177
+ createIdentifierImport(importPath, as, component) {
178
+ let exportedObject;
179
+ let exportedObjectName;
180
+ let importClause;
181
+ if (as) {
182
+ exportedObject = "routes";
183
+ exportedObjectName = as.replace(/\s/g, "");
184
+ importClause = ts.factory.createImportClause(false, undefined, ts.factory.createNamedImports([
185
+ ts.factory.createImportSpecifier(false, ts.factory.createIdentifier(exportedObject), ts.factory.createIdentifier(exportedObjectName))
186
+ ]));
187
+ }
188
+ else {
189
+ importClause = ts.factory.createImportClause(false, ts.factory.createIdentifier(component), undefined);
190
+ }
191
+ const importDeclaration = ts.factory.createImportDeclaration(undefined, undefined, importClause, ts.factory.createStringLiteral(importPath, true));
192
+ return importDeclaration;
193
+ }
194
+ //#endregion ts.TransformerFactory
195
+ //#region Formatting
196
+ /** Format a TS source file, very TBD */
197
+ formatFile(filePath) {
198
+ // formatting via LanguageService https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API
199
+ // https://github.com/Microsoft/TypeScript/issues/1651
200
+ let text = this.fileSystem.readFile(filePath);
201
+ // create the language service files
202
+ const services = ts.createLanguageService(this.getLanguageHost(filePath), ts.createDocumentRegistry());
203
+ this.readFormatConfigs();
204
+ const textChanges = services.getFormattingEditsForDocument(filePath, this.getFormattingOptions());
205
+ text = this.applyChanges(text, textChanges);
206
+ if (this.formatOptions.singleQuotes) {
207
+ for (const str of this.createdStringLiterals) {
208
+ // there shouldn't be duplicate strings of these
209
+ text = text.replace(`"${str}"`, `'${str}'`);
210
+ }
211
+ }
212
+ this.fileSystem.writeFile(filePath, text);
213
+ }
214
+ /** Try and parse formatting from project `.editorconfig` / `tslint.json` */
215
+ readFormatConfigs() {
216
+ if (this.fileSystem.fileExists(".editorconfig")) {
217
+ // very basic parsing support
218
+ const text = this.fileSystem.readFile(".editorconfig", "utf-8");
219
+ const options = text
220
+ .replace(/\s*[#;].*([\r\n])/g, "$1") //remove comments
221
+ .replace(/\[(?!\*\]|\*.ts).+\][^\[]+/g, "") // leave [*]/[*.ts] sections
222
+ .split(/\r\n|\r|\n/)
223
+ .reduce((obj, x) => {
224
+ if (x.indexOf("=") !== -1) {
225
+ const pair = x.split("=");
226
+ obj[pair[0].trim()] = pair[1].trim();
227
+ }
228
+ return obj;
229
+ }, {});
230
+ this.formatOptions.spaces = options["indent_style"] === "space";
231
+ if (options["indent_size"]) {
232
+ this.formatOptions.indentSize = parseInt(options["indent_size"], 10) || this.formatOptions.indentSize;
233
+ }
234
+ if (options["quote_type"]) {
235
+ this.formatOptions.singleQuotes = options["quote_type"] === "single";
236
+ }
237
+ }
238
+ if (this.fileSystem.fileExists("tslint.json")) {
239
+ // tslint prio - overrides other settings
240
+ const options = JSON.parse(this.fileSystem.readFile("tslint.json", "utf-8"));
241
+ if (options.rules && options.rules.indent && options.rules.indent[0]) {
242
+ this.formatOptions.spaces = options.rules.indent[1] === "spaces";
243
+ if (options.rules.indent[2]) {
244
+ this.formatOptions.indentSize = parseInt(options.rules.indent[2], 10);
245
+ }
246
+ }
247
+ if (options.rules && options.rules.quotemark && options.rules.quotemark[0]) {
248
+ this.formatOptions.singleQuotes = options.rules.quotemark.indexOf("single") !== -1;
249
+ }
250
+ }
251
+ }
252
+ /**
253
+ * Apply formatting changes (position based) in reverse
254
+ * from https://github.com/Microsoft/TypeScript/issues/1651#issuecomment-69877863
255
+ */
256
+ applyChanges(orig, changes) {
257
+ let result = orig;
258
+ for (let i = changes.length - 1; i >= 0; i--) {
259
+ const change = changes[i];
260
+ const head = result.slice(0, change.span.start);
261
+ const tail = result.slice(change.span.start + change.span.length);
262
+ result = head + change.newText + tail;
263
+ }
264
+ return result;
265
+ }
266
+ /** Return source file formatting options */
267
+ getFormattingOptions() {
268
+ const formatOptions = {
269
+ // tslint:disable:object-literal-sort-keys
270
+ indentSize: this.formatOptions.indentSize,
271
+ tabSize: 4,
272
+ newLineCharacter: ts.sys.newLine,
273
+ convertTabsToSpaces: this.formatOptions.spaces,
274
+ indentStyle: ts.IndentStyle.Smart,
275
+ insertSpaceAfterCommaDelimiter: true,
276
+ insertSpaceAfterSemicolonInForStatements: true,
277
+ insertSpaceBeforeAndAfterBinaryOperators: true,
278
+ insertSpaceAfterKeywordsInControlFlowStatements: true,
279
+ insertSpaceAfterTypeAssertion: true
280
+ // tslint:enable:object-literal-sort-keys
281
+ };
282
+ return formatOptions;
283
+ }
284
+ /** Get language service host, sloppily */
285
+ getLanguageHost(filePath) {
286
+ const files = {};
287
+ files[filePath] = { version: 0 };
288
+ // create the language service host to allow the LS to communicate with the host
289
+ const servicesHost = {
290
+ getCompilationSettings: () => ({}),
291
+ getScriptFileNames: () => Object.keys(files),
292
+ getScriptVersion: fileName => files[fileName] && files[fileName].version.toString(),
293
+ getScriptSnapshot: fileName => {
294
+ if (!this.fileSystem.fileExists(fileName)) {
295
+ return undefined;
296
+ }
297
+ return ts.ScriptSnapshot.fromString(this.fileSystem.readFile(fileName));
298
+ },
299
+ getCurrentDirectory: () => process.cwd(),
300
+ getDefaultLibFileName: options => ts.getDefaultLibFilePath(options),
301
+ readDirectory: ts.sys.readDirectory,
302
+ readFile: ts.sys.readFile,
303
+ fileExists: ts.sys.fileExists
304
+ };
305
+ return servicesHost;
306
+ }
307
+ //#endregion Formatting
308
+ createVisitor(conditionalVisitor, visitCondition, nodeContext) {
309
+ return function visitor(node) {
310
+ if (visitCondition(node)) {
311
+ node = ts.visitEachChild(node, conditionalVisitor, nodeContext);
312
+ }
313
+ else {
314
+ node = ts.visitEachChild(node, visitor, nodeContext);
315
+ }
316
+ return node;
317
+ };
318
+ }
319
+ createRouteEntry(path, component, name, routerAlias) {
320
+ const routePath = ts.factory.createPropertyAssignment("path", ts.factory.createStringLiteral(path, true));
321
+ const jsxElement = ts.factory.createJsxSelfClosingElement(ts.factory.createIdentifier(component), [], undefined);
322
+ const routeComponent = ts.factory.createPropertyAssignment("element", jsxElement);
323
+ const routeData = ts.factory.createPropertyAssignment("text", ts.factory.createStringLiteral(name, true));
324
+ if (routerAlias) {
325
+ const childrenData = ts.factory.createPropertyAssignment("children", ts.factory.createIdentifier(routerAlias));
326
+ return ts.factory.createObjectLiteralExpression([routePath, routeComponent, routeData, childrenData]);
327
+ }
328
+ else {
329
+ return ts.factory.createObjectLiteralExpression([routePath, routeComponent, routeData]);
330
+ }
331
+ }
332
+ }
333
+ exports.ReactTypeScriptFileUpdate = ReactTypeScriptFileUpdate;
@@ -4,7 +4,7 @@ const cli_core_1 = require("@igniteui/cli-core");
4
4
  class IgrReactProjectLibrary extends cli_core_1.BaseProjectLibrary {
5
5
  constructor() {
6
6
  super(__dirname);
7
- this.name = "Ignite UI for React";
7
+ this.name = "Ignite UI for React (deprecated)";
8
8
  this.projectType = "igr-es6";
9
9
  this.themes = ["default"];
10
10
  const groups = require("./groups.json");
@@ -0,0 +1,8 @@
1
+ import { expect, test } from 'vitest';
2
+ import { render } from '@testing-library/react';
3
+ import $(ClassName) from './index';
4
+
5
+ test('renders $(ClassName) component', () => {
6
+ const wrapper = render(<$(ClassName) />);
7
+ expect(wrapper).toBeTruthy();
8
+ });
@@ -0,0 +1,56 @@
1
+ import { IgrBulletGraphModule } from 'igniteui-react-gauges';
2
+ import { IgrBulletGraph } from 'igniteui-react-gauges';
3
+ import style from './style.module.css';
4
+
5
+ IgrBulletGraphModule.register();
6
+
7
+
8
+ export default function $(ClassName)() {
9
+ const title = 'Bullet Graph';
10
+
11
+ return (
12
+ <div>
13
+ <h1 className={style.title}>{title}</h1>
14
+ <div>
15
+ Read more on the&nbsp;
16
+ <a href="https://www.infragistics.com/products/ignite-ui-react/react/components/bulletgraph.html">
17
+ official documentation page
18
+ </a>
19
+ </div>
20
+ <div className={style.container}>
21
+ <div className={style.graph}>
22
+ <IgrBulletGraph
23
+ height="80px" width="400px"
24
+ minimumValue={0} value={70} interval={10}
25
+ maximumValue={100} targetValue={90}
26
+ isScaleInverted={false}
27
+ scaleBackgroundBrush="DodgerBlue"
28
+ scaleBackgroundOutline="DarkViolet"
29
+ scaleBackgroundThickness={2}
30
+ scaleStartExtent={0.05}
31
+ scaleEndExtent={0.95}>
32
+ </IgrBulletGraph>
33
+ </div>
34
+ <div className={style.graph}>
35
+ <IgrBulletGraph
36
+ value={50}
37
+ valueBrush="DodgerBlue"
38
+ valueStrokeThickness={1}
39
+ valueInnerExtent={0.5}
40
+ valueOuterExtent={0.65}
41
+ targetValue={80}
42
+ targetValueBreadth={10}
43
+ targetValueBrush="LimeGreen"
44
+ targetValueOutline="LimeGreen"
45
+ targetValueStrokeThickness={1}
46
+ targetValueInnerExtent={0.3}
47
+ targetValueOuterExtent={0.85}
48
+ height="80px" width="400px"
49
+ minimumValue={0}
50
+ maximumValue={100}>
51
+ </IgrBulletGraph>
52
+ </div>
53
+ </div>
54
+ </div>
55
+ )
56
+ }