Skip to content

Feature Request: Resolve Object Attributes #12

@vnphanquang

Description

@vnphanquang

Hello everyone, thanks for the good work first of all. The title is itself self-explanatory i think, but please find below more info for completion.

Big question is whether this should be supported at all. Please discuss.

Rationale

Sometimes we need to pass object as prop. For example:

<!-- Image.svelte -->
<script lang="ts">
  export let src: {
    mobile: string;
    desktop: string;
  };
</script>

<picture>
  <!-- mobile img source -->
  <!-- desktop img source -->
</picture>

Right now it is not possible with svelte-preprocess-import-assets.

<script lang="ts">
  import Image from './Image.svelte';
</script>

<Image
  src={{
    mobile: '../assets/image.150x150.png',
    desktop: '../assets/image.400x400.png',
  }}
/>

src.mobile and src.desktop here would be parsed as literals.

How to?

I played with https://astexplorer.net/ and did some experimentation, seen in stackblitz here (run pnpm install & pnpm dev

Repo here if needed.

This is just some minimal code. It looks ugly, but we can expand from the idea.

const TAG = 'Image';
const STRING_TO_REPLACE = `'/vite.svg'`;

walk(ast.html, {
  enter(node) {
    if (node.name === TAG) {
      const srcAttr = node.attributes.find((attr) => attr.name === 'src');
      for (const value of srcAttr.value) {
        if (value?.expression?.type === 'ObjectExpression') {
          for (const prop of value.expression.properties) {
            if (prop.type === 'Property' && prop.value?.type === 'Literal') {
              const { start, end } = prop.value;
              s.update(start, end, STRING_TO_REPLACE);
            }
          }
        }
      }
    }
  },
});

Potential Issues?

(1) How to handle nested objects?

  • only support top level? => best imo, keep things minimal, can expand in the future when there's people requesting it
  • provide a depth config?
  • support recursively by default?

(2) Nuances such as if properties are computed values? Maybe we can do a try-catch or detect these cases and just skip the processing.

Change to config interface?

ImportAssetsOptions

A separate option for configuring behavior concerning this feature?

  • enabled to enable or disable this feature globally
  • depth to limit, if (1) in Potential Issues is of concern
interface ImportAssetsOptions {
    sources?: AssetSource[] | ((defaultSources: AssetSource[]) => AssetSource[]);
    importPrefix?: string;
    http?: boolean;
    urlFilter?: (url: string) => boolean;
+   transformObject: {
+       enabled?: boolean;
+       depth?: number;
+   }  
}

AssetSource

  • An additional objectAttributes for this purpose?
interface AssetSource {
    tag: string;
    srcAttributes?: string[];
    srcsetAttributes?: string[];
    filter?: (metadata: FilterMetadata) => boolean;
+   objectAttributes?: string[];
}

I would love to help out further if needed but might need more guidance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions