@aurelia/jit-html
Advanced tools
Comparing version 0.8.0-dev.202006241024 to 0.8.0-dev.202007041506
@@ -14,4 +14,4 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
import { IAttributeParser, ResourceModel, } from '@aurelia/jit'; | ||
import { mergeDistinct, PLATFORM, Registration, mergeArrays, } from '@aurelia/kernel'; | ||
import { HydrateAttributeInstruction, HydrateElementInstruction, HydrateTemplateController, IExpressionParser, InterpolationInstruction, ITemplateCompiler, LetBindingInstruction, LetElementInstruction, SetPropertyInstruction, CustomElementDefinition, IDOM } from '@aurelia/runtime'; | ||
import { mergeDistinct, PLATFORM, Registration, mergeArrays, toArray, ILogger, } from '@aurelia/kernel'; | ||
import { HydrateAttributeInstruction, HydrateElementInstruction, HydrateTemplateController, IExpressionParser, InterpolationInstruction, ITemplateCompiler, LetBindingInstruction, LetElementInstruction, SetPropertyInstruction, CustomElementDefinition, IDOM, BindingMode, Bindable, CustomElement, } from '@aurelia/runtime'; | ||
import { SetAttributeInstruction, TextBindingInstruction, SetClassAttributeInstruction, SetStyleAttributeInstruction, } from '@aurelia/runtime-html'; | ||
@@ -44,2 +44,14 @@ import { IAttrSyntaxTransformer } from './attribute-syntax-transformer'; | ||
} | ||
var LocalTemplateBindableAttributes; | ||
(function (LocalTemplateBindableAttributes) { | ||
LocalTemplateBindableAttributes["property"] = "property"; | ||
LocalTemplateBindableAttributes["attribute"] = "attribute"; | ||
LocalTemplateBindableAttributes["mode"] = "mode"; | ||
})(LocalTemplateBindableAttributes || (LocalTemplateBindableAttributes = {})); | ||
const allowedLocalTemplateBindableAttributes = Object.freeze([ | ||
"property" /* property */, | ||
"attribute" /* attribute */, | ||
"mode" /* mode */ | ||
]); | ||
const localTemplateIdentifier = 'as-custom-element'; | ||
/** | ||
@@ -51,3 +63,3 @@ * Default (runtime-agnostic) implementation for `ITemplateCompiler`. | ||
let TemplateCompiler = class TemplateCompiler { | ||
constructor(factory, attrParser, exprParser, attrSyntaxModifier) { | ||
constructor(factory, attrParser, exprParser, attrSyntaxModifier, logger) { | ||
this.factory = factory; | ||
@@ -57,2 +69,3 @@ this.attrParser = attrParser; | ||
this.attrSyntaxModifier = attrSyntaxModifier; | ||
this.logger = logger.scopeTo('TemplateCompiler'); | ||
} | ||
@@ -72,4 +85,6 @@ get name() { | ||
const { attrParser, exprParser, attrSyntaxModifier, factory } = this; | ||
const binder = new TemplateBinder(context.get(IDOM), resources, attrParser, exprParser, attrSyntaxModifier); | ||
const dom = context.get(IDOM); | ||
const binder = new TemplateBinder(dom, resources, attrParser, exprParser, attrSyntaxModifier); | ||
const template = factory.createTemplate(definition.template); | ||
processLocalTemplates(template, definition, context, dom, this.logger); | ||
const surrogate = binder.bind(template); | ||
@@ -308,5 +323,106 @@ const compilation = this.compilation = new CustomElementCompilationUnit(definition, surrogate, template); | ||
__param(3, IAttrSyntaxTransformer), | ||
__metadata("design:paramtypes", [Object, Object, Object, Object]) | ||
__param(4, ILogger), | ||
__metadata("design:paramtypes", [Object, Object, Object, Object, Object]) | ||
], TemplateCompiler); | ||
export { TemplateCompiler }; | ||
function getTemplateName(localTemplate, localTemplateNames) { | ||
const name = localTemplate.getAttribute(localTemplateIdentifier); | ||
if (name === null || name === '') { | ||
throw new Error('The value of "as-custom-element" attribute cannot be empty for local template'); | ||
} | ||
if (localTemplateNames.has(name)) { | ||
throw new Error(`Duplicate definition of the local template named ${name}`); | ||
} | ||
else { | ||
localTemplateNames.add(name); | ||
} | ||
return name; | ||
} | ||
function getBindingMode(bindable) { | ||
switch (bindable.getAttribute("mode" /* mode */)) { | ||
case 'oneTime': | ||
return BindingMode.oneTime; | ||
case 'toView': | ||
return BindingMode.toView; | ||
case 'fromView': | ||
return BindingMode.fromView; | ||
case 'twoWay': | ||
return BindingMode.twoWay; | ||
case 'default': | ||
default: | ||
return BindingMode.default; | ||
} | ||
} | ||
function processLocalTemplates(template, definition, context, dom, logger) { | ||
let root; | ||
if (template.nodeName === 'TEMPLATE') { | ||
if (template.hasAttribute(localTemplateIdentifier)) { | ||
throw new Error('The root cannot be a local template itself.'); | ||
} | ||
root = template.content; | ||
} | ||
else { | ||
root = template; | ||
} | ||
const localTemplates = toArray(root.querySelectorAll('template[as-custom-element]')); | ||
const numLocalTemplates = localTemplates.length; | ||
if (numLocalTemplates === 0) { | ||
return; | ||
} | ||
if (numLocalTemplates === root.childElementCount) { | ||
throw new Error('The custom element does not have any content other than local template(s).'); | ||
} | ||
const localTemplateNames = new Set(); | ||
for (const localTemplate of localTemplates) { | ||
if (localTemplate.parentNode !== root) { | ||
throw new Error('Local templates needs to be defined directly under root.'); | ||
} | ||
const name = getTemplateName(localTemplate, localTemplateNames); | ||
const localTemplateType = class LocalTemplate { | ||
}; | ||
const content = localTemplate.content; | ||
const bindableEls = toArray(content.querySelectorAll('bindable')); | ||
const bindableInstructions = Bindable.for(localTemplateType); | ||
const properties = new Set(); | ||
const attributes = new Set(); | ||
for (const bindableEl of bindableEls) { | ||
if (bindableEl.parentNode !== content) { | ||
throw new Error('Bindable properties of local templates needs to be defined directly under root.'); | ||
} | ||
const property = bindableEl.getAttribute("property" /* property */); | ||
if (property === null) { | ||
throw new Error(`The attribute 'property' is missing in ${bindableEl.outerHTML}`); | ||
} | ||
const attribute = bindableEl.getAttribute("attribute" /* attribute */); | ||
if (attribute !== null | ||
&& attributes.has(attribute) | ||
|| properties.has(property)) { | ||
throw new Error(`Bindable property and attribute needs to be unique; found property: ${property}, attribute: ${attribute}`); | ||
} | ||
else { | ||
if (attribute !== null) { | ||
attributes.add(attribute); | ||
} | ||
properties.add(property); | ||
} | ||
bindableInstructions.add({ | ||
property, | ||
attribute: attribute !== null && attribute !== void 0 ? attribute : void 0, | ||
mode: getBindingMode(bindableEl), | ||
}); | ||
const ignoredAttributes = bindableEl.getAttributeNames().filter((attrName) => !allowedLocalTemplateBindableAttributes.includes(attrName)); | ||
if (ignoredAttributes.length > 0) { | ||
logger.warn(`The attribute(s) ${ignoredAttributes.join(', ')} will be ignored for ${bindableEl.outerHTML}. Only ${allowedLocalTemplateBindableAttributes.join(', ')} are processed.`); | ||
} | ||
content.removeChild(bindableEl); | ||
} | ||
const div = dom.createElement('div'); | ||
div.appendChild(content); | ||
const localTemplateDefinition = CustomElement.define({ name, template: div.innerHTML }, localTemplateType); | ||
// the casting is needed here as the dependencies are typed as readonly array | ||
definition.dependencies.push(localTemplateDefinition); | ||
context.register(localTemplateDefinition); | ||
root.removeChild(localTemplate); | ||
} | ||
} | ||
//# sourceMappingURL=template-compiler.js.map |
@@ -54,2 +54,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
} | ||
var LocalTemplateBindableAttributes; | ||
(function (LocalTemplateBindableAttributes) { | ||
LocalTemplateBindableAttributes["property"] = "property"; | ||
LocalTemplateBindableAttributes["attribute"] = "attribute"; | ||
LocalTemplateBindableAttributes["mode"] = "mode"; | ||
})(LocalTemplateBindableAttributes || (LocalTemplateBindableAttributes = {})); | ||
const allowedLocalTemplateBindableAttributes = Object.freeze([ | ||
"property" /* property */, | ||
"attribute" /* attribute */, | ||
"mode" /* mode */ | ||
]); | ||
const localTemplateIdentifier = 'as-custom-element'; | ||
/** | ||
@@ -61,3 +73,3 @@ * Default (runtime-agnostic) implementation for `ITemplateCompiler`. | ||
let TemplateCompiler = class TemplateCompiler { | ||
constructor(factory, attrParser, exprParser, attrSyntaxModifier) { | ||
constructor(factory, attrParser, exprParser, attrSyntaxModifier, logger) { | ||
this.factory = factory; | ||
@@ -67,2 +79,3 @@ this.attrParser = attrParser; | ||
this.attrSyntaxModifier = attrSyntaxModifier; | ||
this.logger = logger.scopeTo('TemplateCompiler'); | ||
} | ||
@@ -82,4 +95,6 @@ get name() { | ||
const { attrParser, exprParser, attrSyntaxModifier, factory } = this; | ||
const binder = new template_binder_1.TemplateBinder(context.get(runtime_1.IDOM), resources, attrParser, exprParser, attrSyntaxModifier); | ||
const dom = context.get(runtime_1.IDOM); | ||
const binder = new template_binder_1.TemplateBinder(dom, resources, attrParser, exprParser, attrSyntaxModifier); | ||
const template = factory.createTemplate(definition.template); | ||
processLocalTemplates(template, definition, context, dom, this.logger); | ||
const surrogate = binder.bind(template); | ||
@@ -318,6 +333,107 @@ const compilation = this.compilation = new CustomElementCompilationUnit(definition, surrogate, template); | ||
__param(3, attribute_syntax_transformer_1.IAttrSyntaxTransformer), | ||
__metadata("design:paramtypes", [Object, Object, Object, Object]) | ||
__param(4, kernel_1.ILogger), | ||
__metadata("design:paramtypes", [Object, Object, Object, Object, Object]) | ||
], TemplateCompiler); | ||
exports.TemplateCompiler = TemplateCompiler; | ||
function getTemplateName(localTemplate, localTemplateNames) { | ||
const name = localTemplate.getAttribute(localTemplateIdentifier); | ||
if (name === null || name === '') { | ||
throw new Error('The value of "as-custom-element" attribute cannot be empty for local template'); | ||
} | ||
if (localTemplateNames.has(name)) { | ||
throw new Error(`Duplicate definition of the local template named ${name}`); | ||
} | ||
else { | ||
localTemplateNames.add(name); | ||
} | ||
return name; | ||
} | ||
function getBindingMode(bindable) { | ||
switch (bindable.getAttribute("mode" /* mode */)) { | ||
case 'oneTime': | ||
return runtime_1.BindingMode.oneTime; | ||
case 'toView': | ||
return runtime_1.BindingMode.toView; | ||
case 'fromView': | ||
return runtime_1.BindingMode.fromView; | ||
case 'twoWay': | ||
return runtime_1.BindingMode.twoWay; | ||
case 'default': | ||
default: | ||
return runtime_1.BindingMode.default; | ||
} | ||
} | ||
function processLocalTemplates(template, definition, context, dom, logger) { | ||
let root; | ||
if (template.nodeName === 'TEMPLATE') { | ||
if (template.hasAttribute(localTemplateIdentifier)) { | ||
throw new Error('The root cannot be a local template itself.'); | ||
} | ||
root = template.content; | ||
} | ||
else { | ||
root = template; | ||
} | ||
const localTemplates = kernel_1.toArray(root.querySelectorAll('template[as-custom-element]')); | ||
const numLocalTemplates = localTemplates.length; | ||
if (numLocalTemplates === 0) { | ||
return; | ||
} | ||
if (numLocalTemplates === root.childElementCount) { | ||
throw new Error('The custom element does not have any content other than local template(s).'); | ||
} | ||
const localTemplateNames = new Set(); | ||
for (const localTemplate of localTemplates) { | ||
if (localTemplate.parentNode !== root) { | ||
throw new Error('Local templates needs to be defined directly under root.'); | ||
} | ||
const name = getTemplateName(localTemplate, localTemplateNames); | ||
const localTemplateType = class LocalTemplate { | ||
}; | ||
const content = localTemplate.content; | ||
const bindableEls = kernel_1.toArray(content.querySelectorAll('bindable')); | ||
const bindableInstructions = runtime_1.Bindable.for(localTemplateType); | ||
const properties = new Set(); | ||
const attributes = new Set(); | ||
for (const bindableEl of bindableEls) { | ||
if (bindableEl.parentNode !== content) { | ||
throw new Error('Bindable properties of local templates needs to be defined directly under root.'); | ||
} | ||
const property = bindableEl.getAttribute("property" /* property */); | ||
if (property === null) { | ||
throw new Error(`The attribute 'property' is missing in ${bindableEl.outerHTML}`); | ||
} | ||
const attribute = bindableEl.getAttribute("attribute" /* attribute */); | ||
if (attribute !== null | ||
&& attributes.has(attribute) | ||
|| properties.has(property)) { | ||
throw new Error(`Bindable property and attribute needs to be unique; found property: ${property}, attribute: ${attribute}`); | ||
} | ||
else { | ||
if (attribute !== null) { | ||
attributes.add(attribute); | ||
} | ||
properties.add(property); | ||
} | ||
bindableInstructions.add({ | ||
property, | ||
attribute: attribute !== null && attribute !== void 0 ? attribute : void 0, | ||
mode: getBindingMode(bindableEl), | ||
}); | ||
const ignoredAttributes = bindableEl.getAttributeNames().filter((attrName) => !allowedLocalTemplateBindableAttributes.includes(attrName)); | ||
if (ignoredAttributes.length > 0) { | ||
logger.warn(`The attribute(s) ${ignoredAttributes.join(', ')} will be ignored for ${bindableEl.outerHTML}. Only ${allowedLocalTemplateBindableAttributes.join(', ')} are processed.`); | ||
} | ||
content.removeChild(bindableEl); | ||
} | ||
const div = dom.createElement('div'); | ||
div.appendChild(content); | ||
const localTemplateDefinition = runtime_1.CustomElement.define({ name, template: div.innerHTML }, localTemplateType); | ||
// the casting is needed here as the dependencies are typed as readonly array | ||
definition.dependencies.push(localTemplateDefinition); | ||
context.register(localTemplateDefinition); | ||
root.removeChild(localTemplate); | ||
} | ||
} | ||
}); | ||
//# sourceMappingURL=template-compiler.js.map |
{ | ||
"name": "@aurelia/jit-html", | ||
"version": "0.8.0-dev.202006241024", | ||
"version": "0.8.0-dev.202007041506", | ||
"main": "dist/umd/index.js", | ||
@@ -31,3 +31,3 @@ "module": "dist/esnext/index.js", | ||
"build": "tsc -b", | ||
"dev": "tsc -b -w" | ||
"dev": "tsc -b -w --preserveWatchOutput" | ||
}, | ||
@@ -38,8 +38,8 @@ "publishConfig": { | ||
"dependencies": { | ||
"@aurelia/jit": "^0.8.0-dev.202006241024", | ||
"@aurelia/kernel": "^0.8.0-dev.202006241024", | ||
"@aurelia/metadata": "^0.8.0-dev.202006241024", | ||
"@aurelia/runtime": "^0.8.0-dev.202006241024", | ||
"@aurelia/runtime-html": "^0.8.0-dev.202006241024", | ||
"@aurelia/scheduler": "^0.8.0-dev.202006241024" | ||
"@aurelia/jit": "^0.8.0-dev.202007041506", | ||
"@aurelia/kernel": "^0.8.0-dev.202007041506", | ||
"@aurelia/metadata": "^0.8.0-dev.202007041506", | ||
"@aurelia/runtime": "^0.8.0-dev.202007041506", | ||
"@aurelia/runtime-html": "^0.8.0-dev.202007041506", | ||
"@aurelia/scheduler": "^0.8.0-dev.202007041506" | ||
}, | ||
@@ -49,3 +49,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "015df8b213e4bdf3c8a71c357a49b6351e0c8422" | ||
"gitHead": "3f15eb801bac897d8c34890e1559be7b9e5b86a6" | ||
} |
@@ -13,2 +13,5 @@ import { | ||
mergeArrays, | ||
toArray, | ||
Key, | ||
ILogger, | ||
} from '@aurelia/kernel'; | ||
@@ -31,3 +34,6 @@ import { | ||
CustomElementDefinition, | ||
IDOM | ||
IDOM, | ||
BindingMode, | ||
Bindable, | ||
CustomElement, | ||
} from '@aurelia/runtime'; | ||
@@ -70,3 +76,3 @@ import { | ||
public readonly template: unknown, | ||
) {} | ||
) { } | ||
@@ -88,2 +94,13 @@ public toDefinition(): CustomElementDefinition { | ||
const enum LocalTemplateBindableAttributes { | ||
property = "property", | ||
attribute = "attribute", | ||
mode = "mode", | ||
} | ||
const allowedLocalTemplateBindableAttributes: readonly string[] = Object.freeze([ | ||
LocalTemplateBindableAttributes.property, | ||
LocalTemplateBindableAttributes.attribute, | ||
LocalTemplateBindableAttributes.mode | ||
]); | ||
const localTemplateIdentifier = 'as-custom-element'; | ||
/** | ||
@@ -97,2 +114,3 @@ * Default (runtime-agnostic) implementation for `ITemplateCompiler`. | ||
private compilation!: CustomElementCompilationUnit; | ||
private readonly logger: ILogger; | ||
@@ -107,4 +125,7 @@ public get name(): string { | ||
@IExpressionParser private readonly exprParser: IExpressionParser, | ||
@IAttrSyntaxTransformer private readonly attrSyntaxModifier: IAttrSyntaxTransformer | ||
) {} | ||
@IAttrSyntaxTransformer private readonly attrSyntaxModifier: IAttrSyntaxTransformer, | ||
@ILogger logger: ILogger, | ||
) { | ||
this.logger = logger.scopeTo('TemplateCompiler'); | ||
} | ||
@@ -124,5 +145,7 @@ public static register(container: IContainer): IResolver<ITemplateCompiler> { | ||
const binder = new TemplateBinder(context.get(IDOM), resources, attrParser, exprParser, attrSyntaxModifier); | ||
const dom = context.get(IDOM); | ||
const binder = new TemplateBinder(dom, resources, attrParser, exprParser, attrSyntaxModifier); | ||
const template = factory.createTemplate(definition.template) as HTMLTemplateElement; | ||
processLocalTemplates(template, definition, context, dom, this.logger); | ||
const surrogate = binder.bind(template); | ||
@@ -419,1 +442,109 @@ | ||
} | ||
function getTemplateName(localTemplate: HTMLTemplateElement, localTemplateNames: Set<string>): string { | ||
const name = localTemplate.getAttribute(localTemplateIdentifier); | ||
if (name === null || name === '') { | ||
throw new Error('The value of "as-custom-element" attribute cannot be empty for local template'); | ||
} | ||
if (localTemplateNames.has(name)) { | ||
throw new Error(`Duplicate definition of the local template named ${name}`); | ||
} else { | ||
localTemplateNames.add(name); | ||
} | ||
return name; | ||
} | ||
function getBindingMode(bindable: Element): BindingMode { | ||
switch (bindable.getAttribute(LocalTemplateBindableAttributes.mode)) { | ||
case 'oneTime': | ||
return BindingMode.oneTime; | ||
case 'toView': | ||
return BindingMode.toView; | ||
case 'fromView': | ||
return BindingMode.fromView; | ||
case 'twoWay': | ||
return BindingMode.twoWay; | ||
case 'default': | ||
default: | ||
return BindingMode.default; | ||
} | ||
} | ||
function processLocalTemplates( | ||
template: HTMLElement, | ||
definition: CustomElementDefinition, | ||
context: IContainer, | ||
dom: IDOM, | ||
logger: ILogger, | ||
) { | ||
let root: HTMLElement | DocumentFragment; | ||
if (template.nodeName === 'TEMPLATE') { | ||
if (template.hasAttribute(localTemplateIdentifier)) { | ||
throw new Error('The root cannot be a local template itself.'); | ||
} | ||
root = (template as HTMLTemplateElement).content; | ||
} else { | ||
root = template; | ||
} | ||
const localTemplates = toArray(root.querySelectorAll('template[as-custom-element]')) as HTMLTemplateElement[]; | ||
const numLocalTemplates = localTemplates.length; | ||
if (numLocalTemplates === 0) { return; } | ||
if (numLocalTemplates === root.childElementCount) { | ||
throw new Error('The custom element does not have any content other than local template(s).'); | ||
} | ||
const localTemplateNames: Set<string> = new Set(); | ||
for (const localTemplate of localTemplates) { | ||
if (localTemplate.parentNode !== root) { | ||
throw new Error('Local templates needs to be defined directly under root.'); | ||
} | ||
const name = getTemplateName(localTemplate, localTemplateNames); | ||
const localTemplateType = class LocalTemplate { }; | ||
const content = localTemplate.content; | ||
const bindableEls = toArray(content.querySelectorAll('bindable')); | ||
const bindableInstructions = Bindable.for(localTemplateType); | ||
const properties = new Set<string>(); | ||
const attributes = new Set<string>(); | ||
for (const bindableEl of bindableEls) { | ||
if (bindableEl.parentNode !== content) { | ||
throw new Error('Bindable properties of local templates needs to be defined directly under root.'); | ||
} | ||
const property = bindableEl.getAttribute(LocalTemplateBindableAttributes.property); | ||
if (property === null) { throw new Error(`The attribute 'property' is missing in ${bindableEl.outerHTML}`); } | ||
const attribute = bindableEl.getAttribute(LocalTemplateBindableAttributes.attribute); | ||
if (attribute !== null | ||
&& attributes.has(attribute) | ||
|| properties.has(property) | ||
) { | ||
throw new Error(`Bindable property and attribute needs to be unique; found property: ${property}, attribute: ${attribute}`); | ||
} else { | ||
if (attribute !== null) { | ||
attributes.add(attribute); | ||
} | ||
properties.add(property); | ||
} | ||
bindableInstructions.add({ | ||
property, | ||
attribute: attribute ?? void 0, | ||
mode: getBindingMode(bindableEl), | ||
}); | ||
const ignoredAttributes = bindableEl.getAttributeNames().filter((attrName) => !allowedLocalTemplateBindableAttributes.includes(attrName)); | ||
if (ignoredAttributes.length > 0) { | ||
logger.warn(`The attribute(s) ${ignoredAttributes.join(', ')} will be ignored for ${bindableEl.outerHTML}. Only ${allowedLocalTemplateBindableAttributes.join(', ')} are processed.`); | ||
} | ||
content.removeChild(bindableEl); | ||
} | ||
const div = dom.createElement('div') as HTMLDivElement; | ||
div.appendChild(content); | ||
const localTemplateDefinition = CustomElement.define({ name, template: div.innerHTML }, localTemplateType); | ||
// the casting is needed here as the dependencies are typed as readonly array | ||
(definition.dependencies as Key[]).push(localTemplateDefinition); | ||
context.register(localTemplateDefinition); | ||
root.removeChild(localTemplate); | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
349021
5058