@lukfel/ng-scaffold 20.0.48 → 20.0.50

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lukfel/ng-scaffold",
3
- "version": "20.0.48",
3
+ "version": "20.0.50",
4
4
  "description": "This Angular library provides a basic UI scaffold and services for modern web and mobile apps",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -16,9 +16,6 @@
16
16
  "@angular/core": "^20.0.5",
17
17
  "@angular/material": "^20.0.5"
18
18
  },
19
- "dependencies": {
20
- "tslib": "^2.3.0"
21
- },
22
19
  "exports": {
23
20
  "./styles": {
24
21
  "sass": "./styles/style.scss"
@@ -37,5 +34,8 @@
37
34
  },
38
35
  "sideEffects": false,
39
36
  "module": "fesm2022/lukfel-ng-scaffold.mjs",
40
- "typings": "index.d.ts"
37
+ "typings": "index.d.ts",
38
+ "dependencies": {
39
+ "tslib": "^2.3.0"
40
+ }
41
41
  }
@@ -2,9 +2,9 @@
2
2
  "$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
3
3
  "schematics": {
4
4
  "ng-add": {
5
- "description": "Add ng-scaffold to the project",
5
+ "description": "Add ng-scaffold to the project.",
6
6
  "factory": "./ng-add/index#ngAdd",
7
7
  "schema": "./ng-add/schema.json"
8
8
  }
9
9
  }
10
- }
10
+ }
@@ -0,0 +1,2 @@
1
+ import { Rule } from '@angular-devkit/schematics';
2
+ export declare function addStyles(): Rule;
@@ -1,40 +1,38 @@
1
- import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics';
2
-
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addStyles = addStyles;
3
4
  const SNIPPET = `
4
5
  @use "@lukfel/ng-scaffold/styles" as lf;
5
6
  // Create a base theme and include it with @include lf.scaffold-theme($base-theme);
6
7
  // Include additional themes with @include lf.scaffold-colors($theme2, 'theme2');
7
8
 
8
- `;
9
-
10
- export function addStyles(): Rule {
11
- return (tree: Tree, context: SchematicContext) => {
12
- context.logger.info('[Styles] Searching for styles file ...');
13
-
14
- const possiblePaths = [
15
- 'src/styles.scss',
16
- 'src/styles.sass',
17
- 'src/styles.css',
18
- 'src/styles.css.scss',
19
- 'styles.scss'
20
- ];
21
-
22
- const path = possiblePaths.find(p => tree.exists(p));
23
- if (!path) {
24
- context.logger.warn('[Styles] No global styles file found. Skip.');
25
- return tree
26
- };
27
-
28
- const content = tree.read(path)!.toString('utf-8');
29
- if (content.includes('@lukfel/ng-scaffold/styles') || content.includes('lf.scaffold-theme')) {
30
- context.logger.info('[Styles] Styles already added. Skip.');
31
- return tree;
32
- }
33
-
34
- const recorder = tree.beginUpdate(path);
35
- recorder.insertLeft(content.length, SNIPPET);
36
- tree.commitUpdate(recorder);
37
- context.logger.info('[Styles] Successfully added.');
38
- return tree;
39
- };
40
- }
9
+ `;
10
+ function addStyles() {
11
+ return (tree, context) => {
12
+ context.logger.info('[Styles] Searching for styles file ...');
13
+ const possiblePaths = [
14
+ 'src/styles.scss',
15
+ 'src/styles.sass',
16
+ 'src/styles.css',
17
+ 'src/styles.css.scss',
18
+ 'styles.scss'
19
+ ];
20
+ const path = possiblePaths.find(p => tree.exists(p));
21
+ if (!path) {
22
+ context.logger.warn('[Styles] No global styles file found. Skip.');
23
+ return tree;
24
+ }
25
+ ;
26
+ const content = tree.read(path).toString('utf-8');
27
+ if (content.includes('@lukfel/ng-scaffold/styles') || content.includes('lf.scaffold-theme')) {
28
+ context.logger.info('[Styles] Styles already added. Skip.');
29
+ return tree;
30
+ }
31
+ const recorder = tree.beginUpdate(path);
32
+ recorder.insertLeft(content.length, SNIPPET);
33
+ tree.commitUpdate(recorder);
34
+ context.logger.info('[Styles] Successfully added.');
35
+ return tree;
36
+ };
37
+ }
38
+ //# sourceMappingURL=add-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-styles.js","sourceRoot":"","sources":["../../../../projects/ng-scaffold/schematics/ng-add/add-styles.ts"],"names":[],"mappings":";;AASA,8BA8BC;AArCD,MAAM,OAAO,GAAG;;;;;CAKf,CAAC;AAEF,SAAgB,SAAS;IACrB,OAAO,CAAC,IAAU,EAAE,OAAyB,EAAE,EAAE;QAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;QAE9D,MAAM,aAAa,GAAG;YAClB,iBAAiB;YACjB,iBAAiB;YACjB,gBAAgB;YAChB,qBAAqB;YACrB,aAAa;SAChB,CAAC;QAEF,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QACrD,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;YACnE,OAAO,IAAI,CAAA;QACf,CAAC;QAAA,CAAC;QAEF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACnD,IAAI,OAAO,CAAC,QAAQ,CAAC,4BAA4B,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC;YAC1F,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;YAC5D,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACxC,QAAQ,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7C,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAC5B,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;AACN,CAAC"}
@@ -0,0 +1,2 @@
1
+ import { Rule } from '@angular-devkit/schematics';
2
+ export default function ngAdd(): Rule;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = ngAdd;
4
+ const schematics_1 = require("@angular-devkit/schematics");
5
+ // import { addModule } from './add-module';
6
+ // import { addService } from './add-service';
7
+ const add_styles_1 = require("./add-styles");
8
+ // import { addTemplate } from './add-template';
9
+ function ngAdd() {
10
+ return (0, schematics_1.chain)([
11
+ // addModule(),
12
+ // addService(),
13
+ // addTemplate(),
14
+ (0, add_styles_1.addStyles)(),
15
+ ]);
16
+ }
17
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ng-scaffold/schematics/ng-add/index.ts"],"names":[],"mappings":";;AAMA,wBAOC;AAbD,2DAAyD;AACzD,4CAA4C;AAC5C,8CAA8C;AAC9C,6CAAyC;AACzC,gDAAgD;AAEhD,SAAwB,KAAK;IACzB,OAAO,IAAA,kBAAK,EAAC;QACT,eAAe;QACf,gBAAgB;QAChB,iBAAiB;QACjB,IAAA,sBAAS,GAAE;KACd,CAAC,CAAC;AACP,CAAC"}
@@ -1,74 +0,0 @@
1
- import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
2
- import * as ts from 'typescript';
3
- import { getTsSourceFile } from './ts-ast-utils';
4
-
5
- export function addModule(): Rule {
6
- return (tree: Tree) => {
7
- const mainPaths = ['src/main.ts', 'main.ts'];
8
- let mainPath: string | undefined;
9
-
10
- for (const p of mainPaths) {
11
- if (tree.exists(p)) {
12
- mainPath = p;
13
- break;
14
- }
15
- }
16
-
17
- // --- 1) Standalone bootstrap ---
18
- if (mainPath) {
19
- const sourceFile = getTsSourceFile(tree, mainPath);
20
- if (!sourceFile) throw new SchematicsException(`Could not read ${mainPath}`);
21
- const content = tree.read(mainPath)!.toString('utf-8');
22
-
23
- if (!content.includes('@lukfel/ng-scaffold')) {
24
- const importStatements = sourceFile.statements.filter(s => ts.isImportDeclaration(s));
25
- const insertPos = importStatements.length ? importStatements[importStatements.length - 1].end + 1 : 0;
26
- const recorder = tree.beginUpdate(mainPath);
27
- recorder.insertLeft(insertPos, 'import { ScaffoldModule } from \'@lukfel/ng-scaffold\';\n');
28
- tree.commitUpdate(recorder);
29
- }
30
- return tree;
31
- }
32
-
33
- // --- 2) NgModule ---
34
- const modulePaths = ['src/app/app.module.ts', 'app.module.ts'];
35
- for (const mp of modulePaths) {
36
- if (!tree.exists(mp)) continue;
37
- const sourceFile = getTsSourceFile(tree, mp);
38
- if (!sourceFile) continue;
39
- let content = tree.read(mp)!.toString('utf-8');
40
-
41
- // Add import if missing
42
- if (!content.includes('@lukfel/ng-scaffold')) {
43
- const importStatements = sourceFile.statements.filter(s => ts.isImportDeclaration(s));
44
- const insertPos = importStatements.length ? importStatements[importStatements.length - 1].end + 1 : 0;
45
- const recorder = tree.beginUpdate(mp);
46
- recorder.insertLeft(insertPos, 'import { ScaffoldModule } from \'@lukfel/ng-scaffold\';\n');
47
- tree.commitUpdate(recorder);
48
- content = tree.read(mp)!.toString('utf-8');
49
- }
50
-
51
- // Add ScaffoldModule to imports array
52
- const importsMatch = /imports\s*:\s*\[([\s\S]*?)\]/m.exec(content);
53
- if (importsMatch) {
54
- const arrayStart = content.indexOf('[', importsMatch.index) + 1;
55
- const recorder = tree.beginUpdate(mp);
56
- recorder.insertLeft(arrayStart, ' ScaffoldModule,');
57
- tree.commitUpdate(recorder);
58
- return tree;
59
- }
60
- // No imports array: insert one
61
- const ngModuleMatch = /@NgModule\s*\(\s*\{/.exec(content);
62
- if (ngModuleMatch) {
63
- const insertPos = ngModuleMatch.index + ngModuleMatch[0].length;
64
- const recorder = tree.beginUpdate(mp);
65
- recorder.insertLeft(insertPos, '\n imports: [ScaffoldModule],');
66
- tree.commitUpdate(recorder);
67
- return tree;
68
- }
69
-
70
- }
71
-
72
- throw new SchematicsException('Could not find main.ts or app.module.ts to add ScaffoldModule');
73
- };
74
- }
@@ -1,117 +0,0 @@
1
- import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
2
- import * as ts from 'typescript';
3
-
4
- function detectBootstrapComponent(tree: Tree): { className: string, filePath: string } | null {
5
- // Reuse the same detection logic as addTemplate
6
- const mainPaths = ['src/main.ts', 'main.ts'];
7
- for (const mp of mainPaths) {
8
- if (!tree.exists(mp)) continue;
9
- const text = tree.read(mp)!.toString('utf-8');
10
- // eslint-disable-next-line no-useless-escape
11
- const match = /bootstrapApplication\(([^,\)]+)/.exec(text);
12
- if (match) {
13
- const className = match[1].trim();
14
- const importMatch = new RegExp(`import\\s+\\{?\\s*${className}\\s*\\}?\\s+from\\s+['"](.*)['"]`).exec(text);
15
- if (importMatch) {
16
- const importPath = importMatch[1].startsWith('.') ? importMatch[1] : `./${importMatch[1]}`;
17
- const filePath = `src/${importPath.replace(/^\.\/+/, '')}.ts`;
18
- if (tree.exists(filePath)) return { className, filePath };
19
- }
20
- }
21
- }
22
-
23
- const modulePaths = ['src/app/app.module.ts', 'app.module.ts'];
24
- for (const mp of modulePaths) {
25
- if (!tree.exists(mp)) continue;
26
- const text = tree.read(mp)!.toString('utf-8');
27
- const match = /bootstrap\s*:\s*\[([^\]]+)\]/.exec(text);
28
- if (match) {
29
- const className = match[1].split(',')[0].trim();
30
- const importMatch = new RegExp(`import\\s+\\{?\\s*${className}\\s*\\}?\\s+from\\s+['"](.*)['"]`).exec(text);
31
- if (importMatch) {
32
- const importPath = importMatch[1].startsWith('.') ? importMatch[1] : `./${importMatch[1]}`;
33
- const filePath = `src/${importPath.replace(/^\.\/+/, '')}.ts`;
34
- if (tree.exists(filePath)) return { className, filePath };
35
- }
36
- }
37
- }
38
-
39
- return null;
40
- }
41
-
42
- export function addService(): Rule {
43
- return (tree: Tree) => {
44
- const detected = detectBootstrapComponent(tree);
45
- if (!detected) throw new SchematicsException('Could not detect bootstrap component');
46
-
47
- const { className, filePath } = detected;
48
- if (!tree.exists(filePath)) throw new SchematicsException(`Component file not found: ${filePath}`);
49
-
50
- let content = tree.read(filePath)!.toString('utf-8');
51
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
52
- const recorder = tree.beginUpdate(filePath);
53
-
54
- // Add imports if missing
55
- if (!content.includes('@lukfel/ng-scaffold')) {
56
- content = 'import { ScaffoldService, ScaffoldConfig } from \'@lukfel/ng-scaffold\';\n' + content;
57
- }
58
- if (!content.includes('inject')) {
59
- content = 'import { inject } from \'@angular/core\';\n' + content;
60
- }
61
-
62
- // Find class node
63
- let classNode: ts.ClassDeclaration | undefined;
64
- function visit(node: ts.Node): void {
65
- if (ts.isClassDeclaration(node) && node.name?.text === className) {
66
- classNode = node;
67
- } else ts.forEachChild(node, visit);
68
- }
69
- visit(sourceFile);
70
-
71
- if (!classNode) throw new SchematicsException(`Could not find class ${className} in ${filePath}`);
72
-
73
- // Determine constructor
74
- const constructorNode = classNode.members.find(ts.isConstructorDeclaration);
75
-
76
- if (constructorNode) {
77
- // Existing constructor: inject via parameter if missing
78
- const paramExists = constructorNode.parameters.some(p =>
79
- p.type?.getText(sourceFile).includes('ScaffoldService')
80
- );
81
- if (!paramExists) {
82
- const ctorStart = constructorNode.getStart(sourceFile);
83
- const ctorText = constructorNode.getFullText(sourceFile);
84
- const insertPos = ctorStart + ctorText.indexOf('(') + 1;
85
- recorder.insertLeft(insertPos, 'private scaffoldService: ScaffoldService, ');
86
- }
87
-
88
- // Add assignment inside constructor body if missing
89
- const bodyStart = constructorNode.body!.getStart(sourceFile);
90
- const bodyEnd = constructorNode.body!.getEnd();
91
- const bodyText = content.slice(bodyStart, bodyEnd);
92
- if (!bodyText.includes('this.scaffoldService.scaffoldConfig')) {
93
- recorder.insertLeft(bodyEnd - 1, '\n this.scaffoldService.scaffoldConfig = this.scaffoldConfig;\n');
94
- }
95
- } else {
96
- // No constructor: use inject() + new constructor
97
- const classStart = classNode.getStart(sourceFile);
98
- const classHeaderEnd = content.indexOf('{', classStart) + 1;
99
-
100
- const snippet = `
101
- private scaffoldService = inject(ScaffoldService);
102
- private scaffoldConfig: ScaffoldConfig = {
103
- // Create your own config or generate it at https://lukfel.github.io/ng-scaffold
104
- };
105
- constructor() {
106
- this.scaffoldService.scaffoldConfig = this.scaffoldConfig;
107
- }
108
- `;
109
-
110
- recorder.insertLeft(classHeaderEnd, snippet);
111
- }
112
-
113
- tree.commitUpdate(recorder);
114
- return tree;
115
- };
116
- }
117
-
@@ -1,107 +0,0 @@
1
- import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
2
- import * as ts from 'typescript';
3
-
4
- function detectBootstrapComponent(tree: Tree): { className: string, filePath: string } | null {
5
- // simplified detection: main.ts (standalone) or AppModule
6
- const mainPaths = ['src/main.ts', 'main.ts'];
7
- for (const mp of mainPaths) {
8
- if (!tree.exists(mp)) continue;
9
- const text = tree.read(mp)!.toString('utf-8');
10
- // eslint-disable-next-line no-useless-escape
11
- const match = /bootstrapApplication\(([^,\)]+)/.exec(text);
12
- if (match) {
13
- const className = match[1].trim();
14
- const importMatch = new RegExp(`import\\s+\\{?\\s*${className}\\s*\\}?\\s+from\\s+['"](.*)['"]`).exec(text);
15
- if (importMatch) {
16
- const importPath = importMatch[1].startsWith('.') ? importMatch[1] : `./${importMatch[1]}`;
17
- const filePath = `src/${importPath.replace(/^\.\/+/, '')}.ts`;
18
- if (tree.exists(filePath)) return { className, filePath };
19
- }
20
- }
21
- }
22
-
23
- const modulePaths = ['src/app/app.module.ts', 'app.module.ts'];
24
- for (const mp of modulePaths) {
25
- if (!tree.exists(mp)) continue;
26
- const text = tree.read(mp)!.toString('utf-8');
27
- const match = /bootstrap\s*:\s*\[([^\]]+)\]/.exec(text);
28
- if (match) {
29
- const className = match[1].split(',')[0].trim();
30
- const importMatch = new RegExp(`import\\s+\\{?\\s*${className}\\s*\\}?\\s+from\\s+['"](.*)['"]`).exec(text);
31
- if (importMatch) {
32
- const importPath = importMatch[1].startsWith('.') ? importMatch[1] : `./${importMatch[1]}`;
33
- const filePath = `src/${importPath.replace(/^\.\/+/, '')}.ts`;
34
- if (tree.exists(filePath)) return { className, filePath };
35
- }
36
- }
37
- }
38
-
39
- return null;
40
- }
41
-
42
- export function addTemplate(): Rule {
43
- return (tree: Tree) => {
44
- const detected = detectBootstrapComponent(tree);
45
- if (!detected) throw new SchematicsException('Could not detect bootstrap component');
46
-
47
- const { className, filePath } = detected;
48
- if (!tree.exists(filePath)) throw new SchematicsException(`Component file not found: ${filePath}`);
49
-
50
- const content = tree.read(filePath)!.toString('utf-8');
51
- const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);
52
- const recorder = tree.beginUpdate(filePath);
53
- let modified = false;
54
-
55
- function visit(node: ts.Node): void {
56
- if (ts.isClassDeclaration(node) && node.name?.text === className) {
57
- // ✅ Correct type assertion for decorators
58
- const decorators = (node as ts.ClassDeclaration & { decorators?: ts.NodeArray<ts.Decorator> }).decorators;
59
- if (!decorators) return;
60
-
61
- const componentDecorator = decorators.find(d => d.getText(sourceFile).startsWith('@Component'));
62
- if (!componentDecorator) return;
63
-
64
- const decoratorText = componentDecorator.getFullText(sourceFile);
65
-
66
- // templateUrl
67
- const templateUrlMatch = /templateUrl\s*:\s*['"`](.*?)['"`]/.exec(decoratorText);
68
- if (templateUrlMatch) {
69
- const templatePathRaw = templateUrlMatch[1];
70
- // eslint-disable-next-line no-useless-escape
71
- const compDir = filePath.replace(/\/[^\/]+$/, '');
72
- let templatePath = templatePathRaw.startsWith('./')
73
- ? `${compDir}/${templatePathRaw.slice(2)}`
74
- : `${compDir}/${templatePathRaw}`;
75
- if (!tree.exists(templatePath)) templatePath += '.html';
76
- if (!tree.exists(templatePath)) throw new SchematicsException(`Template not found: ${templatePath}`);
77
- const html = tree.read(templatePath)!.toString('utf-8');
78
- if (!html.includes('<lf-scaffold>')) {
79
- recorder.remove(0, html.length);
80
- recorder.insertLeft(0, `<lf-scaffold>\n${html}\n</lf-scaffold>`);
81
- modified = true;
82
- }
83
- } else {
84
- // inline template
85
- const templateMatch = /template\s*:\s*(`([\s\S]*?)`|['"`]([\s\S]*?)['"`])/.exec(decoratorText);
86
- if (templateMatch) {
87
- const inner = templateMatch[2] ?? templateMatch[3] ?? '';
88
- const start = content.indexOf(inner);
89
- if (start !== -1) {
90
- recorder.remove(start, inner.length);
91
- recorder.insertLeft(start, `<lf-scaffold>\n${inner}\n</lf-scaffold>`);
92
- modified = true;
93
- }
94
- }
95
- }
96
- } else {
97
- ts.forEachChild(node, visit);
98
- }
99
- }
100
-
101
- visit(sourceFile);
102
-
103
- if (modified) tree.commitUpdate(recorder);
104
-
105
- return tree;
106
- };
107
- }
@@ -1,14 +0,0 @@
1
- import { chain, Rule } from '@angular-devkit/schematics';
2
- // import { addModule } from './add-module';
3
- // import { addService } from './add-service';
4
- import { addStyles } from './add-styles';
5
- // import { addTemplate } from './add-template';
6
-
7
- export default function ngAdd(): Rule {
8
- return chain([
9
- // addModule(),
10
- // addService(),
11
- // addTemplate(),
12
- addStyles(),
13
- ]);
14
- }
@@ -1,29 +0,0 @@
1
- import { Tree } from '@angular-devkit/schematics';
2
- import { InsertChange, ReplaceChange } from '@schematics/angular/utility/change';
3
- import * as ts from 'typescript';
4
-
5
- /**
6
- * Read a file into a ts.SourceFile
7
- */
8
- export function getTsSourceFile(tree: Tree, path: string): ts.SourceFile | null {
9
- const buffer = tree.read(path);
10
- if (!buffer) return null;
11
- const content = buffer.toString('utf-8');
12
- return ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
13
- }
14
-
15
- /**
16
- * Create InsertChange or ReplaceChange compatible object
17
- */
18
- export function applyInsertChanges(tree: Tree, filePath: string, changes: Array<InsertChange | ReplaceChange>): void {
19
- const recorder = tree.beginUpdate(filePath);
20
- for (const change of changes) {
21
- // InsertChange has 'pos' and 'toAdd'
22
- if ((change as any).pos !== undefined && (change as any).toAdd !== undefined) {
23
- recorder.insertLeft((change as any).pos, (change as any).toAdd);
24
- } else if ((change as any).order != undefined) {
25
- // ignore other change shapes
26
- }
27
- }
28
- tree.commitUpdate(recorder);
29
- }