-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Svmigrate deletes styles and replaces with /*$$__STYLE_CONTENT__$$*/
#14712
Comments
Probably a separate issue, but the migrate script couldn't migrate
And spit out: The migration script can't fix writables? |
Can you provide a reproduction for this? |
As per the original issue: which version of svelte are you on? This was fixed before and i can't reproduce it locally. So please provide a reproduction for both issues.
Also please, we are all here to help you and this tone doesn't adhere to our code of conduct. The reason why svelte errors out in such cases is not only to make your code be more correct but also because the browser adding an extra |
Thanks for the help. Below is the exact file that failed on the cubie issue I mentioned: File<script context="module" lang="ts">
/**
* Displays a 2d rubiks scramble color map, scramble string and quick buttons
*
* Uses the current scramble stored in settings
*/
import { get, writable } from 'svelte/store';
import TailwindColors from 'tailwindcss/colors.js';
import { getKeys } from '$/types';
import Cube, { type Face, type Move, type SquareKey } from '$lib/util/rubiksCube';
import getScramble from '$lib/util/rubiksScrambleGenerator';
// (x, y) positions on canvas to draw squares
type Position = [number, number];
type Cubie = {
x: number;
y: number;
color: string;
};
const squares = writable<Cubie[]>([]);
function addSquare(position: Position, color: string) {
squares.update((s) => {
s.push({
x: position[0],
y: position[1],
color: color
});
return s;
});
}
// Modified from https://github.com/notchahm/js_speedcube_scrambler
function drawScramble(cube: Cube) {
const cornerLetterPositionMap = {
A: [155, 0],
B: [255, 0],
C: [255, 100],
D: [155, 100],
E: [0, 155],
F: [100, 155],
G: [100, 255],
H: [0, 255],
I: [155, 155],
J: [255, 155],
K: [255, 255],
L: [155, 255],
M: [310, 155],
N: [410, 155],
O: [410, 255],
P: [310, 255],
Q: [465, 155],
R: [565, 155],
S: [565, 255],
T: [465, 255],
U: [155, 310],
V: [255, 310],
W: [255, 410],
X: [155, 410]
} as Record<SquareKey, Position>;
const edgeLetterPositionMap = {
A: [205, 0],
B: [255, 50],
C: [205, 100],
D: [155, 50],
E: [50, 155],
F: [100, 205],
G: [50, 255],
H: [0, 205],
I: [205, 155],
J: [255, 205],
K: [205, 255],
L: [155, 205],
M: [360, 155],
N: [410, 205],
O: [360, 255],
P: [310, 205],
Q: [515, 155],
R: [565, 205],
S: [515, 255],
T: [465, 205],
U: [205, 310],
V: [255, 360],
W: [205, 410],
X: [155, 360]
} as Record<SquareKey, Position>;
const centerPositionMap = {
W: [205, 50],
Y: [205, 360],
O: [50, 205],
R: [360, 205],
B: [515, 205],
G: [205, 205]
} as Record<Face, Position>;
// Same as `colorRGB` in `RubiksCube3DModel.svelte`
const colorMap = {
W: '#fff',
Y: TailwindColors.yellow[400], // #facc15
O: TailwindColors.orange[500], // #f97316
R: TailwindColors.red[600], // #dc2626
B: TailwindColors.blue[600], // #2563eb
G: TailwindColors.green[600] // #16a34a
};
const cornerFaces = cube.getCornerFaces();
const edgeFaces = cube.getEdgeFaces();
squares.set([]);
for (const face of getKeys(centerPositionMap)) {
const position = centerPositionMap[face];
const color = colorMap[face];
addSquare(position, color);
}
for (const letter of getKeys(cornerFaces)) {
const position = cornerLetterPositionMap[letter];
const color = colorMap[cornerFaces[letter]];
addSquare(position, color);
}
for (const letter of getKeys(edgeFaces)) {
const position = edgeLetterPositionMap[letter];
const color = colorMap[edgeFaces[letter]];
addSquare(position, color);
}
}
export function generateScramble(newScramble = true) {
const $settings = get(settings);
// create a new scramble
if (newScramble) {
// Use the current timestamp as a seed for random scramble
$settings.rubiks.scramble = getScramble(new Date().toISOString());
}
// Create a new cube and apply the scramble to it
const c = new Cube();
$settings.rubiks.scramble.split(' ').forEach((m) => c.applyMove(m as Move));
// Draw the 2d scramble map given the scrambled 3d cube representation
drawScramble(c);
settings.set($settings);
}
</script>
<script lang="ts">
import { onMount } from 'svelte';
import { Icon } from '$lib/components/Icon';
import { dictionary } from '$lib/stores/languageDictionary';
import { settings } from '$lib/stores/settings';
import { open } from '$lib/util/modal';
onMount(() => generateScramble($settings.rubiks.scramble === ''));
</script>
<p class="h3 font-light whitespace-nowrap overflow-x-auto">
{$settings.rubiks.scramble}
</p>
<svg
viewBox="-2.5 -2.5 620 465"
class="my-4 lg:my-6 mx-auto md:max-h-[40vh]"
xmlns="http://www.w3.org/2000/svg">
<g class="stroke-base-100 dark:stroke-base-900" stroke-width="2.5">
{#each $squares as { x, y, color }}
<rect {x} {y} fill={color} width={50} height={50} class="transition-colors" />
{/each}
</g>
</svg>
<div class="flex flex-wrap gap-4 lg:gap-6">
<button
class="outline-btn btn-move-right mx-auto w-full sm:w-auto"
on:click={() => generateScramble()}>
<Icon name="chevron_right" />
{$dictionary.rubiksSettings['Generate scramble']}
</button>
<button
class="outline-btn btn-move-up mx-auto w-full sm:w-auto"
on:click={() => open('rubiks-scramble-guide')}>
<Icon name="info" />
{$dictionary.rubiksSettings['Scramble Guide']}
</button>
<button
class="outline-btn btn-move-up mx-auto w-full sm:w-auto"
on:click={() => open('rubiks-scramble-walkthrough', { scramble: $settings.rubiks.scramble })}>
<Icon name="info" />
{$dictionary.rubiksSettings['Scramble Walkthrough']}
</button>
<button
class="outline-btn btn-move-up mx-auto w-full sm:w-auto"
on:click={() => open('rubiks-interactable-cube')}>
<Icon name="cube" />
{$dictionary.rubiksSettings['Interactable Cube']}
</button>
</div> And here is the original file that got the styles deleted: File<script lang="ts">
/**
* Modal for displaying a single rubiks cube session
*/
import Icon from '$lib/components/Icon/Icon.svelte';
import ThemedVectorArt from '$lib/components/ThemedVectorArt.svelte';
import { dictionary } from '$lib/stores/languageDictionary';
import { settings } from '$lib/stores/settings';
import downloadCSV from '$lib/util/downloadCSV';
import getFormat from '$lib/util/getFormat';
import { close, open } from '$lib/util/modal';
import { getAvg, getHi, getLo } from '$lib/util/rubiksStats';
import { getDateTime } from '$lib/util/timeText';
import uid from '$lib/util/uid';
// get date session started
const getFormattedDate = (date: Date) => {
return getDateTime(date, getFormat('clock', 'date'));
};
export let data: { sessionID: string };
$: theSession = $settings.rubiks.sessions[data.sessionID];
function deleteSession() {
delete $settings.rubiks.sessions[data.sessionID];
// Handle if deleted session is the current one
if ($settings.rubiks.currentSessionID === data.sessionID) {
if (Object.keys($settings.rubiks.sessions).length === 0) {
// If no other sessions exist, create one
const rubiksSessionID = uid();
$settings.rubiks.sessions = {
[rubiksSessionID]: {
name: '',
timestamp: Date.now(),
times: []
}
};
$settings.rubiks.currentSessionID = rubiksSessionID;
} else {
// Else set the current session to the first one
$settings.rubiks.currentSessionID = Object.keys($settings.rubiks.sessions)[0];
}
}
close(); // Close the modal
}
function downloadSessionCSV() {
const session = $settings.rubiks.sessions[data.sessionID];
const csvData = [
[
$dictionary.rubiksSettings['Session Name'],
$dictionary.rubiksSettings['Session Timestamp'],
$dictionary.rubiksSettings['Session ID']
],
[session.name, session.timestamp, data.sessionID],
[],
[
$dictionary.stopwatchSettings['Time'],
$dictionary.rubiksSettings['Penalty'],
$dictionary.rubiksSettings['Scramble'],
$dictionary.rubiksSettings['Timestamp']
]
];
session.times.map((time) => {
csvData.push([time.time + time.penalty, time.penalty, time.scramble, time.timestamp]);
});
downloadCSV(csvData, `${session.name || 'Untitled'}.csv`);
}
function deleteTime(timestamp: number) {
theSession.times = theSession.times.filter((t) => t.timestamp !== timestamp);
// Update the time list behind the modal
$settings.rubiks.sessions = $settings.rubiks.sessions;
}
</script>
<!--
Wrap modal in `if` check so deleting session doesn't crash.
Modal will close after session is deleted anyway and we can't open a session that doesn't exist,
so this `if` check resolves all problems.
-->
{#if theSession}
<div class="pad">
<div class="flex flex-wrap flex-col md:flex-row justify-between items-center gap-4 lg:gap-10">
<div class="text-center">
<label for="session-name" class="label">
{$dictionary.pomodoroSettings['Name:']}
</label>
<input id="session-name" type="text" maxlength="40" bind:value={theSession.name} />
</div>
<p class="p">{getFormattedDate(new Date(theSession.timestamp))}</p>
<button
class="my-4 outline-btn inline-flex"
class:accent-btn={data.sessionID === $settings.rubiks.currentSessionID}
on:click={() => ($settings.rubiks.currentSessionID = data.sessionID)}>
<Icon name="play" />
<p>
{$dictionary.rubiksSettings[
data.sessionID === $settings.rubiks.currentSessionID
? 'Current session'
: 'Make current'
]}
</p>
</button>
{#if theSession.times.length > 0}
<p class="h4">
{$dictionary.rubiksSettings['Lo:']}
<span class="font-bold">
{getLo(theSession.times) / 1000}{$dictionary.rubiksSettings['seconds_short']}
</span>
<span class="mx-1">|</span>
{$dictionary.rubiksSettings['Avg:']}
<span class="font-bold">
{getAvg(theSession.times) / 1000}{$dictionary.rubiksSettings['seconds_short']}
</span>
<span class="mx-1">|</span>
{$dictionary.rubiksSettings['Hi:']}
<span class="font-bold">
{getHi(theSession.times) / 1000}{$dictionary.rubiksSettings['seconds_short']}
</span>
</p>
<button class="outline-btn btn-move-down" on:click={downloadSessionCSV}>
<Icon name="download" />
{$dictionary.labels['Download']}
</button>
{/if}
<button class="outline-btn btn-rotate-clock-sm" on:click={deleteSession}>
<Icon name="trash" />
{$dictionary.labels['Delete']}
</button>
</div>
<hr class="my-10 max-w-full" />
{#if theSession.times.length > 0}
<div class="w-full overflow-x-auto">
<table class="p pb-4 whitespace-nowrap max-w-5xl mx-auto">
<tr>
<th>{$dictionary.stopwatchSettings['Time']}</th>
<th>{$dictionary.rubiksSettings['Penalty']}</th>
<th>{$dictionary.rubiksSettings['Scramble']}</th>
<th />
</tr>
{#each theSession.times as time}
<tr>
<td>
<span>
<!-- fix for shift if time becomes over 10s due to penalty -->
<span class="opacity-0">
{time.time + time.penalty < 10_000 ? '0' : ''}
</span>
{(time.time + time.penalty) / 1000}{$dictionary.rubiksSettings['seconds_short']}
</span>
</td>
<td class="flex items-center gap-4">
<button
class="btn block"
disabled={time.penalty === 0}
on:click={() => (time.penalty -= 2000)}>
{$dictionary.rubiksSettings['-2s']}
</button>
<span class="block text-center">
<!-- fix for shift if over 10s penalty -->
<span class="opacity-0">
{time.penalty < 10_000 ? '0' : ''}
</span>
{time.penalty / 1000}s
</span>
<button
class="btn block"
disabled={time.penalty === 100_000}
on:click={() => (time.penalty += 2000)}>
{$dictionary.rubiksSettings['+2s']}
</button>
</td>
<td>
<button
class="a p-sm"
on:click={() => open('rubiks-scramble-walkthrough', { scramble: time.scramble })}>
{time.scramble}
</button>
</td>
<td>
<button
class="icon-btn"
on:click={() => deleteTime(time.timestamp)}
title={$dictionary.labels['Delete']}>
<Icon name="trash" />
</button>
</td>
</tr>
{/each}
</table>
</div>
{:else}
<div class="select-none w-80 xl:w-96 mx-auto">
<ThemedVectorArt name="rubiks" />
</div>
<h3 class="h3 sm:mt-6 text-center">{$dictionary.rubiksSettings['No times yet']}</h3>
{/if}
</div>
{/if}
<style lang="postcss">
table td {
@apply border-l border-base-300 first:border-0 dark:border-base-600;
}
.accent-btn {
@apply border-0 bg-accent-700 text-white hover:bg-accent-700;
}
</style> As for the Here are the deps before upgrade: "devDependencies": {
"@sveltejs/adapter-netlify": "^4.3.3",
"@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.5.13",
"@types/gtag.js": "^0.0.12",
"@types/suncalc": "^1.9.2",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"@vitest/coverage-v8": "^1.1.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-svelte": "^2.35.1",
"lighthouse": "^11.4.0",
"postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
"prettier": "^3.1.1",
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-svelte": "^3.1.2",
"prettier-plugin-tailwindcss": "^0.5.10",
"puppeteer": "^21.3.8",
"pwa-asset-generator": "^6.3.1",
"svelte": "^4.2.8",
"svelte-check": "^3.6.2",
"svelte-preprocess": "^5.1.3",
"typescript": "^5.3.3",
"vite": "^5.0.13",
"vitest": "^1.1.0"
},
"dependencies": {
"dayjs": "^1.11.10",
"lz-string": "^1.5.0",
"motion": "^10.16.4",
"screenfull": "^6.0.2",
"suncalc": "^1.9.0",
"tailwindcss": "^3.4.0"
}, And after: "devDependencies": {
"@sveltejs/adapter-netlify": "^4.3.3",
"@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.5.27",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@tauri-apps/api": "^1.6.0",
"@tauri-apps/cli": "^1.5.13",
"@types/gtag.js": "^0.0.12",
"@types/suncalc": "^1.9.2",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"@vitest/coverage-v8": "^1.1.0",
"autoprefixer": "^10.4.16",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.2",
"eslint-plugin-svelte": "^2.45.1",
"lighthouse": "^11.4.0",
"postcss": "^8.4.32",
"postcss-load-config": "^5.0.2",
"prettier": "^3.1.1",
"prettier-plugin-organize-imports": "^3.2.4",
"prettier-plugin-svelte": "^3.2.6",
"prettier-plugin-tailwindcss": "^0.5.10",
"puppeteer": "^21.3.8",
"pwa-asset-generator": "^6.3.1",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"svelte-preprocess": "^6.0.0",
"typescript": "^5.5.0",
"vite": "^5.4.4",
"vitest": "^1.1.0"
},
"dependencies": {
"dayjs": "^1.11.10",
"lz-string": "^1.5.0",
"motion": "^10.16.4",
"screenfull": "^6.0.2",
"suncalc": "^1.9.0",
"tailwindcss": "^3.4.0"
}, The only thing I did was run Thanks again for the help! |
Another file where the migration script ended up copying and pasting my comment over and over again: Original File<script lang="ts">
import type { ChangeEventHandler } from 'svelte/elements';
import { systemFontFamilies } from '$lib/data/consts';
type LabelMapper = (value: string | number, idx: number) => string;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
export let id: string | undefined = undefined,
selectLabel: string = '',
showLabel: boolean = true,
value: string | number | null,
disabled = false,
values: Readonly<(string | number)[]> = [],
labels: Record<string | number, string> | undefined = undefined,
onchange: ChangeEventHandler<HTMLSelectElement> | undefined = undefined,
labelMapper: LabelMapper = (value) => (labels ? labels[value] : String(value)),
dynamicFont = false;
// HACK: svelte has no way of knowing other than this that the labelMapper depends on labels
// Update the values when labels changes, so the dropdown has the correct values
$: labels, (values = values);
</script>
{#if selectLabel && showLabel}
<label for={id} class="label">{selectLabel}</label>
{/if}
<!--
The change listener is basically `on:change={onchange}`
except we copy the event so the currentTarget doesn't change.
Otherwise, the component wouldn't work.
We use `currentTarget` instead of `target` to make TypeScript happy.
-->
<select
{id}
{disabled}
aria-label={selectLabel}
bind:value
on:change={(e) => onchange?.({ ...e, currentTarget: e.currentTarget })}>
{#each values as val, idx}
<option
value={val}
style={dynamicFont && val === ''
? `font-family:${systemFontFamilies}`
: `font-family:${dynamicFont ? val : ''}`}>{labelMapper(val, idx)}</option>
{/each}
</select>
New File<script lang="ts">
import { run } from 'svelte/legacy';
import type { ChangeEventHandler } from 'svelte/elements';
import { systemFontFamilies } from '$lib/data/consts';
type LabelMapper = (value: string | number, idx: number) => string;
interface Props {
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
id?: string | undefined;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
selectLabel?: string;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
showLabel?: boolean;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
value: string | number | null;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
disabled?: boolean;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
values?: Readonly<(string | number)[]>;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
labels?: Record<string | number, string> | undefined;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
onchange?: ChangeEventHandler<HTMLSelectElement> | undefined;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
labelMapper?: LabelMapper;
/*
id: id of select and for label
selectLabel: label text
value: current value of select (can be bound)
disabled: disabled attr of select
values: list of values to loop through, option values
labels: array of labels for each option, indexed by values
onchange: function that runs on:change
labelMapper: custom function that maps a value to a label string
dynamicFont: true if each option should have a font family according to its value (for font family pickers)
*/
dynamicFont?: boolean;
}
let {
id = undefined,
selectLabel = '',
showLabel = true,
value = $bindable(),
disabled = false,
values = $bindable([]),
labels = undefined,
onchange = undefined,
labelMapper = (value) => (labels ? labels[value] : String(value)),
dynamicFont = false
}: Props = $props();
// HACK: svelte has no way of knowing other than this that the labelMapper depends on labels
// Update the values when labels changes, so the dropdown has the correct values
run(() => {
labels, (values = values);
});
</script>
{#if selectLabel && showLabel}
<label for={id} class="label">{selectLabel}</label>
{/if}
<!--
The change listener is basically `on:change={onchange}`
except we copy the event so the currentTarget doesn't change.
Otherwise, the component wouldn't work.
We use `currentTarget` instead of `target` to make TypeScript happy.
-->
<select
{id}
{disabled}
aria-label={selectLabel}
bind:value
onchange={(e) => onchange?.({ ...e, currentTarget: e.currentTarget })}>
{#each values as val, idx}
<option
value={val}
style={dynamicFont && val === ''
? `font-family:${systemFontFamilies}`
: `font-family:${dynamicFont ? val : ''}`}>{labelMapper(val, idx)}</option>
{/each}
</select>
|
A question while I'm bothering you about sv migrate: Is there a reason this:
Was replaced with this:
And not just $derived()? Is it because the migration script has no way of knowing if |
For the first issue i confirm that while it can't migrate it doesn't substitute the styles (you should probably update svelte and try again). For the export function generateScramble(newScramble = true) {
const $settings = get(settings);
// create a new scramble
if (newScramble) {
// Use the current timestamp as a seed for random scramble
$settings.rubiks.scramble = getScramble(new Date().toISOString());
}
// Create a new cube and apply the scramble to it
const c = new Cube();
$settings.rubiks.scramble.split(' ').forEach((m) => c.applyMove(m as Move));
// Draw the 2d scramble map given the scrambled 3d cube representation
drawScramble(c);
settings.set($settings);
} it's creating a variable starting with For the comment issue we can't do much about it...we use the comment above the prop declaration to keep the comments attached to the new prop declaration and we can't possibly know that what you meant with that comment is to provide a comment for different lines of the declaration. Finally for the I'll close this issue since everything is resolved but thanks for reporting! |
Thanks again for the reply. I tried multiple times and it replaces the styles. I understand why the For the comment issue, I agree you can't know where it goes, but surely you can agree that copying and pasting the same comment over and over is a bug and not intentional, right? Thanks for explaining I wouldn't say the replacing styles issue is resolved, but I suppose that's all I'll get. Thanks again for all the help and fast replies. |
Did you update svelte to latest before doing it? I literally copy pasted your component in a fresh project and migrated it and it did not delete the styles. If you can provide your code I can take a look.
Obviously in an ideal word we wouldn't do that but how can we know if that is meant to be a comment that goes over every prop or one that should just go on top of everything reliably? |
I suppose you have no way of knowing where the comment goes. I just think you put it in the first location it could go rather than copying and pasting. But it's not a big deal. Also wdym update svelte before doing it? Isn't the whole point of sv migrate to update svelte for me, from 4 to 5? Do I update to the latest version of svelte 4 before running sv migrate? Is that mentioned in the docs? Or do I update to svelte 5 and then run sv migrate after that? Thanks again for the help. Appreciate all the work on svelte. |
Do you have any advice for svelte 4 to 5 migration by the way? It's been a few weeks and I'm still nowhere close and running into a bunch of bugs. The diff is also thousands of lines across 120+ files, and 25% increased line count from the diff. I keep finding new bugs and pages that are broken. It's starting to really not feel worth upgrading. I'm not doing anything super complex, it's mostly basic CRUD/MVC stuff, not much worse than a todo app. I just have a lot of components and pages. Thanks in advance. |
This is the number one suggestion: if you then run into problems what I would do is just revert the changes of the problematic components leaving them in legacy mode and then migrate them by hand incrementally |
I began migration from my svelte 4 project to svelte 5 by running |
Regardless...did you tried to delete the lock, install again and run the migration? |
Tried again, deleting Still had the issue of copy and paste duplicate comments: And still resulted in deleting all my styles when there is "invalid" html Again, using the term "invalid" quite loosely here, since tables have rendered fine for many years on 99.99% of browsers without tbody, browsers have no problems, screen readers have no problems, doesn't cause bugs, hurt a11y, etc. And I don't mind fixing it, but it doesn't feel like something that should break sv migrate imo. Thanks again for the help. It's been a few weeks but I'm almost done migrating my project. Not the fault of migrate, but it's been a lot of work, many hours a day for many days. Lots of infinite loops that didn't used to occur, deleted comments, moved code, deleted css, fixing for legacy APIs, etc. The diff is way way longer, many hundreds of lines, but there are parts of it that are cleaner. I do really like runes. I've certainly got my issues with svelte 5 as well, but that's another topic. |
Then I need you to provide an actual reproduction for this, as I've said I was not able to reproduce with your code in my project so there's definitely something weird with the rest of the setup. |
Describe the bug
Deleted all my styles and output
/*$$__STYLE_CONTENT__$$*/
Reproduction
I ran
npx sv migrate svelte-5
I had a file with an "error" due to having a
<tr>
inside a<table>
.I understand and are technically correct, but
I understand something more important like not having a button within a button, but for a tr inside a table, this is ridiculous.
I've got a svelte 4 project that is quite large, and I'm not doing anything wacky or hacky or legacy, and it's taking me hours to sift through all this and fix all the the hundreds of lines that svmigrate deleted.
I appreciate the devs hard at work on svmigrate; it's well beyond my paygrade here and (hopefully in the future) saves devs a lot of time and headache.
Logs
No response
System Info
Severity
blocking an upgrade
The text was updated successfully, but these errors were encountered: