svelte-shaker 0.9.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
Binary file
|
package/dist/transform.js
CHANGED
|
@@ -274,12 +274,17 @@ outDead) {
|
|
|
274
274
|
* or gain a space.
|
|
275
275
|
*/
|
|
276
276
|
function foldIfBlocks(fragment, env, setEnv, code, s, dead) {
|
|
277
|
-
walk(fragment, { parent: null, preserve: hasPreserveWhitespaceOption(fragment) }, {
|
|
277
|
+
walk(fragment, { parent: null, preserve: hasPreserveWhitespaceOption(fragment), element: null }, {
|
|
278
278
|
_(node, { state, next }) {
|
|
279
279
|
if (node.type !== 'IfBlock') {
|
|
280
|
-
// Descend, recording this node as the children's parent
|
|
281
|
-
// opens a preserved-whitespace context
|
|
282
|
-
|
|
280
|
+
// Descend, recording this node as the children's parent, whether it
|
|
281
|
+
// opens a preserved-whitespace context, and the content-model element
|
|
282
|
+
// their seam would land in (for the `{" "}` validity check).
|
|
283
|
+
next({
|
|
284
|
+
parent: node,
|
|
285
|
+
preserve: state.preserve || isPreserveElement(node),
|
|
286
|
+
element: childParentElement(node, state.element),
|
|
287
|
+
});
|
|
283
288
|
return;
|
|
284
289
|
}
|
|
285
290
|
// `elseif` IfBlocks are the *continuation* of a chain we already own from
|
|
@@ -294,9 +299,12 @@ function foldIfBlocks(fragment, env, setEnv, code, s, dead) {
|
|
|
294
299
|
// node as its children's parent), so its `nodes` are the chain's siblings.
|
|
295
300
|
index: state.parent?.nodes?.indexOf(node) ?? -1,
|
|
296
301
|
preserve: state.preserve,
|
|
302
|
+
element: state.element,
|
|
297
303
|
});
|
|
304
|
+
// kept head: descend for nested blocks. The `{#if}` is transparent to the
|
|
305
|
+
// content model, so children stay in the same parent element.
|
|
298
306
|
if (decision.recurse)
|
|
299
|
-
next({ parent: node, preserve: state.preserve });
|
|
307
|
+
next({ parent: node, preserve: state.preserve, element: state.element });
|
|
300
308
|
// otherwise the subtree is gone or re-emitted verbatim — do not recurse.
|
|
301
309
|
},
|
|
302
310
|
});
|
|
@@ -366,10 +374,12 @@ function isFullRemoval(decision) {
|
|
|
366
374
|
* edge-trimmed, so it renders exactly one space wherever it lands, matching the
|
|
367
375
|
* original. Otherwise plain deletion already preserves space presence (only the
|
|
368
376
|
* run LENGTH can differ, which the SSR oracle normalizes). Never compensate
|
|
369
|
-
* under preserved whitespace — there plain deletion is byte-exact
|
|
377
|
+
* under preserved whitespace — there plain deletion is byte-exact — nor inside a
|
|
378
|
+
* text-free parent (`<tr>`, `<tbody>`, …), where Svelte rejects the `{" "}` text
|
|
379
|
+
* child outright and the whitespace rendered nothing to begin with.
|
|
370
380
|
*/
|
|
371
381
|
function removeChain(removed, span, code, s, dead, ctx) {
|
|
372
|
-
if (!ctx.preserve && ctx.parent?.nodes && ctx.index >= 0) {
|
|
382
|
+
if (!ctx.preserve && !isTextFreeParent(ctx.element) && ctx.parent?.nodes && ctx.index >= 0) {
|
|
373
383
|
const seam = analyzeSeam(ctx.parent.nodes, ctx.index, span, code, dead);
|
|
374
384
|
if (seam) {
|
|
375
385
|
s.overwrite(seam[0], seam[1], '{" "}');
|
|
@@ -431,6 +441,49 @@ function isRenderingSibling(node, code) {
|
|
|
431
441
|
function isPreserveElement(node) {
|
|
432
442
|
return node.type === 'RegularElement' && (node.name === 'pre' || node.name === 'textarea');
|
|
433
443
|
}
|
|
444
|
+
/**
|
|
445
|
+
* Parent elements whose HTML content model forbids a text child: Svelte's
|
|
446
|
+
* `is_tag_valid_with_parent('#text', …)` rejects a `#text`/`{" "}` here with
|
|
447
|
+
* `node_invalid_placement` — these are exactly its `disallowed_children` entries
|
|
448
|
+
* that carry an `only` list (html/head/frameset/#document can't appear as
|
|
449
|
+
* elements inside a component, so only the table parts remain). Svelte never
|
|
450
|
+
* renders inter-child whitespace inside them either, so a removed chain's seam
|
|
451
|
+
* needs plain deletion: emitting the `{" "}` compensation would produce a
|
|
452
|
+
* component that fails to compile. See {@link removeChain}.
|
|
453
|
+
*/
|
|
454
|
+
const TEXT_FREE_PARENTS = new Set(['table', 'thead', 'tbody', 'tfoot', 'tr', 'colgroup']);
|
|
455
|
+
/**
|
|
456
|
+
* Node types that reset the content-model parent to "unknown" (text allowed
|
|
457
|
+
* again), mirroring svelte's `parent_element: null` reset in the SvelteElement /
|
|
458
|
+
* SvelteFragment / SnippetBlock / Component visitors. A `{" "}` seam in any of
|
|
459
|
+
* these contexts is valid, so the seam compensation may proceed.
|
|
460
|
+
*/
|
|
461
|
+
const PARENT_ELEMENT_RESET = new Set([
|
|
462
|
+
'SvelteElement',
|
|
463
|
+
'SvelteFragment',
|
|
464
|
+
'SnippetBlock',
|
|
465
|
+
'Component',
|
|
466
|
+
'SvelteSelf',
|
|
467
|
+
'SvelteComponent',
|
|
468
|
+
]);
|
|
469
|
+
/**
|
|
470
|
+
* The content-model parent element a seam would land in for `node`'s children,
|
|
471
|
+
* given the element the walk is currently inside. Mirrors svelte's
|
|
472
|
+
* `parent_element` threading: a `RegularElement` becomes the parent, the reset
|
|
473
|
+
* node types clear it, and every other node (Fragment, blocks, …) is transparent
|
|
474
|
+
* and inherits. `null` means "text allowed" (root or a reset context).
|
|
475
|
+
*/
|
|
476
|
+
function childParentElement(node, current) {
|
|
477
|
+
if (node.type === 'RegularElement')
|
|
478
|
+
return node.name ?? null;
|
|
479
|
+
if (PARENT_ELEMENT_RESET.has(node.type))
|
|
480
|
+
return null;
|
|
481
|
+
return current;
|
|
482
|
+
}
|
|
483
|
+
/** True when an `{" "}` seam would be an invalid text child of `element`. */
|
|
484
|
+
function isTextFreeParent(element) {
|
|
485
|
+
return element !== null && TEXT_FREE_PARENTS.has(element);
|
|
486
|
+
}
|
|
434
487
|
/** Does the component opt into preserved whitespace via `<svelte:options>`? */
|
|
435
488
|
function hasPreserveWhitespaceOption(fragment) {
|
|
436
489
|
let preserve = false;
|