From f47ffa2ad0ac35859a3034e9d740ecb91f632fa0 Mon Sep 17 00:00:00 2001 From: Simon Holthausen Date: Thu, 25 Apr 2024 20:42:55 +0200 Subject: [PATCH] indentation --- packages/svelte/src/compiler/migrate/index.js | 63 ++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/packages/svelte/src/compiler/migrate/index.js b/packages/svelte/src/compiler/migrate/index.js index d5e17153e5..b29d1e69c5 100644 --- a/packages/svelte/src/compiler/migrate/index.js +++ b/packages/svelte/src/compiler/migrate/index.js @@ -28,12 +28,14 @@ export function migrate(source) { const str = new MagicString(source); const analysis = analyze_component(parsed, source, combined_options); + const indent = guess_indent(source); /** @type {State} */ let state = { scope: analysis.instance.scope, analysis, str, + indent, props: [], props_insertion_point: 0, has_props_rune: false, @@ -81,13 +83,13 @@ export function migrate(source) { // no regular props found, but render tags or events to forward found, $props() will be first in the script tag str.appendRight( /** @type {number} */ (parsed.instance.content.start), - `\n\t${props_declaration}` + `\n${indent}${props_declaration}` ); } else { str.appendRight(state.props_insertion_point, props_declaration); } } else { - str.prepend(``); + str.prepend(``); } } } @@ -104,6 +106,7 @@ export function migrate(source) { * scope: import('../phases/scope.js').Scope; * str: MagicString; * analysis: import('../phases/types.js').ComponentAnalysis; + * indent: string; * props: Array<{ local: string; exported: string; init: string; bindable: boolean }>; * props_insertion_point: number; * has_props_rune: boolean; @@ -245,15 +248,32 @@ const instance_script = { state.str.prependLeft(/** @type {number} */ (node.body.expression.right.start), '$derived('); state.str.appendRight(/** @type {number} */ (node.body.expression.right.end), ')'); } else { + const is_block_stmt = node.body.type === 'BlockStatement'; + const start_end = /** @type {number} */ (node.body.start); // $effect.pre, to be precise, but we gloss over that // TODO try to find out if we can use $derived.by instead? // TODO SSR mode variant needed - state.str.update( - /** @type {number} */ (node.start), - /** @type {number} */ (node.body.start), - '$effect(() => {' - ); - state.str.appendRight(/** @type {number} */ (node.end), '})'); + if (is_block_stmt) { + state.str.update(/** @type {number} */ (node.start), start_end + 1, '$effect(() => {'); + const end = /** @type {number} */ (node.body.end); + state.str.update(end - 1, end, '});'); + } else { + state.str.update( + /** @type {number} */ (node.start), + start_end, + `$effect(() => {\n${state.indent}` + ); + state.str.indent(state.indent, { + exclude: [ + [0, /** @type {number} */ (node.body.start)], + [ + /** @type {number} */ (node.body.end), + /** @type {number} */ (/** @type {import('estree').Program} */ (path.at(-1)).end) + ] + ] + }); + state.str.appendRight(/** @type {number} */ (node.end), `\n${state.indent}});`); + } } } }; @@ -367,3 +387,30 @@ function handle_identifier(node, state) { ); } } + +/** @param {string} content */ +function guess_indent(content) { + const lines = content.split('\n'); + + const tabbed = lines.filter((line) => /^\t+/.test(line)); + const spaced = lines.filter((line) => /^ {2,}/.test(line)); + + if (tabbed.length === 0 && spaced.length === 0) { + return '\t'; + } + + // More lines tabbed than spaced? Assume tabs, and + // default to tabs in the case of a tie (or nothing + // to go on) + if (tabbed.length >= spaced.length) { + return '\t'; + } + + // Otherwise, we need to guess the multiple + const min = spaced.reduce((previous, current) => { + const count = /^ +/.exec(current)?.[0].length ?? 0; + return Math.min(count, previous); + }, Infinity); + + return ' '.repeat(min); +}