Skip to content
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

Attributify with Astro missing some styles in some cases #1584

Closed
AllanChain opened this issue Sep 12, 2022 · 5 comments · Fixed by #2187
Closed

Attributify with Astro missing some styles in some cases #1584

AllanChain opened this issue Sep 12, 2022 · 5 comments · Fixed by #2187
Labels
astro bug Something isn't working has-workaround

Comments

@AllanChain
Copy link

AllanChain commented Sep 12, 2022

This is a known problem and has been mentioned in #105 (comment). I'm opening a new issue here for further tracking it.

The case

The attributify extractor fails to generate style for text-red-500

<a href={href} text-red-500>Vite</a>

Reproduction: https://stackblitz.com/edit/withastro-astro-vkmvgi?file=src%2Fpages%2Findex.astro

Why

As I've mentioned:

Astro pre-processes the .astro files and transforms them into something like:

return $$render`<img${$$addAttribute(src, "src")} w-full>`;

UnoCSS expected a space after <img but Astro gives $$addAttribute part instead, making attributify mode not work well. Here we pass modified code with extra space to UnoCSS for extracting the tokens.

What can we do

Option 1: pre-process the source before extracting

This is what I've done in astro-uno, but it's a bit hacky.

        // Fixing attributify preset
        const attributifyPreset = options.presets.find(preset =>
          !Array.isArray(preset) && preset.name === '@unocss/preset-attributify'
        )
        if (!Array.isArray(attributifyPreset) && attributifyPreset) {
          const attributifyExtractor = attributifyPreset.extractors
            .find(extractor => extractor.name === 'attributify')
          const extract = attributifyExtractor.extract
          attributifyExtractor.extract = ({ code, original }) => extract({
            // Adding a space here, otherwise UnoCSS doesn't recognize the tag
            code: code.replace(/(<\w+)(\$\{\$\$addAttribute)/g, '$1 $2'),
            original
          })
        }

Option 2: make Astro allow UnoCSS to be applied earlier

This is not quite possible since the use case is rare. (And the Astro guys chose not to include official UnoCSS integration, didn't they?)

Option 3: add an option for custom extractors

We can add some APIs for creating custom extractors from existing ones and pass them to attributify. This is similar to option 1 but less hacky. Also, if we decide to support a new framework in the future but the existing extractors are not working well, we can create a new extractor to solve this.

Other options

...

Additional comments

This is the last fix astro-uno provides but is not included in unocss/astro. astro-uno can safely retire after unocss/astro provides this fix.

EDIT 1: Related issue: #1734

@impcyber
Copy link
Contributor

impcyber commented Oct 5, 2022

an alternative way could be to use a transformer in uno config:

  transformers: [
    {
      name: 'uno-astro-patch',
      enforce: 'pre',
      idFilter: id => !!id.match(/\.astro$/),
      async transform(code) {
        const matches = [...code.original.matchAll(/\$\{\$\$(addAttribute|spreadAttributes)/g)]

        if (!matches.length)
          return

        for (const match of matches) {
          const start = match.index

          code.overwrite(start, start + match[0].length, ` ${match[0]}`)
        }
      },
    },
    ...
  ],

@AllanChain
Copy link
Author

AllanChain commented Oct 5, 2022

I think @impcyber means a Vite transformer. This alternative is better and easier but will add an extra space to the final output. And we can add another transformer to remove the spaces if the spaces ever matter.

EDIT: This still can potentially break other plugins which rely on the absence of spaces. But the chance is small.

@stale
Copy link

stale bot commented Dec 5, 2022

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added stale and removed stale labels Dec 5, 2022
@stale
Copy link

stale bot commented Feb 8, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Feb 8, 2023
@sibbng
Copy link
Member

sibbng commented Feb 8, 2023

As a workaround you can use extraContent option for now:

// https://astro.build/config
export default defineConfig({
  integrations: [
    Unocss({
      extraContent: {
        filesystem: ['src/**/*.astro']
      },
      presets: [presetUno(), presetAttributify()],
    }),
  ],
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
astro bug Something isn't working has-workaround
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants