Skip to content

Commit f67f917

Browse files
authored
Merge pull request #18 from kaltepeter/feature/schemas
feat(schemas): extend schema and split builders
2 parents 0615740 + 4d3171b commit f67f917

File tree

12 files changed

+512
-144
lines changed

12 files changed

+512
-144
lines changed

README.md

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,16 @@ Angular CLI: `ng add @angular-extensions/svg-icons-builder`
1919

2020
### Configuring the builder
2121

22-
To use the builder you need to add a new entry to your `architect` object inside your `angular.json`. In our example we call it `generate-icons`. You then need to specify the following properties:
22+
To use the builder you need to add a new entry to your `architect` object inside your `angular.json`.
2323

24-
- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-builder"`
25-
- **Config**: A valid [svg-to-ts configuration](https://github.com/kreuzerk/svg-to-ts). ⚠️ the options depend on the `conversionType` and may therefore vary. Means, a configuration for the `convesionType: "files"` will look different than configuration for the `conversionType: "constants"`
24+
A valid [svg-to-ts configuration](https://github.com/kreuzerk/svg-to-ts). ⚠️ the options depend on the `conversionType` and may therefore vary. Means, a configuration for the `convesionType: "files"` will look different than configuration for the `conversionType: "constants"`. Each `conversionType` has it's own builder.
25+
26+
In our example we call it `generate-icons`. You then need to specify the following properties:
27+
28+
## `conversionType: constants`
29+
30+
- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-constants-builder"`
31+
- **Config**: [svg-to-ts constants config](https://github.com/kreuzerk/svg-to-ts#2-multiple-constants---treeshakable-and-typesafe-with-one-file-conversiontypeconstants)
2632

2733
```json
2834
"generate-icons": {
@@ -48,6 +54,68 @@ To use the builder you need to add a new entry to your `architect` object inside
4854
}
4955
```
5056

57+
## `conversionType: files`
58+
59+
- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-files-builder"`
60+
- **Config**: [svg-to-ts files config](https://github.com/kreuzerk/svg-to-ts#3-tree-shakable-and-optimized-for-lazy-loading-conversiontypefiles)
61+
62+
```json
63+
"generate-icons": {
64+
"builder": "@angular-extensions/svg-icons-builder:svg-icons-files-builder",
65+
"options": {
66+
"conversionType": "files",
67+
"srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
68+
"outputDirectory": "./projects/dinosaur-icons/icons",
69+
"interfaceName": "DinosaurIcon",
70+
"generateType": false,
71+
"generateTypeObject": false,
72+
"generateCompleteIconSet": false,
73+
"exportCompleteIconSet": false,
74+
"fileName": "dinosaur-icons",
75+
"iconsFolderName": "dinosaur-icons",
76+
"objectName": "dinosaur-icons",
77+
"typeName": "dinosaurIcon",
78+
"prefix": "dinosaurIcon",
79+
"modelFileName": "dinosaur-icons",
80+
"barrelFileName": "index",
81+
"svgoConfig": {
82+
"plugins": [
83+
{
84+
"cleanupAttrs": true
85+
}
86+
]
87+
},
88+
"compileSources": true
89+
}
90+
}
91+
```
92+
93+
## `conversionType: object`
94+
95+
- **Builder**: `"@angular-extensions/svg-icons-builder:svg-icons-object-builder"`
96+
- **Config**: [svg-to-ts object config](https://github.com/kreuzerk/svg-to-ts#1-converting-to-a-single-object-conversiontypeobject)
97+
98+
```json
99+
"generate-icons": {
100+
"builder": "@angular-extensions/svg-icons-builder:svg-icons-object-builder",
101+
"options": {
102+
"conversionType": "object",
103+
"srcFiles": ["./projects/dinosaur-icons/icons/**/*.svg"],
104+
"outputDirectory": "./projects/dinosaur-icons/icons",
105+
"fileName": "dinosaur-icons",
106+
"objectName": "dinosaur-icons",
107+
"svgoConfig": {
108+
"plugins": [
109+
{
110+
"cleanupAttrs": true
111+
}
112+
]
113+
},
114+
"compileSources": true
115+
}
116+
}
117+
```
118+
51119
### Run the builder
52120

53121
In order to run the builder you have to add a new npm script to your `package.json`. Replace `name-of-your-app` with the name of your application 😉.

builders.json

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
11
{
2+
"$schema": "@angular-devkit/architect/src/builders-schema.json",
23
"builders": {
3-
"svg-icons-builder": {
4-
"implementation": "./svg-icons-builder",
4+
"svg-icons-constants-builder": {
5+
"implementation": "./svg-icons-builder/constants",
56
"schema": "./svg-icons-builder/schema.json",
6-
"description": "Build SVG icons."
7+
"description": "Build SVG icons using `constants` conversion type."
8+
},
9+
"svg-icons-object-builder": {
10+
"implementation": "./svg-icons-builder/object",
11+
"schema": "./svg-icons-builder/schema.json",
12+
"description": "Build SVG icons using `objects` conversion type."
13+
},
14+
"svg-icons-files-builder": {
15+
"implementation": "./svg-icons-builder/files",
16+
"schema": "./svg-icons-builder/schema.json",
17+
"description": "Build SVG icons using `files` conversion type."
718
}
819
}
920
}

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import { Architect } from '@angular-devkit/architect';
2+
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
3+
import { logging, schema } from '@angular-devkit/core';
4+
import { ConversionType } from 'svg-to-ts';
5+
import { defaultCommonOptions } from '../test-helpers';
6+
const { join } = require('path');
7+
8+
describe('svg-icons-builder', () => {
9+
let architect: Architect;
10+
let architectHost: TestingArchitectHost;
11+
12+
beforeEach(async () => {
13+
const registry = new schema.CoreSchemaRegistry();
14+
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
15+
const workspaceRoot = join(__dirname, '..', '..');
16+
17+
architectHost = new TestingArchitectHost('/root', '/root');
18+
architect = new Architect(architectHost, registry);
19+
20+
await architectHost.addBuilderFromPackage(workspaceRoot);
21+
});
22+
23+
it('generates `constants` for icons', async () => {
24+
const logger = new logging.Logger('');
25+
const logs: string[] = [];
26+
logger.subscribe((ev) => logs.push(ev.message));
27+
28+
const run = await architect.scheduleBuilder(
29+
'@angular-extensions/svg-icons-builder:svg-icons-constants-builder',
30+
{
31+
...defaultCommonOptions(),
32+
conversionType: ConversionType.CONSTANTS,
33+
fileName: 'dinosaur-icons',
34+
typeName: 'dinosaurIcon',
35+
generateType: true,
36+
generateTypeObject: true,
37+
generateCompleteIconSet: true,
38+
prefix: 'dinosaurIcon',
39+
interfaceName: 'DinosaurIcon',
40+
},
41+
{ logger }
42+
);
43+
44+
expect(await run.result).toEqual(
45+
expect.objectContaining({
46+
success: true,
47+
})
48+
);
49+
50+
await run.stop();
51+
52+
expect(logs).toContain('We are using the conversion type "constants"');
53+
});
54+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
2+
import { JsonObject } from '@angular-devkit/core';
3+
import { ConstantsConversionOptions, ConversionType, convertToConstants, mergeWithDefaults } from 'svg-to-ts';
4+
5+
interface Options extends ConstantsConversionOptions {}
6+
7+
// Using `Options & JsonObject` instead of extending JsonObject because of optional boolean
8+
export default createBuilder<Options & JsonObject>((options: Options, context: BuilderContext) => {
9+
return new Promise<BuilderOutput>(async (resolve, reject) => {
10+
try {
11+
if (options.conversionType !== ConversionType.CONSTANTS) {
12+
reject(new Error(`This builder only supports '${ConversionType.CONSTANTS}' conversionType.`));
13+
}
14+
15+
const conversionOptions = await mergeWithDefaults(options);
16+
context.logger.info('We are using the conversion type "constants"');
17+
await convertToConstants((conversionOptions as unknown) as ConstantsConversionOptions);
18+
19+
resolve({ success: true });
20+
context.reportStatus(`Done.`);
21+
} catch (error) {
22+
context.reportStatus(`Error: ${error.message}`);
23+
reject(error);
24+
process.disconnect();
25+
process.exit(1);
26+
}
27+
});
28+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Architect } from '@angular-devkit/architect';
2+
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
3+
import { logging, schema } from '@angular-devkit/core';
4+
import { defaultCommonOptions } from '../test-helpers';
5+
const { join } = require('path');
6+
7+
describe('svg-icons-builder', () => {
8+
let architect: Architect;
9+
let architectHost: TestingArchitectHost;
10+
11+
beforeEach(async () => {
12+
const registry = new schema.CoreSchemaRegistry();
13+
registry.addPostTransform(schema.transforms.addUndefinedDefaults);
14+
const workspaceRoot = join(__dirname, '..', '..');
15+
16+
architectHost = new TestingArchitectHost('/root', '/root');
17+
architect = new Architect(architectHost, registry);
18+
19+
await architectHost.addBuilderFromPackage(workspaceRoot);
20+
console.log('#', Array.from((architectHost as any)._builderMap.keys()));
21+
});
22+
23+
it('generates `files` for icons', async () => {
24+
const logger = new logging.Logger('');
25+
const logs: string[] = [];
26+
logger.subscribe((ev) => logs.push(ev.message));
27+
28+
const run = await architect.scheduleBuilder(
29+
'@angular-extensions/svg-icons-builder:svg-icons-files-builder',
30+
{
31+
...defaultCommonOptions(),
32+
conversionType: 'files',
33+
typeName: 'dinosaurIcon',
34+
generateType: true,
35+
generateTypeObject: true,
36+
exportCompleteIconSet: true,
37+
prefix: 'dinosaurIcon',
38+
interfaceName: 'DinosaurIcon',
39+
modelFileName: 'dinosaur-icons.model',
40+
iconsFolderName: 'build',
41+
compileSources: true,
42+
barrelFileName: 'index',
43+
},
44+
{ logger }
45+
);
46+
47+
expect(await run.result).toEqual(
48+
expect.objectContaining({
49+
success: true,
50+
})
51+
);
52+
53+
await run.stop();
54+
55+
expect(logs).toContain('We are using the conversion type "files"');
56+
});
57+
});

svg-icons-builder/files/index.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
2+
import { JsonObject } from '@angular-devkit/core';
3+
import {
4+
ConversionType,
5+
FileConversionOptions,
6+
convertToFiles,
7+
mergeWithDefaults,
8+
} from 'svg-to-ts';
9+
10+
interface Options extends FileConversionOptions {}
11+
12+
// Using `Options & JsonObject` instead of extending JsonObject because of optional boolean
13+
export default createBuilder<Options & JsonObject>((options: Options, context: BuilderContext) => {
14+
return new Promise<BuilderOutput>(async (resolve, reject) => {
15+
try {
16+
if (options.conversionType !== ConversionType.FILES) {
17+
reject(new Error(`This builder only supports '${ConversionType.FILES}' conversionType.`));
18+
}
19+
20+
const conversionOptions = await mergeWithDefaults(options);
21+
context.logger.info('We are using the conversion type "files"');
22+
await convertToFiles((conversionOptions as unknown) as FileConversionOptions);
23+
24+
resolve({ success: true });
25+
context.reportStatus(`Done.`);
26+
} catch (error) {
27+
context.reportStatus(`Error: ${error.message}`);
28+
reject(error);
29+
process.disconnect();
30+
process.exit(1);
31+
}
32+
});
33+
});

svg-icons-builder/index.ts

Lines changed: 0 additions & 48 deletions
This file was deleted.

0 commit comments

Comments
 (0)