Skip to content

Commit 566e3bd

Browse files
yoontheyoonthe
andauthored
fix: issue SVG camel tag is not support #585, SVG setAttribute xmlns:xlink failed #584 (#586)
Co-authored-by: yoonthe <yuzaiyang.yoonthe@bytedance.com>
1 parent b4b5874 commit 566e3bd

File tree

4 files changed

+111
-3
lines changed

4 files changed

+111
-3
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { DOMApis } from '../src/domApis';
2+
3+
describe('Garfish shared domApis', () => {
4+
const domApis = new DOMApis(document);
5+
it('set Attribute SVG xmlns:xlink', () => {
6+
const svg = domApis.createElement({
7+
type: 'element',
8+
key: 'svg',
9+
tagName: 'svg',
10+
children: [],
11+
attributes: [
12+
{
13+
key: 'xmlns:xlink',
14+
value: 'http://www.w3.org/1999/xlink',
15+
},
16+
],
17+
});
18+
expect(svg.outerHTML).toBe('<svg xmlns:xlink="http://www.w3.org/1999/xlink"></svg>');
19+
});
20+
21+
it('set Attribute SVG xlink:href', () => {
22+
const use = domApis.createElement({
23+
type: 'element',
24+
key: 'use',
25+
tagName: 'use',
26+
children: [],
27+
attributes: [
28+
{
29+
key: 'xlink:href',
30+
value: '#image1_1060_8858',
31+
},
32+
],
33+
});
34+
expect(use.outerHTML).toBe('<use xlink:href="#image1_1060_8858"></use>');
35+
});
36+
37+
})
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { templateParse } from '../src/templateParse';
2+
3+
4+
function Attributes(this: any, { name, value }) {
5+
this.key = name;
6+
this.value = value;
7+
}
8+
9+
describe('Garfish shared templateParse', () => {
10+
it('parse SVG feFlood', () => {
11+
const [ast] = templateParse('<head></head><body><svg xmlns="http://www.w3.org/2000/svg"><feFlood flood-opacity="0"/></svg></body>', []);
12+
expect(ast).toEqual([{
13+
type: 'element',
14+
tagName: 'head',
15+
attributes: [],
16+
children: [],
17+
},{
18+
type: 'element',
19+
tagName: 'body',
20+
attributes: [],
21+
children: [{
22+
type: 'element',
23+
tagName: 'svg',
24+
attributes: [new Attributes({
25+
name: 'xmlns',
26+
value: 'http://www.w3.org/2000/svg',
27+
})],
28+
children: [
29+
{
30+
type: 'element',
31+
tagName: 'feFlood',
32+
attributes: [new Attributes({
33+
name: 'flood-opacity',
34+
value: '0',
35+
})],
36+
children: [],
37+
},
38+
],
39+
}],
40+
}])
41+
});
42+
43+
it('parse Uppercase DIV', () => {
44+
const [ast] = templateParse('<head></head><body><DIV id="div"/></body>', []);
45+
expect(ast).toEqual([{
46+
type: 'element',
47+
tagName: 'head',
48+
attributes: [],
49+
children: [],
50+
},{
51+
type: 'element',
52+
tagName: 'body',
53+
attributes: [],
54+
children: [{
55+
type: 'element',
56+
tagName: 'div',
57+
attributes: [new Attributes({
58+
name: 'id',
59+
value: 'div',
60+
})],
61+
children: [],
62+
}],
63+
}]);
64+
});
65+
});

packages/utils/src/domApis.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ const ns = 'http://www.w3.org/2000/svg';
2121
const xlinkNS = 'http://www.w3.org/1999/xlink'; // xmlns:xlink
2222
const xmlNS = 'http://www.w3.org/XML/1998/namespace'; // xmlns
2323

24+
const xlinkPrefix = 'xlink';
25+
2426
// https://developer.mozilla.org/en-US/docs/Web/SVG/Element
2527
const SVG_TAGS =
2628
'svg,animate,animateMotion,animateTransform,circle,clipPath,color-profile,' +
@@ -36,6 +38,10 @@ const SVG_TAGS =
3638

3739
const isSVG = makeMap(SVG_TAGS.split(','));
3840

41+
export function changeTagNameToLowerCase(tagName: string) {
42+
return isSVG(tagName) ? tagName : tagName.toLowerCase();
43+
}
44+
3945
function attributesString(attributes: Node['attributes']) {
4046
if (!attributes || attributes.length === 0) return '';
4147
return attributes.reduce((total, { key, value }) => {
@@ -184,7 +190,7 @@ export class DOMApis {
184190
el.setAttribute(key, value);
185191
} else if (key.charCodeAt(3) === colonChar) {
186192
el.setAttributeNS(xmlNS, key, value);
187-
} else if (key.charCodeAt(5) === colonChar) {
193+
} else if (key.charCodeAt(5) === colonChar && key.slice(0, 5) === xlinkPrefix) {
188194
el.setAttributeNS(xlinkNS, key, value);
189195
} else {
190196
el.setAttribute(key, value);

packages/utils/src/templateParse.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { error } from './utils';
2-
import { Node as VNode } from './domApis';
2+
import { changeTagNameToLowerCase, Node as VNode } from './domApis';
33

44
enum ElementType {
55
TEXT = 3,
@@ -48,7 +48,7 @@ const createElement = (el: Element, filter: (el: VNode) => VNode) => {
4848
case ElementType.ELEMENT:
4949
return filter({
5050
type: 'element',
51-
tagName: el.tagName.toLowerCase(),
51+
tagName: changeTagNameToLowerCase(el.tagName),
5252
attributes: generateAttributes(el),
5353
children: Array.from(el.childNodes).map((node) => {
5454
return createElement(node as Element, filter);

0 commit comments

Comments
 (0)