Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@stencil/angular-output-target

Package Overview
Dependencies
Maintainers
11
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@stencil/angular-output-target - npm Package Compare versions

Comparing version 0.0.3 to 0.0.4

dist/generate-angular-component.d.ts

2

dist/generate-value-accessors.d.ts
import { OutputTargetAngular } from './types';
import { CompilerCtx, ComponentCompilerMeta, Config } from '@stencil/core/internal';
export default function generateValueAccessors(compilerCtx: CompilerCtx, components: ComponentCompilerMeta[], outputTarget: OutputTargetAngular, config: Config): Promise<void[] | undefined>;
export default function generateValueAccessors(compilerCtx: CompilerCtx, components: ComponentCompilerMeta[], outputTarget: OutputTargetAngular, config: Config): Promise<void>;
import path from 'path';
export default async function generateValueAccessors(compilerCtx, components, outputTarget, config) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) || outputTarget.valueAccessorConfigs.length === 0) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) ||
outputTarget.valueAccessorConfigs.length === 0) {
return;

@@ -8,3 +9,5 @@ }

const normalizedValueAccessors = outputTarget.valueAccessorConfigs.reduce((allAccessors, va) => {
const elementSelectors = (Array.isArray(va.elementSelectors)) ? va.elementSelectors : [va.elementSelectors];
const elementSelectors = Array.isArray(va.elementSelectors)
? va.elementSelectors
: [va.elementSelectors];
const type = va.type;

@@ -19,23 +22,21 @@ let allElementSelectors = [];

elementSelectors: allElementSelectors.concat(elementSelectors),
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]])
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]]),
} });
}, {});
await copyResources(config, ['value-accessor.ts'], targetDir);
return Promise.all(Object.keys(normalizedValueAccessors).map((type) => {
await Promise.all(Object.keys(normalizedValueAccessors).map(async (type) => {
const valueAccessorType = type; // Object.keys converts to string
return writeValueAccessor(valueAccessorType, normalizedValueAccessors[valueAccessorType], compilerCtx, targetDir);
const targetFileName = `${type}-value-accessor.ts`;
const targetFilePath = path.join(targetDir, targetFileName);
const srcFilePath = path.join(__dirname, '../resources/control-value-accessors/', targetFileName);
const srcFileContents = await compilerCtx.fs.readFile(srcFilePath);
const finalText = createValueAccessor(srcFileContents, normalizedValueAccessors[valueAccessorType]);
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}));
await copyResources(config, ['value-accessor.ts'], targetDir);
}
async function writeValueAccessor(type, valueAccessor, compilerCtx, targetDir) {
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
function createValueAccessor(srcFileContents, valueAccessor) {
const hostContents = valueAccessor.eventTargets.map((listItem) => VALUE_ACCESSOR_EVENTTARGETS.replace(VALUE_ACCESSOR_EVENT, listItem[0]).replace(VALUE_ACCESSOR_TARGETATTR, listItem[1]));
return srcFileContents
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join('\n'));
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}

@@ -46,3 +47,3 @@ function copyResources(config, resourcesFilesToCopy, directory) {

}
const copyTasks = resourcesFilesToCopy.map(rf => {
const copyTasks = resourcesFilesToCopy.map((rf) => {
return {

@@ -52,3 +53,3 @@ src: path.join(__dirname, '../resources/control-value-accessors/', rf),

keepDirStructure: false,
warn: false
warn: false,
};

@@ -55,0 +56,0 @@ });

@@ -13,3 +13,6 @@ 'use strict';

const toLowerCase = (str) => str.toLowerCase();
const dashToPascalCase = (str) => toLowerCase(str).split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join('');
const dashToPascalCase = (str) => toLowerCase(str)
.split('-')
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
.join('');
function sortBy(array, prop) {

@@ -84,48 +87,11 @@ return array.slice().sort((a, b) => {

const SLASH_REGEX = /\\/g;
const GENERATED_DTS = 'components.d.ts';
async function generateProxies(compilerCtx, components, outputTarget, rootDir) {
const pkgData = await readPackageJson(rootDir);
const distTypesDir = path.dirname(pkgData.types);
const proxies = getProxies(components, outputTarget.componentCorePackage, distTypesDir);
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
const imports = `/* tslint:disable */
/* auto-generated angular directive proxies */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, NgZone } from '@angular/core';`;
const sourceImports = !outputTarget.componentCorePackage ?
`import { Components } from '${normalizePath(componentsTypeFile)}';` :
`import { Components } from '${normalizePath(outputTarget.componentCorePackage)}'`;
const final = [
imports,
getProxyUtils(outputTarget),
sourceImports,
proxies,
];
const finalText = final.join('\n') + '\n';
return compilerCtx.fs.writeFile(outputTarget.directivesProxyFile, finalText);
}
function getProxies(components, componentCorePackage, distTypesDir) {
return components
.map((cmpMeta) => getProxy(cmpMeta, componentCorePackage, distTypesDir))
.join('\n');
}
function getProxyCmp(inputs, methods) {
const hasInputs = inputs.length > 0;
const hasMethods = methods.length > 0;
const proxMeta = [];
if (!hasInputs && !hasMethods) {
return '';
}
if (hasInputs)
proxMeta.push(`inputs: ['${inputs.join(`', '`)}']`);
if (hasMethods)
proxMeta.push(`'methods': ['${methods.join(`', '`)}']`);
return `@ProxyCmp({${proxMeta.join(', ')}})`;
}
function getProxy(cmpMeta, componentCorePackage, distTypesDir) {
const createComponentDefinition = (componentCorePackage, distTypesDir, rootDir) => (cmpMeta) => {
// Collect component meta
const inputs = getInputs(cmpMeta);
const outputs = getOutputs(cmpMeta);
const methods = getMethods(cmpMeta);
const inputs = [
...cmpMeta.properties.filter((prop) => !prop.internal).map((prop) => prop.name),
...cmpMeta.virtualProperties.map((prop) => prop.name),
].sort();
const outputs = cmpMeta.events.filter((ev) => !ev.internal).map((prop) => prop);
const methods = cmpMeta.methods.filter((method) => !method.internal).map((prop) => prop.name);
// Process meta

@@ -137,3 +103,3 @@ const hasOutputs = outputs.length > 0;

`changeDetection: ChangeDetectionStrategy.OnPush`,
`template: '<ng-content></ng-content>'`
`template: '<ng-content></ng-content>'`,
];

@@ -144,17 +110,23 @@ if (inputs.length > 0) {

if (outputs.length > 0) {
directiveOpts.push(`outputs: ['${outputs.map(output => output.name).join(`', '`)}']`);
directiveOpts.push(`outputs: ['${outputs.map((output) => output.name).join(`', '`)}']`);
}
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
const typePath = path.relative(componentCorePackage, cmpMeta.sourceFilePath).replace('../src', path.join(componentCorePackage, distTypesDir)).replace('.tsx', '');
const typePath = path.parse(path.join(componentCorePackage, path.join(cmpMeta.sourceFilePath, '').replace(path.join(rootDir, 'src'), distTypesDir)));
const importPath = normalizePath(path.join(typePath.dir, typePath.name));
const outputsInterface = outputs.length > 0
? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${typePath}';`
? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${importPath}';`
: '';
const lines = [`${outputsInterface}
const lines = [
`
${outputsInterface}
export declare interface ${tagNameAsPascal} extends Components.${tagNameAsPascal} {}
${getProxyCmp(inputs, methods)}
@Component({ ${directiveOpts.join(', ')} })
export class ${tagNameAsPascal} {`];
// Generate outputs
outputs.forEach(output => {
lines.push(` /** ${output.docs.text} ${output.docs.tags.map(tag => `@${tag.name} ${tag.text}`)}*/`);
@Component({
${directiveOpts.join(',\n ')}
})
export class ${tagNameAsPascal} {`,
];
// Generate outputs
outputs.forEach((output) => {
lines.push(` /** ${output.docs.text} ${output.docs.tags.map((tag) => `@${tag.name} ${tag.text}`)}*/`);
lines.push(` ${output.name}!: I${cmpMeta.componentClassName}['${output.method}'];`);

@@ -167,3 +139,3 @@ });

if (hasOutputs) {
lines.push(` proxyOutputs(this, this.el, ['${outputs.map(output => output.name).join(`', '`)}']);`);
lines.push(` proxyOutputs(this, this.el, ['${outputs.map((output) => output.name).join(`', '`)}']);`);
}

@@ -173,66 +145,19 @@ lines.push(` }`);

return lines.join('\n');
}
function getInputs(cmpMeta) {
return [
...cmpMeta.properties.filter(prop => !prop.internal).map(prop => prop.name),
...cmpMeta.virtualProperties.map(prop => prop.name)
].sort();
}
function getOutputs(cmpMeta) {
return cmpMeta.events.filter(ev => !ev.internal).map(prop => prop);
}
function getMethods(cmpMeta) {
return cmpMeta.methods.filter(method => !method.internal).map(prop => prop.name);
}
function getProxyUtils(outputTarget) {
if (!outputTarget.directivesUtilsFile) {
return PROXY_UTILS;
}
else {
const utilsPath = relativeImport(outputTarget.directivesProxyFile, outputTarget.directivesUtilsFile, '.ts');
return `import { ProxyCmp, proxyOutputs } from '${normalizePath(utilsPath)}';\n`;
}
}
const PROXY_UTILS = `import { fromEvent } from 'rxjs';
export const proxyInputs = (Cmp: any, inputs: string[]) => {
const Prototype = Cmp.prototype;
inputs.forEach(item => {
Object.defineProperty(Prototype, item, {
get() { return this.el[item]; },
set(val: any) { this.z.runOutsideAngular(() => (this.el[item] = val)); }
});
});
};
export const proxyMethods = (Cmp: any, methods: string[]) => {
const Prototype = Cmp.prototype;
methods.forEach(methodName => {
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
};
});
};
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
}
// tslint:disable-next-line: only-arrow-functions
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
const decorator = function(cls: any){
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
function getProxyCmp(inputs, methods) {
const hasInputs = inputs.length > 0;
const hasMethods = methods.length > 0;
const proxMeta = [];
if (!hasInputs && !hasMethods) {
return '';
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
};
return decorator;
if (hasInputs)
proxMeta.push(`inputs: ['${inputs.join(`', '`)}']`);
if (hasMethods)
proxMeta.push(`methods: ['${methods.join(`', '`)}']`);
return `@ProxyCmp({\n ${proxMeta.join(',\n ')}\n})`;
}
`;
function generateAngularArray(compilerCtx, components, outputTarget) {
function generateAngularDirectivesFile(compilerCtx, components, outputTarget) {
// Only create the file if it is defined in the stencil configuration
if (!outputTarget.directivesArrayFile) {

@@ -243,4 +168,4 @@ return Promise.resolve();

const directives = components
.map(cmpMeta => dashToPascalCase(cmpMeta.tagName))
.map(className => `d.${className}`)
.map((cmpMeta) => dashToPascalCase(cmpMeta.tagName))
.map((className) => `d.${className}`)
.join(',\n ');

@@ -257,50 +182,5 @@ const c = `

async function generateAngularUtils(compilerCtx, outputTarget) {
if (outputTarget.directivesUtilsFile) {
await compilerCtx.fs.writeFile(outputTarget.directivesUtilsFile, '/* tslint:disable */\n' + PROXY_UTILS$1);
}
}
const PROXY_UTILS$1 = `import { fromEvent } from 'rxjs';
export const proxyInputs = (Cmp: any, inputs: string[]) => {
const Prototype = Cmp.prototype;
inputs.forEach(item => {
Object.defineProperty(Prototype, item, {
get() { return this.el[item]; },
set(val: any) { this.z.runOutsideAngular(() => (this.el[item] = val)); }
});
});
};
export const proxyMethods = (Cmp: any, methods: string[]) => {
const Prototype = Cmp.prototype;
methods.forEach(methodName => {
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
};
});
};
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
}
// tslint:disable-next-line: only-arrow-functions
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
const decorator = function(cls: any){
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
};
return decorator;
}
`;
async function generateValueAccessors(compilerCtx, components, outputTarget, config) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) || outputTarget.valueAccessorConfigs.length === 0) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) ||
outputTarget.valueAccessorConfigs.length === 0) {
return;

@@ -310,3 +190,5 @@ }

const normalizedValueAccessors = outputTarget.valueAccessorConfigs.reduce((allAccessors, va) => {
const elementSelectors = (Array.isArray(va.elementSelectors)) ? va.elementSelectors : [va.elementSelectors];
const elementSelectors = Array.isArray(va.elementSelectors)
? va.elementSelectors
: [va.elementSelectors];
const type = va.type;

@@ -321,23 +203,21 @@ let allElementSelectors = [];

elementSelectors: allElementSelectors.concat(elementSelectors),
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]])
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]]),
} });
}, {});
await copyResources(config, ['value-accessor.ts'], targetDir);
return Promise.all(Object.keys(normalizedValueAccessors).map((type) => {
await Promise.all(Object.keys(normalizedValueAccessors).map(async (type) => {
const valueAccessorType = type; // Object.keys converts to string
return writeValueAccessor(valueAccessorType, normalizedValueAccessors[valueAccessorType], compilerCtx, targetDir);
const targetFileName = `${type}-value-accessor.ts`;
const targetFilePath = path.join(targetDir, targetFileName);
const srcFilePath = path.join(__dirname, '../resources/control-value-accessors/', targetFileName);
const srcFileContents = await compilerCtx.fs.readFile(srcFilePath);
const finalText = createValueAccessor(srcFileContents, normalizedValueAccessors[valueAccessorType]);
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}));
await copyResources(config, ['value-accessor.ts'], targetDir);
}
async function writeValueAccessor(type, valueAccessor, compilerCtx, targetDir) {
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
function createValueAccessor(srcFileContents, valueAccessor) {
const hostContents = valueAccessor.eventTargets.map((listItem) => VALUE_ACCESSOR_EVENTTARGETS.replace(VALUE_ACCESSOR_EVENT, listItem[0]).replace(VALUE_ACCESSOR_TARGETATTR, listItem[1]));
return srcFileContents
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join('\n'));
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}

@@ -348,3 +228,3 @@ function copyResources(config, resourcesFilesToCopy, directory) {

}
const copyTasks = resourcesFilesToCopy.map(rf => {
const copyTasks = resourcesFilesToCopy.map((rf) => {
return {

@@ -354,3 +234,3 @@ src: path.join(__dirname, '../resources/control-value-accessors/', rf),

keepDirStructure: false,
warn: false
warn: false,
};

@@ -365,8 +245,11 @@ });

function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
async function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
const filteredComponents = getFilteredComponents(outputTarget.excludeComponents, components);
return Promise.all([
generateProxies(compilerCtx, filteredComponents, outputTarget, config.rootDir),
generateAngularArray(compilerCtx, filteredComponents, outputTarget),
generateAngularUtils(compilerCtx, outputTarget),
const rootDir = config.rootDir;
const pkgData = await readPackageJson(rootDir);
const finalText = generateProxies(filteredComponents, pkgData, outputTarget, config.rootDir);
await Promise.all([
compilerCtx.fs.writeFile(outputTarget.directivesProxyFile, finalText),
copyResources$1(config, outputTarget),
generateAngularDirectivesFile(compilerCtx, filteredComponents, outputTarget),
generateValueAccessors(compilerCtx, filteredComponents, outputTarget, config),

@@ -376,5 +259,41 @@ ]);

function getFilteredComponents(excludeComponents = [], cmps) {
return sortBy(cmps, cmp => cmp.tagName)
.filter(c => !excludeComponents.includes(c.tagName) && !c.internal);
return sortBy(cmps, (cmp) => cmp.tagName).filter((c) => !excludeComponents.includes(c.tagName) && !c.internal);
}
async function copyResources$1(config, outputTarget) {
if (!config.sys || !config.sys.copy || !config.sys.glob) {
throw new Error('stencil is not properly initialized at this step. Notify the developer');
}
const srcDirectory = path.join(__dirname, '..', 'angular-component-lib');
const destDirectory = path.join(path.dirname(outputTarget.directivesProxyFile), 'angular-component-lib');
return config.sys.copy([
{
src: srcDirectory,
dest: destDirectory,
keepDirStructure: false,
warn: false,
},
], srcDirectory);
}
function generateProxies(components, pkgData, outputTarget, rootDir) {
const distTypesDir = path.dirname(pkgData.types);
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
const imports = `/* tslint:disable */
/* auto-generated angular directive proxies */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';
import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils';\n`;
const typeImports = !outputTarget.componentCorePackage
? `import { ${IMPORT_TYPES} } from '${normalizePath(componentsTypeFile)}';`
: `import { ${IMPORT_TYPES} } from '${normalizePath(outputTarget.componentCorePackage)}';`;
const final = [
imports,
typeImports,
components
.map(createComponentDefinition(outputTarget.componentCorePackage, distTypesDir, rootDir))
.join('\n'),
];
return final.join('\n') + '\n';
}
const GENERATED_DTS = 'components.d.ts';
const IMPORT_TYPES = 'Components';

@@ -391,3 +310,3 @@ const angularOutputTarget = (outputTarget) => ({

timespan.finish(`generate angular proxies finished`);
}
},
});

@@ -394,0 +313,0 @@ function normalizeOutputTarget(config, outputTarget) {

@@ -7,3 +7,6 @@ import path from 'path';

const toLowerCase = (str) => str.toLowerCase();
const dashToPascalCase = (str) => toLowerCase(str).split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join('');
const dashToPascalCase = (str) => toLowerCase(str)
.split('-')
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
.join('');
function sortBy(array, prop) {

@@ -78,48 +81,11 @@ return array.slice().sort((a, b) => {

const SLASH_REGEX = /\\/g;
const GENERATED_DTS = 'components.d.ts';
async function generateProxies(compilerCtx, components, outputTarget, rootDir) {
const pkgData = await readPackageJson(rootDir);
const distTypesDir = path.dirname(pkgData.types);
const proxies = getProxies(components, outputTarget.componentCorePackage, distTypesDir);
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
const imports = `/* tslint:disable */
/* auto-generated angular directive proxies */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, NgZone } from '@angular/core';`;
const sourceImports = !outputTarget.componentCorePackage ?
`import { Components } from '${normalizePath(componentsTypeFile)}';` :
`import { Components } from '${normalizePath(outputTarget.componentCorePackage)}'`;
const final = [
imports,
getProxyUtils(outputTarget),
sourceImports,
proxies,
];
const finalText = final.join('\n') + '\n';
return compilerCtx.fs.writeFile(outputTarget.directivesProxyFile, finalText);
}
function getProxies(components, componentCorePackage, distTypesDir) {
return components
.map((cmpMeta) => getProxy(cmpMeta, componentCorePackage, distTypesDir))
.join('\n');
}
function getProxyCmp(inputs, methods) {
const hasInputs = inputs.length > 0;
const hasMethods = methods.length > 0;
const proxMeta = [];
if (!hasInputs && !hasMethods) {
return '';
}
if (hasInputs)
proxMeta.push(`inputs: ['${inputs.join(`', '`)}']`);
if (hasMethods)
proxMeta.push(`'methods': ['${methods.join(`', '`)}']`);
return `@ProxyCmp({${proxMeta.join(', ')}})`;
}
function getProxy(cmpMeta, componentCorePackage, distTypesDir) {
const createComponentDefinition = (componentCorePackage, distTypesDir, rootDir) => (cmpMeta) => {
// Collect component meta
const inputs = getInputs(cmpMeta);
const outputs = getOutputs(cmpMeta);
const methods = getMethods(cmpMeta);
const inputs = [
...cmpMeta.properties.filter((prop) => !prop.internal).map((prop) => prop.name),
...cmpMeta.virtualProperties.map((prop) => prop.name),
].sort();
const outputs = cmpMeta.events.filter((ev) => !ev.internal).map((prop) => prop);
const methods = cmpMeta.methods.filter((method) => !method.internal).map((prop) => prop.name);
// Process meta

@@ -131,3 +97,3 @@ const hasOutputs = outputs.length > 0;

`changeDetection: ChangeDetectionStrategy.OnPush`,
`template: '<ng-content></ng-content>'`
`template: '<ng-content></ng-content>'`,
];

@@ -138,17 +104,23 @@ if (inputs.length > 0) {

if (outputs.length > 0) {
directiveOpts.push(`outputs: ['${outputs.map(output => output.name).join(`', '`)}']`);
directiveOpts.push(`outputs: ['${outputs.map((output) => output.name).join(`', '`)}']`);
}
const tagNameAsPascal = dashToPascalCase(cmpMeta.tagName);
const typePath = path.relative(componentCorePackage, cmpMeta.sourceFilePath).replace('../src', path.join(componentCorePackage, distTypesDir)).replace('.tsx', '');
const typePath = path.parse(path.join(componentCorePackage, path.join(cmpMeta.sourceFilePath, '').replace(path.join(rootDir, 'src'), distTypesDir)));
const importPath = normalizePath(path.join(typePath.dir, typePath.name));
const outputsInterface = outputs.length > 0
? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${typePath}';`
? `import { ${cmpMeta.componentClassName} as I${cmpMeta.componentClassName} } from '${importPath}';`
: '';
const lines = [`${outputsInterface}
const lines = [
`
${outputsInterface}
export declare interface ${tagNameAsPascal} extends Components.${tagNameAsPascal} {}
${getProxyCmp(inputs, methods)}
@Component({ ${directiveOpts.join(', ')} })
export class ${tagNameAsPascal} {`];
// Generate outputs
outputs.forEach(output => {
lines.push(` /** ${output.docs.text} ${output.docs.tags.map(tag => `@${tag.name} ${tag.text}`)}*/`);
@Component({
${directiveOpts.join(',\n ')}
})
export class ${tagNameAsPascal} {`,
];
// Generate outputs
outputs.forEach((output) => {
lines.push(` /** ${output.docs.text} ${output.docs.tags.map((tag) => `@${tag.name} ${tag.text}`)}*/`);
lines.push(` ${output.name}!: I${cmpMeta.componentClassName}['${output.method}'];`);

@@ -161,3 +133,3 @@ });

if (hasOutputs) {
lines.push(` proxyOutputs(this, this.el, ['${outputs.map(output => output.name).join(`', '`)}']);`);
lines.push(` proxyOutputs(this, this.el, ['${outputs.map((output) => output.name).join(`', '`)}']);`);
}

@@ -167,66 +139,19 @@ lines.push(` }`);

return lines.join('\n');
}
function getInputs(cmpMeta) {
return [
...cmpMeta.properties.filter(prop => !prop.internal).map(prop => prop.name),
...cmpMeta.virtualProperties.map(prop => prop.name)
].sort();
}
function getOutputs(cmpMeta) {
return cmpMeta.events.filter(ev => !ev.internal).map(prop => prop);
}
function getMethods(cmpMeta) {
return cmpMeta.methods.filter(method => !method.internal).map(prop => prop.name);
}
function getProxyUtils(outputTarget) {
if (!outputTarget.directivesUtilsFile) {
return PROXY_UTILS;
}
else {
const utilsPath = relativeImport(outputTarget.directivesProxyFile, outputTarget.directivesUtilsFile, '.ts');
return `import { ProxyCmp, proxyOutputs } from '${normalizePath(utilsPath)}';\n`;
}
}
const PROXY_UTILS = `import { fromEvent } from 'rxjs';
export const proxyInputs = (Cmp: any, inputs: string[]) => {
const Prototype = Cmp.prototype;
inputs.forEach(item => {
Object.defineProperty(Prototype, item, {
get() { return this.el[item]; },
set(val: any) { this.z.runOutsideAngular(() => (this.el[item] = val)); }
});
});
};
export const proxyMethods = (Cmp: any, methods: string[]) => {
const Prototype = Cmp.prototype;
methods.forEach(methodName => {
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
};
});
};
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
}
// tslint:disable-next-line: only-arrow-functions
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
const decorator = function(cls: any){
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
function getProxyCmp(inputs, methods) {
const hasInputs = inputs.length > 0;
const hasMethods = methods.length > 0;
const proxMeta = [];
if (!hasInputs && !hasMethods) {
return '';
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
};
return decorator;
if (hasInputs)
proxMeta.push(`inputs: ['${inputs.join(`', '`)}']`);
if (hasMethods)
proxMeta.push(`methods: ['${methods.join(`', '`)}']`);
return `@ProxyCmp({\n ${proxMeta.join(',\n ')}\n})`;
}
`;
function generateAngularArray(compilerCtx, components, outputTarget) {
function generateAngularDirectivesFile(compilerCtx, components, outputTarget) {
// Only create the file if it is defined in the stencil configuration
if (!outputTarget.directivesArrayFile) {

@@ -237,4 +162,4 @@ return Promise.resolve();

const directives = components
.map(cmpMeta => dashToPascalCase(cmpMeta.tagName))
.map(className => `d.${className}`)
.map((cmpMeta) => dashToPascalCase(cmpMeta.tagName))
.map((className) => `d.${className}`)
.join(',\n ');

@@ -251,50 +176,5 @@ const c = `

async function generateAngularUtils(compilerCtx, outputTarget) {
if (outputTarget.directivesUtilsFile) {
await compilerCtx.fs.writeFile(outputTarget.directivesUtilsFile, '/* tslint:disable */\n' + PROXY_UTILS$1);
}
}
const PROXY_UTILS$1 = `import { fromEvent } from 'rxjs';
export const proxyInputs = (Cmp: any, inputs: string[]) => {
const Prototype = Cmp.prototype;
inputs.forEach(item => {
Object.defineProperty(Prototype, item, {
get() { return this.el[item]; },
set(val: any) { this.z.runOutsideAngular(() => (this.el[item] = val)); }
});
});
};
export const proxyMethods = (Cmp: any, methods: string[]) => {
const Prototype = Cmp.prototype;
methods.forEach(methodName => {
Prototype[methodName] = function () {
const args = arguments;
return this.z.runOutsideAngular(() => this.el[methodName].apply(this.el, args));
};
});
};
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
}
// tslint:disable-next-line: only-arrow-functions
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
const decorator = function(cls: any){
if (opts.inputs) {
proxyInputs(cls, opts.inputs);
}
if (opts.methods) {
proxyMethods(cls, opts.methods);
}
return cls;
};
return decorator;
}
`;
async function generateValueAccessors(compilerCtx, components, outputTarget, config) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) || outputTarget.valueAccessorConfigs.length === 0) {
if (!Array.isArray(outputTarget.valueAccessorConfigs) ||
outputTarget.valueAccessorConfigs.length === 0) {
return;

@@ -304,3 +184,5 @@ }

const normalizedValueAccessors = outputTarget.valueAccessorConfigs.reduce((allAccessors, va) => {
const elementSelectors = (Array.isArray(va.elementSelectors)) ? va.elementSelectors : [va.elementSelectors];
const elementSelectors = Array.isArray(va.elementSelectors)
? va.elementSelectors
: [va.elementSelectors];
const type = va.type;

@@ -315,23 +197,21 @@ let allElementSelectors = [];

elementSelectors: allElementSelectors.concat(elementSelectors),
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]])
eventTargets: allEventTargets.concat([[va.event, va.targetAttr]]),
} });
}, {});
await copyResources(config, ['value-accessor.ts'], targetDir);
return Promise.all(Object.keys(normalizedValueAccessors).map((type) => {
await Promise.all(Object.keys(normalizedValueAccessors).map(async (type) => {
const valueAccessorType = type; // Object.keys converts to string
return writeValueAccessor(valueAccessorType, normalizedValueAccessors[valueAccessorType], compilerCtx, targetDir);
const targetFileName = `${type}-value-accessor.ts`;
const targetFilePath = path.join(targetDir, targetFileName);
const srcFilePath = path.join(__dirname, '../resources/control-value-accessors/', targetFileName);
const srcFileContents = await compilerCtx.fs.readFile(srcFilePath);
const finalText = createValueAccessor(srcFileContents, normalizedValueAccessors[valueAccessorType]);
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}));
await copyResources(config, ['value-accessor.ts'], targetDir);
}
async function writeValueAccessor(type, valueAccessor, compilerCtx, targetDir) {
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
function createValueAccessor(srcFileContents, valueAccessor) {
const hostContents = valueAccessor.eventTargets.map((listItem) => VALUE_ACCESSOR_EVENTTARGETS.replace(VALUE_ACCESSOR_EVENT, listItem[0]).replace(VALUE_ACCESSOR_TARGETATTR, listItem[1]));
return srcFileContents
.replace(VALUE_ACCESSOR_SELECTORS, valueAccessor.elementSelectors.join(', '))
.replace(VALUE_ACCESSOR_EVENTTARGETS, hostContents.join('\n'));
await compilerCtx.fs.writeFile(targetFilePath, finalText);
}

@@ -342,3 +222,3 @@ function copyResources(config, resourcesFilesToCopy, directory) {

}
const copyTasks = resourcesFilesToCopy.map(rf => {
const copyTasks = resourcesFilesToCopy.map((rf) => {
return {

@@ -348,3 +228,3 @@ src: path.join(__dirname, '../resources/control-value-accessors/', rf),

keepDirStructure: false,
warn: false
warn: false,
};

@@ -359,8 +239,11 @@ });

function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
async function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
const filteredComponents = getFilteredComponents(outputTarget.excludeComponents, components);
return Promise.all([
generateProxies(compilerCtx, filteredComponents, outputTarget, config.rootDir),
generateAngularArray(compilerCtx, filteredComponents, outputTarget),
generateAngularUtils(compilerCtx, outputTarget),
const rootDir = config.rootDir;
const pkgData = await readPackageJson(rootDir);
const finalText = generateProxies(filteredComponents, pkgData, outputTarget, config.rootDir);
await Promise.all([
compilerCtx.fs.writeFile(outputTarget.directivesProxyFile, finalText),
copyResources$1(config, outputTarget),
generateAngularDirectivesFile(compilerCtx, filteredComponents, outputTarget),
generateValueAccessors(compilerCtx, filteredComponents, outputTarget, config),

@@ -370,5 +253,41 @@ ]);

function getFilteredComponents(excludeComponents = [], cmps) {
return sortBy(cmps, cmp => cmp.tagName)
.filter(c => !excludeComponents.includes(c.tagName) && !c.internal);
return sortBy(cmps, (cmp) => cmp.tagName).filter((c) => !excludeComponents.includes(c.tagName) && !c.internal);
}
async function copyResources$1(config, outputTarget) {
if (!config.sys || !config.sys.copy || !config.sys.glob) {
throw new Error('stencil is not properly initialized at this step. Notify the developer');
}
const srcDirectory = path.join(__dirname, '..', 'angular-component-lib');
const destDirectory = path.join(path.dirname(outputTarget.directivesProxyFile), 'angular-component-lib');
return config.sys.copy([
{
src: srcDirectory,
dest: destDirectory,
keepDirStructure: false,
warn: false,
},
], srcDirectory);
}
function generateProxies(components, pkgData, outputTarget, rootDir) {
const distTypesDir = path.dirname(pkgData.types);
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
const imports = `/* tslint:disable */
/* auto-generated angular directive proxies */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';
import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils';\n`;
const typeImports = !outputTarget.componentCorePackage
? `import { ${IMPORT_TYPES} } from '${normalizePath(componentsTypeFile)}';`
: `import { ${IMPORT_TYPES} } from '${normalizePath(outputTarget.componentCorePackage)}';`;
const final = [
imports,
typeImports,
components
.map(createComponentDefinition(outputTarget.componentCorePackage, distTypesDir, rootDir))
.join('\n'),
];
return final.join('\n') + '\n';
}
const GENERATED_DTS = 'components.d.ts';
const IMPORT_TYPES = 'Components';

@@ -385,3 +304,3 @@ const angularOutputTarget = (outputTarget) => ({

timespan.finish(`generate angular proxies finished`);
}
},
});

@@ -388,0 +307,0 @@ function normalizeOutputTarget(config, outputTarget) {

@@ -1,3 +0,4 @@

import { OutputTargetAngular } from './types';
import { CompilerCtx, ComponentCompilerMeta, Config } from '@stencil/core/internal';
export declare function angularDirectiveProxyOutput(compilerCtx: CompilerCtx, outputTarget: OutputTargetAngular, components: ComponentCompilerMeta[], config: Config): Promise<[import("@stencil/core/internal").FsWriteResults, any, void, void[] | undefined]>;
import { OutputTargetAngular, PackageJSON } from './types';
export declare function angularDirectiveProxyOutput(compilerCtx: CompilerCtx, outputTarget: OutputTargetAngular, components: ComponentCompilerMeta[], config: Config): Promise<void>;
export declare function generateProxies(components: ComponentCompilerMeta[], pkgData: PackageJSON, outputTarget: OutputTargetAngular, rootDir: string): string;

@@ -1,12 +0,15 @@

import { sortBy } from './utils';
import generateProxies from './generate-proxies';
import generateAngularArray from './generate-angular-array';
import generateAngularUtils from './generate-angular-utils';
import path from 'path';
import { relativeImport, normalizePath, sortBy, readPackageJson } from './utils';
import { createComponentDefinition } from './generate-angular-component';
import { generateAngularDirectivesFile } from './generate-angular-directives-file';
import generateValueAccessors from './generate-value-accessors';
export function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
export async function angularDirectiveProxyOutput(compilerCtx, outputTarget, components, config) {
const filteredComponents = getFilteredComponents(outputTarget.excludeComponents, components);
return Promise.all([
generateProxies(compilerCtx, filteredComponents, outputTarget, config.rootDir),
generateAngularArray(compilerCtx, filteredComponents, outputTarget),
generateAngularUtils(compilerCtx, outputTarget),
const rootDir = config.rootDir;
const pkgData = await readPackageJson(rootDir);
const finalText = generateProxies(filteredComponents, pkgData, outputTarget, config.rootDir);
await Promise.all([
compilerCtx.fs.writeFile(outputTarget.directivesProxyFile, finalText),
copyResources(config, outputTarget),
generateAngularDirectivesFile(compilerCtx, filteredComponents, outputTarget),
generateValueAccessors(compilerCtx, filteredComponents, outputTarget, config),

@@ -16,4 +19,40 @@ ]);

function getFilteredComponents(excludeComponents = [], cmps) {
return sortBy(cmps, cmp => cmp.tagName)
.filter(c => !excludeComponents.includes(c.tagName) && !c.internal);
return sortBy(cmps, (cmp) => cmp.tagName).filter((c) => !excludeComponents.includes(c.tagName) && !c.internal);
}
async function copyResources(config, outputTarget) {
if (!config.sys || !config.sys.copy || !config.sys.glob) {
throw new Error('stencil is not properly initialized at this step. Notify the developer');
}
const srcDirectory = path.join(__dirname, '..', 'angular-component-lib');
const destDirectory = path.join(path.dirname(outputTarget.directivesProxyFile), 'angular-component-lib');
return config.sys.copy([
{
src: srcDirectory,
dest: destDirectory,
keepDirStructure: false,
warn: false,
},
], srcDirectory);
}
export function generateProxies(components, pkgData, outputTarget, rootDir) {
const distTypesDir = path.dirname(pkgData.types);
const dtsFilePath = path.join(rootDir, distTypesDir, GENERATED_DTS);
const componentsTypeFile = relativeImport(outputTarget.directivesProxyFile, dtsFilePath, '.d.ts');
const imports = `/* tslint:disable */
/* auto-generated angular directive proxies */
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, NgZone } from '@angular/core';
import { ProxyCmp, proxyOutputs } from './angular-component-lib/utils';\n`;
const typeImports = !outputTarget.componentCorePackage
? `import { ${IMPORT_TYPES} } from '${normalizePath(componentsTypeFile)}';`
: `import { ${IMPORT_TYPES} } from '${normalizePath(outputTarget.componentCorePackage)}';`;
const final = [
imports,
typeImports,
components
.map(createComponentDefinition(outputTarget.componentCorePackage, distTypesDir, rootDir))
.join('\n'),
];
return final.join('\n') + '\n';
}
const GENERATED_DTS = 'components.d.ts';
const IMPORT_TYPES = 'Components';

@@ -1,3 +0,4 @@

import { OutputTargetCustom } from '@stencil/core/internal';
import { Config, OutputTargetCustom } from '@stencil/core/internal';
import { OutputTargetAngular } from './types';
export declare const angularOutputTarget: (outputTarget: OutputTargetAngular) => OutputTargetCustom;
export declare function normalizeOutputTarget(config: Config, outputTarget: any): OutputTargetAngular;

@@ -14,5 +14,5 @@ import { normalizePath } from './utils';

timespan.finish(`generate angular proxies finished`);
}
},
});
function normalizeOutputTarget(config, outputTarget) {
export function normalizeOutputTarget(config, outputTarget) {
const results = Object.assign(Object.assign({}, outputTarget), { excludeComponents: outputTarget.excludeComponents || [], valueAccessorConfig: outputTarget.valueAccessorConfig || [] });

@@ -19,0 +19,0 @@ if (config.rootDir == null) {

import { PackageJSON } from './types';
export declare const toLowerCase: (str: string) => string;
export declare const dashToPascalCase: (str: string) => string;
export declare function sortBy<T>(array: T[], prop: ((item: T) => string)): T[];
export declare function sortBy<T>(array: T[], prop: (item: T) => string): T[];
export declare function normalizePath(str: string): string;
export declare function relativeImport(pathFrom: string, pathTo: string, ext?: string): string;
export declare function readPackageJson(rootDir: string): Promise<PackageJSON>;
export declare const GENERATED_DTS = "components.d.ts";

@@ -6,3 +6,6 @@ import path from 'path';

export const toLowerCase = (str) => str.toLowerCase();
export const dashToPascalCase = (str) => toLowerCase(str).split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join('');
export const dashToPascalCase = (str) => toLowerCase(str)
.split('-')
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
.join('');
export function sortBy(array, prop) {

@@ -77,2 +80,1 @@ return array.slice().sort((a, b) => {

const SLASH_REGEX = /\\/g;
export const GENERATED_DTS = 'components.d.ts';
{
"name": "@stencil/angular-output-target",
"version": "0.0.3",
"version": "0.0.4",
"description": "This is an output plugin for stencil.",

@@ -22,3 +22,3 @@ "main": "dist/index.cjs.js",

"release": "np",
"test": "../../node_modules/.bin/jest --passWithNoTests",
"test": "jest --passWithNoTests",
"test.watch": "jest --watch"

@@ -39,2 +39,3 @@ },

"@angular/forms": "8.2.14",
"jest": "^26.1.0",
"np": "^4.0.2",

@@ -59,3 +60,3 @@ "rimraf": "^2.6.3",

},
"gitHead": "1a9082929749288da703753a03a4f87d70a106e5"
"gitHead": "e545765342b7f561ddd6826df05ee183163cbcb9"
}

@@ -34,2 +34,6 @@ import { ElementRef, HostListener } from '@angular/core';

}
setDisabledState(isDisabled: boolean) {
this.el.nativeElement.disabled = isDisabled;
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc