feat(ivy): now supports SVG and MathML elements (#24377)
- Adds support for ivy creating SVG and MathML elements properly using createElementNS PR Close #24377
This commit is contained in:
@ -21,6 +21,105 @@ describe('compiler compliance', () => {
|
||||
});
|
||||
|
||||
describe('elements', () => {
|
||||
it('should handle SVG', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<div class="my-app" title="Hello"><svg><circle cx="20" cy="30" r="50"/></svg><p>test</p></div>\`
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
// The factory should look like this:
|
||||
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ['class', 'my-app', 'title', 'Hello'];
|
||||
const $c2$ = ['cx', '20', 'cy', '30', 'r', '50'];
|
||||
…
|
||||
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div', $c1$);
|
||||
$r3$.ɵNS();
|
||||
$r3$.ɵE(1, 'svg');
|
||||
$r3$.ɵE(2, 'circle', $c2$);
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵNH();
|
||||
$r3$.ɵE(3, 'p');
|
||||
$r3$.ɵT(4, 'test');
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
|
||||
expectEmit(result.source, factory, 'Incorrect factory');
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should handle MathML', () => {
|
||||
const files = {
|
||||
app: {
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<div class="my-app" title="Hello"><math><infinity/></math><p>test</p></div>\`
|
||||
})
|
||||
export class MyComponent {}
|
||||
|
||||
@NgModule({declarations: [MyComponent]})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
// The factory should look like this:
|
||||
const factory = 'factory: function MyComponent_Factory() { return new MyComponent(); }';
|
||||
|
||||
// The template should look like this (where IDENT is a wild card for an identifier):
|
||||
const template = `
|
||||
const $c1$ = ['class', 'my-app', 'title', 'Hello'];
|
||||
…
|
||||
template: function MyComponent_Template(rf: IDENT, ctx: IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵE(0, 'div', $c1$);
|
||||
$r3$.ɵNM();
|
||||
$r3$.ɵE(1, 'math');
|
||||
$r3$.ɵE(2, 'infinity');
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵNH();
|
||||
$r3$.ɵE(3, 'p');
|
||||
$r3$.ɵT(4, 'test');
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
|
||||
expectEmit(result.source, factory, 'Incorrect factory');
|
||||
expectEmit(result.source, template, 'Incorrect template');
|
||||
});
|
||||
|
||||
it('should translate DOM structure', () => {
|
||||
const files = {
|
||||
app: {
|
||||
@ -1164,6 +1263,80 @@ describe('compiler compliance', () => {
|
||||
}
|
||||
};
|
||||
|
||||
it('should support embedded views in the SVG namespace', () => {
|
||||
const files = {
|
||||
app: {
|
||||
...shared,
|
||||
'spec.ts': `
|
||||
import {Component, NgModule} from '@angular/core';
|
||||
import {ForOfDirective} from './shared/for_of';
|
||||
|
||||
@Component({
|
||||
selector: 'my-component',
|
||||
template: \`<svg><g *for="let item of items"><circle></circle></g></svg>\`
|
||||
})
|
||||
export class MyComponent {
|
||||
items = [{ data: 42 }, { data: 42 }];
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [MyComponent, ForOfDirective]
|
||||
})
|
||||
export class MyModule {}
|
||||
`
|
||||
}
|
||||
};
|
||||
|
||||
// TODO(benlesh): Enforce this when the directives are specified
|
||||
const ForDirectiveDefinition = `
|
||||
static ngDirectiveDef = $r3$.ɵdefineDirective({
|
||||
type: ForOfDirective,
|
||||
selectors: [['', 'forOf', '']],
|
||||
factory: function ForOfDirective_Factory() {
|
||||
return new ForOfDirective($r3$.ɵinjectViewContainerRef(), $r3$.ɵinjectTemplateRef());
|
||||
},
|
||||
features: [$r3$.ɵNgOnChangesFeature(NgForOf)],
|
||||
inputs: {forOf: 'forOf'}
|
||||
});
|
||||
`;
|
||||
|
||||
const MyComponentDefinition = `
|
||||
const $_c0$ = ['for','','forOf',''];
|
||||
…
|
||||
static ngComponentDef = $r3$.ɵdefineComponent({
|
||||
type: MyComponent,
|
||||
selectors: [['my-component']],
|
||||
factory: function MyComponent_Factory() { return new MyComponent(); },
|
||||
template: function MyComponent_Template(rf:IDENT,ctx:IDENT){
|
||||
if (rf & 1) {
|
||||
$r3$.ɵNS();
|
||||
$r3$.ɵE(0,'svg');
|
||||
$r3$.ɵC(1,MyComponent__svg_g_Template_1,null,$_c0$);
|
||||
$r3$.ɵe();
|
||||
}
|
||||
if (rf & 2) { $r3$.ɵp(1,'forOf',$r3$.ɵb(ctx.items)); }
|
||||
function MyComponent__svg_g_Template_1(rf:IDENT,ctx0:IDENT) {
|
||||
if (rf & 1) {
|
||||
$r3$.ɵNS();
|
||||
$r3$.ɵE(0,'g');
|
||||
$r3$.ɵE(1,'circle');
|
||||
$r3$.ɵe();
|
||||
$r3$.ɵe();
|
||||
}
|
||||
}
|
||||
},
|
||||
directives: [ForOfDirective]
|
||||
});
|
||||
`;
|
||||
|
||||
const result = compile(files, angularFiles);
|
||||
const source = result.source;
|
||||
|
||||
// TODO(benlesh): Enforce this when the directives are specified
|
||||
// expectEmit(source, ForDirectiveDefinition, 'Invalid directive definition');
|
||||
expectEmit(source, MyComponentDefinition, 'Invalid component definition');
|
||||
});
|
||||
|
||||
it('should support a let variable and reference', () => {
|
||||
const files = {
|
||||
app: {
|
||||
|
Reference in New Issue
Block a user