optimize class name runtime calc & add tests & ref

pull/3320/head
bre30kra69cs 5 years ago
parent 9b5bbb556d
commit ccf2ad819a

@ -5,6 +5,7 @@ import ElementWrapper from './index';
import { stringify } from '../../../utils/stringify';
import deindent from '../../../utils/deindent';
import Expression from '../../../nodes/shared/Expression';
import Text from '../../../nodes/Text';
export default class AttributeWrapper {
node: Attribute;
@ -84,26 +85,13 @@ export default class AttributeWrapper {
value = (this.node.chunks[0] as Expression).render(block);
} else {
// '{foo} {bar}' — treat as string concatenation
value =
(this.node.chunks[0].type === 'Text' ? '' : `"" + `) +
this.node.chunks
.map((chunk) => {
if (chunk.type === 'Text') {
return stringify(chunk.data);
} else {
const renderedChunk = chunk.render();
if (this.node.name === 'class') {
return chunk.get_precedence() <= 13
? `(${renderedChunk})`
: `(${renderedChunk} || '')`;
} else {
return chunk.get_precedence() <= 13
? `(${renderedChunk})`
: renderedChunk;
}
}
})
.join(' + ');
const attrPrefix = this.node.chunks[0].type === 'Text' ? '' : `"" + `;
const attrText = this.node.name === 'class'
? this.get_class_name_text()
: this.get_attr_text();
value = `${attrPrefix}${attrText}`;
}
const is_select_value_attribute =
@ -217,6 +205,41 @@ export default class AttributeWrapper {
}
}
get_class_name_text() {
const isStyled = this.node.chunks
.filter((chunk) => chunk.type === 'Text')
.some((chunk: Text) => !chunk.start && !chunk.end);
const classNameStringArray = this.render_attr();
if (!isStyled || classNameStringArray.length !== 2) {
return classNameStringArray.join(' + ');
}
const targetToken = 0;
return classNameStringArray
.map((token, index) => index === targetToken ? `@class_name_resolver(${token})` : token)
.join(' + ');
}
get_attr_text() {
return this.render_attr().join(' + ');
}
render_attr() {
return this.node.chunks.map((chunk) => {
if (chunk.type === 'Text') {
return stringify(chunk.data);
}
const renderedChunk = chunk.render();
return chunk.get_precedence() <= 13
? `(${renderedChunk})`
: renderedChunk;
});
}
stringify() {
if (this.node.is_true) return '';

@ -89,3 +89,7 @@ export function once(fn) {
fn.call(this, ...args);
};
}
export function class_name_resolver(nextClassName) {
return nextClassName == undefined ? '' : nextClassName;
}

@ -0,0 +1,5 @@
export default {
skip_if_ssr: true,
html: `<div class="false"></div>`,
};

@ -0,0 +1,44 @@
export default {
skip_if_ssr: true,
props: {
testName: "testClassName"
},
html: `<div class="testClassName"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'testClassName');
component.testName = null;
assert.equal(div.className, '');
component.testName = undefined;
assert.equal(div.className, '');
component.testName = undefined + '';
assert.equal(div.className, 'undefined');
component.testName = null + '';
assert.equal(div.className, 'null');
component.testName = 1;
assert.equal(div.className, '1');
component.testName = 0;
assert.equal(div.className, '0');
component.testName = false;
assert.equal(div.className, 'false');
component.testName = true;
assert.equal(div.className, 'true');
component.testName = {};
assert.equal(div.className, '[object Object]');
component.testName = '';
assert.equal(div.className, '');
}
};

@ -0,0 +1,5 @@
<script>
export let testName;
</script>
<div class={testName}></div>

@ -26,6 +26,18 @@ export default {
component.testName = 1;
assert.equal(div.className, '1 svelte-x1o6ra');
component.testName = 0;
assert.equal(div.className, '0 svelte-x1o6ra');
component.testName = false;
assert.equal(div.className, 'false svelte-x1o6ra');
component.testName = true;
assert.equal(div.className, 'true svelte-x1o6ra');
component.testName = {};
assert.equal(div.className, '[object Object] svelte-x1o6ra');
component.testName = '';
assert.equal(div.className, ' svelte-x1o6ra');
}

@ -0,0 +1,47 @@
export default {
skip_if_ssr: true,
props: {
testName1: "test1",
testName2: "test2",
},
html: `<div class="test1test2"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'test1test2');
component.testName1 = null;
component.testName2 = null;
assert.equal(div.className, '0');
component.testName1 = null;
component.testName2 = "test";
assert.equal(div.className, 'nulltest');
component.testName1 = undefined;
component.testName2 = "test";
assert.equal(div.className, 'undefinedtest');
component.testName1 = undefined;
component.testName2 = undefined;
assert.equal(div.className, 'NaN');
component.testName1 = null;
component.testName2 = 1;
assert.equal(div.className, '1');
component.testName1 = undefined;
component.testName2 = 1;
assert.equal(div.className, 'NaN');
component.testName1 = null;
component.testName2 = 0;
assert.equal(div.className, '0');
component.testName1 = undefined;
component.testName2 = 0;
assert.equal(div.className, 'NaN');
}
};

@ -0,0 +1,6 @@
<script>
export let testName1;
export let testName2;
</script>
<div class={testName1 + testName2}></div>

@ -35,5 +35,13 @@ export default {
component.testName1 = undefined;
component.testName2 = 1;
assert.equal(div.className, 'NaN svelte-x1o6ra');
component.testName1 = null;
component.testName2 = 0;
assert.equal(div.className, '0 svelte-x1o6ra');
component.testName1 = undefined;
component.testName2 = 0;
assert.equal(div.className, 'NaN svelte-x1o6ra');
}
};

@ -0,0 +1,44 @@
export default {
skip_if_ssr: true,
props: {
testName: "testClassName"
},
html: `<div class="testClassName"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'testClassName');
component.testName = null;
assert.equal(div.className, '');
component.testName = undefined;
assert.equal(div.className, '');
component.testName = undefined + '';
assert.equal(div.className, 'undefined');
component.testName = null + '';
assert.equal(div.className, 'null');
component.testName = 1;
assert.equal(div.className, '1');
component.testName = 0;
assert.equal(div.className, '0');
component.testName = false;
assert.equal(div.className, 'false');
component.testName = true;
assert.equal(div.className, 'true');
component.testName = {};
assert.equal(div.className, '[object Object]');
component.testName = '';
assert.equal(div.className, '');
}
};

@ -0,0 +1,9 @@
<script>
export let testName;
function myHelper(testName) {
return testName;
}
</script>
<div class={myHelper(testName)}></div>

@ -0,0 +1,44 @@
export default {
skip_if_ssr: true,
props: {
testName: "testClassName"
},
html: `<div class="testClassName svelte-x1o6ra"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'testClassName svelte-x1o6ra');
component.testName = null;
assert.equal(div.className, ' svelte-x1o6ra');
component.testName = undefined;
assert.equal(div.className, ' svelte-x1o6ra');
component.testName = undefined + '';
assert.equal(div.className, 'undefined svelte-x1o6ra');
component.testName = null + '';
assert.equal(div.className, 'null svelte-x1o6ra');
component.testName = 1;
assert.equal(div.className, '1 svelte-x1o6ra');
component.testName = 0;
assert.equal(div.className, '0 svelte-x1o6ra');
component.testName = false;
assert.equal(div.className, 'false svelte-x1o6ra');
component.testName = true;
assert.equal(div.className, 'true svelte-x1o6ra');
component.testName = {};
assert.equal(div.className, '[object Object] svelte-x1o6ra');
component.testName = '';
assert.equal(div.className, ' svelte-x1o6ra');
}
};

@ -0,0 +1,15 @@
<script>
export let testName;
function myHelper(testName) {
return testName;
}
</script>
<style>
div {
color: purple;
}
</style>
<div class={myHelper(testName)}></div>

@ -0,0 +1,47 @@
export default {
skip_if_ssr: true,
props: {
testName1: "test1",
testName2: "test2",
},
html: `<div class="test1test2"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'test1test2');
component.testName1 = null;
component.testName2 = null;
assert.equal(div.className, '0');
component.testName1 = null;
component.testName2 = "test";
assert.equal(div.className, 'nulltest');
component.testName1 = undefined;
component.testName2 = "test";
assert.equal(div.className, 'undefinedtest');
component.testName1 = undefined;
component.testName2 = undefined;
assert.equal(div.className, 'NaN');
component.testName1 = null;
component.testName2 = 1;
assert.equal(div.className, '1');
component.testName1 = undefined;
component.testName2 = 1;
assert.equal(div.className, 'NaN');
component.testName1 = null;
component.testName2 = 0;
assert.equal(div.className, '0');
component.testName1 = undefined;
component.testName2 = 0;
assert.equal(div.className, 'NaN');
}
};

@ -0,0 +1,11 @@
<script>
export let testName1;
export let testName2;
function myHelper(testName) {
return testName;
}
</script>
<div class={myHelper(testName1) + myHelper(testName2)}></div>

@ -0,0 +1,47 @@
export default {
skip_if_ssr: true,
props: {
testName1: "test1",
testName2: "test2",
},
html: `<div class="test1test2 svelte-x1o6ra"></div>`,
test({ assert, component, target }) {
const div = target.querySelector('div');
assert.equal(div.className, 'test1test2 svelte-x1o6ra');
component.testName1 = null;
component.testName2 = null;
assert.equal(div.className, '0 svelte-x1o6ra');
component.testName1 = null;
component.testName2 = "test";
assert.equal(div.className, 'nulltest svelte-x1o6ra');
component.testName1 = undefined;
component.testName2 = "test";
assert.equal(div.className, 'undefinedtest svelte-x1o6ra');
component.testName1 = undefined;
component.testName2 = undefined;
assert.equal(div.className, 'NaN svelte-x1o6ra');
component.testName1 = null;
component.testName2 = 1;
assert.equal(div.className, '1 svelte-x1o6ra');
component.testName1 = undefined;
component.testName2 = 1;
assert.equal(div.className, 'NaN svelte-x1o6ra');
component.testName1 = null;
component.testName2 = 0;
assert.equal(div.className, '0 svelte-x1o6ra');
component.testName1 = undefined;
component.testName2 = 0;
assert.equal(div.className, 'NaN svelte-x1o6ra');
}
};

@ -0,0 +1,17 @@
<script>
export let testName1;
export let testName2;
function myHelper(testName) {
return testName;
}
</script>
<style>
div {
color: purple;
}
</style>
<div class={myHelper(testName1) + myHelper(testName2)}></div>

@ -0,0 +1,5 @@
export default {
skip_if_ssr: true,
html: `<div></div>`,
};

@ -0,0 +1,5 @@
export default {
skip_if_ssr: true,
html: `<div></div>`,
};
Loading…
Cancel
Save