Rich Harris 3 months ago
parent 1ca1be5a03
commit 80370e3a26

@ -1,5 +1,5 @@
/** @import { AST } from '#compiler'; */ /** @import { AST } from '#compiler'; */
/** @import { Visitors } from 'esrap' */ /** @import { Context, Visitors } from 'esrap' */
import * as esrap from 'esrap'; import * as esrap from 'esrap';
import ts from 'esrap/languages/ts'; import ts from 'esrap/languages/ts';
import { is_void } from '../../utils.js'; import { is_void } from '../../utils.js';
@ -65,20 +65,71 @@ const visitors = {
}, },
Fragment(node, context) { Fragment(node, context) {
for (let i = 0; i < node.nodes.length; i += 1) { const join = context.new();
const child = node.nodes[i];
/** @type {Context[]} */
const contexts = [];
if (child.type === 'Text') { let sequence = context.new();
let data = child.data;
if (i === 0) data = data.trimStart(); let multiline = false;
if (i === node.nodes.length - 1) data = data.trimEnd();
context.write(data); function flush() {
if (sequence.empty()) {
return;
}
contexts.push(sequence);
sequence = context.new();
}
for (let i = 0; i < node.nodes.length; i += 1) {
const child_node = node.nodes[i];
const prev = node.nodes[i - 1];
const next = node.nodes[i + 1];
const prev_is_text = prev && (prev.type === 'Text' || prev.type === 'ExpressionTag');
const next_is_text = next && (next.type === 'Text' || next.type === 'ExpressionTag');
if (child_node.type === 'Text' || child_node.type === 'ExpressionTag') {
if (child_node.type === 'Text') {
let { data } = child_node;
let a = !prev_is_text && data !== (data = data.trimStart());
let b = !next_is_text && data !== (data = data.trimEnd());
if (data === '') {
if (prev && next) sequence.append(join);
} else {
if (a && prev) sequence.append(join);
sequence.write(data);
if (b && next) sequence.append(join);
}
} else {
sequence.visit(child_node);
}
} else { } else {
context.visit(child); flush();
const child_context = context.new();
child_context.visit(child_node);
contexts.push(child_context);
multiline ||= child_context.multiline;
} }
} }
flush();
if (multiline) {
join.newline();
} else {
join.write(' ');
}
for (const child_context of contexts) {
context.append(child_context);
}
}, },
AnimateDirective(node, context) { AnimateDirective(node, context) {
@ -329,14 +380,24 @@ const visitors = {
context.write('{:else if '); context.write('{:else if ');
context.visit(node.test); context.visit(node.test);
context.write('}'); context.write('}');
context.indent();
context.newline();
context.visit(node.consequent); context.visit(node.consequent);
context.dedent();
context.newline();
} else { } else {
context.write('{#if '); context.write('{#if ');
context.visit(node.test); context.visit(node.test);
context.write('}'); context.write('}');
context.indent();
context.newline();
context.visit(node.consequent); context.visit(node.consequent);
context.dedent();
context.newline();
} }
if (node.alternate !== null) { if (node.alternate !== null) {
if ( if (
!( !(
@ -347,8 +408,14 @@ const visitors = {
) { ) {
context.write('{:else}'); context.write('{:else}');
} }
context.indent();
context.newline();
context.visit(node.alternate); context.visit(node.alternate);
context.dedent();
context.newline();
} }
if (!node.elseif) { if (!node.elseif) {
context.write('{/if}'); context.write('{/if}');
} }

@ -0,0 +1 @@
{#if condition} yes {:else} no {/if}

@ -0,0 +1,5 @@
{#if condition}
yes
{:else}
no
{/if}

@ -23,7 +23,7 @@ const { test, run } = suite<ParserTest>(async (config, cwd) => {
const file = `${cwd}/output.svelte`; const file = `${cwd}/output.svelte`;
const expected = fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : ''; const expected = fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : '';
assert.deepEqual(output.code, expected); assert.deepEqual(output.code.trim(), expected.trim());
} }
}); });

Loading…
Cancel
Save