-
Notifications
You must be signed in to change notification settings - Fork 126
/
Copy pathgenerate-value-accessors.ts
91 lines (72 loc) · 3.56 KB
/
generate-value-accessors.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import path from 'path';
import { OutputTargetAngular, ValueAccessorTypes } from './types';
import { CompilerCtx, ComponentCompilerMeta, Config } from '@stencil/core/internal';
interface ValueAccessor {
elementSelectors: string[];
eventTargets: [string, string][];
}
type NormalizedValueAccessors = {
[T in ValueAccessorTypes]: ValueAccessor
};
export default async function generateValueAccessors(compilerCtx: CompilerCtx, components: ComponentCompilerMeta[], outputTarget: OutputTargetAngular, config: Config) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) || outputTarget.valueAccessorConfigs.length === 0) {
return;
}
const targetDir = path.dirname(outputTarget.directivesProxyFile);
const normalizedValueAccessors: NormalizedValueAccessors = outputTarget.valueAccessorConfigs.reduce((allAccessors, va) => {
const elementSelectors = (Array.isArray(va.elementSelectors)) ? va.elementSelectors : [va.elementSelectors];
const type = va.type;
let allElementSelectors: string[] = [];
let allEventTargets: [string, string][] = [];
if (allAccessors.hasOwnProperty(type)) {
allElementSelectors = allAccessors[type].elementSelectors;
allEventTargets = allAccessors[type].eventTargets;
}
return {
...allAccessors,
[type]: {
elementSelectors: allElementSelectors.concat(elementSelectors),
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]])
}
};
}, {} as NormalizedValueAccessors);
await copyResources(config, ['value-accessor.ts'], targetDir);
return Promise.all(Object.keys(normalizedValueAccessors).map((type) => {
const valueAccessorType = type as ValueAccessorTypes; // Object.keys converts to string
return writeValueAccessor(valueAccessorType, normalizedValueAccessors[valueAccessorType], compilerCtx, targetDir);
}));
}
async function writeValueAccessor(type: ValueAccessorTypes, valueAccessor: ValueAccessor, compilerCtx: CompilerCtx, targetDir: string) {
const targetFileName = `${type}-value-accessor.ts`;
const srcFilePath = path.join(__dirname, '../resources/control-value-accessors/', targetFileName);
const targetFilePath = path.join(targetDir, `${type}-value-accessor.ts`);
const srcFileContents = await compilerCtx.fs.readFile(srcFilePath);
const hostContents = valueAccessor.eventTargets.map((listItem) =>
VALUE_ACCESSOR_EVENTTARGETS
.replace(VALUE_ACCESSOR_EVENT, listItem[0])
.replace(VALUE_ACCESSOR_TARGETATTR, listItem[1])
);
const finalText = srcFileContents
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join(',\n'))
.replace(VALUE_ACCESSOR_TARGETATTR, valueAccessor.eventTargets[0][1])
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}
function copyResources(config: Config, resourcesFilesToCopy: string[], directory: string) {
if (!config.sys || !config.sys.copy) {
throw new Error('stencil is not properly initialized at this step. Notify the developer');
}
return config.sys.copy(
resourcesFilesToCopy.map(rf => ({
src: path.join(__dirname, '../resources/control-value-accessors/', rf),
dest: path.join(directory, rf),
keepDirStructure: true,
warn: false
})),
''
);
}
const VALUE_ACCESSOR_SELECTORS = `<VALUE_ACCESSOR_SELECTORS>`;
const VALUE_ACCESSOR_EVENT = `<VALUE_ACCESSOR_EVENT>`;
const VALUE_ACCESSOR_TARGETATTR = '<VALUE_ACCESSOR_TARGETATTR>';
const VALUE_ACCESSOR_EVENTTARGETS = ` '(<VALUE_ACCESSOR_EVENT>)': 'handleChangeEvent($event.target.<VALUE_ACCESSOR_TARGETATTR>)'`;