fix: keep space in `<pre>` or `preserveWhitespace: true`

pull/6990/head
yosuke ota 5 years ago
parent 68dd118de0
commit 8d90e0eb4f

@ -43,4 +43,21 @@ export default class Text extends Node {
return parent_element.namespace || elements_without_text.has(parent_element.name);
}
keep_space(): boolean {
if (this.component.component_options.preserveWhitespace) return true;
return this.within_pre();
}
within_pre(): boolean {
let node = this.parent;
while (node) {
if (node.type === 'Element' && node.name === 'pre') {
return true;
}
node = node.parent;
}
return false;
}
}

@ -95,7 +95,7 @@ export default class FragmentWrapper {
next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.node.data) && trimmable_at(child, next_sibling)) : !child.has_ancestor('EachBlock')
);
if (should_trim) {
if (should_trim && !child.keep_space()) {
data = trim_end(data);
if (!data) continue;
}
@ -127,7 +127,7 @@ export default class FragmentWrapper {
if (strip_whitespace) {
const first = this.nodes[0] as Text;
if (first && first.node.type === 'Text') {
if (first && first.node.type === 'Text' && !first.node.keep_space()) {
first.data = trim_start(first.data);
if (!first.data) {
first.var = null;

@ -29,15 +29,7 @@ export default class TextWrapper extends Wrapper {
if (this.renderer.component.component_options.preserveWhitespace) return false;
if (/[\S\u00A0]/.test(this.data)) return false;
let node = this.parent && this.parent.node;
while (node) {
if (node.type === 'Element' && node.name === 'pre') {
return false;
}
node = node.parent;
}
return true;
return !this.node.within_pre();
}
render(block: Block, parent_node: Identifier, parent_nodes: Identifier) {

@ -26,7 +26,7 @@ export default function remove_whitespace_children(children: INode[], next?: INo
trimmable_at(child, next)
: !child.has_ancestor('EachBlock');
if (should_trim) {
if (should_trim && !child.keep_space()) {
data = trim_end(data);
if (!data) continue;
}
@ -47,7 +47,7 @@ export default function remove_whitespace_children(children: INode[], next?: INo
}
const first = nodes[0];
if (first && first.type === 'Text') {
if (first && first.type === 'Text' && !first.keep_space()) {
first.data = trim_start(first.data);
if (!first.data) {
first.var = null;

@ -0,0 +1,86 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
detach,
element,
init,
insert,
noop,
safe_not_equal,
space
} from "svelte/internal";
function create_fragment(ctx) {
let pre0;
let t3;
let div0;
let t7;
let div1;
return {
c() {
pre0 = element("pre");
pre0.innerHTML = `
A
B
<span>
C
D
</span>
E
F
`;
t3 = space();
div0 = element("div");
div0.innerHTML = `A
B
<span>C
D</span>
E
F`;
t7 = space();
div1 = element("div");
div1.innerHTML = `<pre>
A
B
<span>
C
D
</span>
E
F
</pre>`;
},
m(target, anchor) {
insert(target, pre0, anchor);
insert(target, t3, anchor);
insert(target, div0, anchor);
insert(target, t7, anchor);
insert(target, div1, anchor);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(pre0);
if (detaching) detach(t3);
if (detaching) detach(div0);
if (detaching) detach(t7);
if (detaching) detach(div1);
}
};
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
}
}
export default Component;

@ -0,0 +1,34 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>
A
B
<span>
C
D
</span>
E
F
</div>
<div>
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
</div>

@ -0,0 +1,5 @@
export default {
options: {
preserveWhitespace: true
}
};

@ -0,0 +1,92 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
detach,
element,
init,
insert,
noop,
safe_not_equal,
text
} from "svelte/internal";
function create_fragment(ctx) {
let pre0;
let t3;
let div0;
let t7;
let div1;
return {
c() {
pre0 = element("pre");
pre0.innerHTML = `
A
B
<span>
C
D
</span>
E
F
`;
t3 = text("\n\n");
div0 = element("div");
div0.innerHTML = `
A
B
<span>
C
D
</span>
E
F
`;
t7 = text("\n\n");
div1 = element("div");
div1.innerHTML = `
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
`;
},
m(target, anchor) {
insert(target, pre0, anchor);
insert(target, t3, anchor);
insert(target, div0, anchor);
insert(target, t7, anchor);
insert(target, div1, anchor);
},
p: noop,
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(pre0);
if (detaching) detach(t3);
if (detaching) detach(div0);
if (detaching) detach(t7);
if (detaching) detach(div1);
}
};
}
class Component extends SvelteComponent {
constructor(options) {
super();
init(this, options, null, create_fragment, safe_not_equal, {});
}
}
export default Component;

@ -0,0 +1,34 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>
A
B
<span>
C
D
</span>
E
F
</div>
<div>
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
</div>

@ -83,9 +83,13 @@ describe('ssr', () => {
if (css.code) fs.writeFileSync(`${dir}/_actual.css`, css.code);
try {
(compileOptions.preserveComments
? assert.htmlEqualWithComments
: assert.htmlEqual)(html, expectedHtml);
if (config.withoutNormalizeHtml) {
assert.strictEqual(html.trim(), expectedHtml.trim());
} else {
(compileOptions.preserveComments
? assert.htmlEqualWithComments
: assert.htmlEqual)(html, expectedHtml);
}
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(`${dir}/_expected.html`, html);

@ -0,0 +1,3 @@
export default {
withoutNormalizeHtml: true
};

@ -0,0 +1,30 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>A
B
<span>C
D
</span>
E
F
</div>
<div><pre>
A
B
<span>
C
D
</span>
E
F
</pre></div>

@ -0,0 +1,34 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>
A
B
<span>
C
D
</span>
E
F
</div>
<div>
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
</div>

@ -0,0 +1,6 @@
export default {
withoutNormalizeHtml: true,
compileOptions: {
preserveWhitespace: true
}
};

@ -0,0 +1,34 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>
A
B
<span>
C
D
</span>
E
F
</div>
<div>
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
</div>

@ -0,0 +1,34 @@
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
<div>
A
B
<span>
C
D
</span>
E
F
</div>
<div>
<pre>
A
B
<span>
C
D
</span>
E
F
</pre>
</div>
Loading…
Cancel
Save