Stillat / blade-parser-typescript

A Laravel Blade parser, compiler, and static analyzer written in TypeScript.
https://stillat.com
MIT License
90 stars 3 forks source link

Embedded JS in Alpine x-data #55

Closed cheesegrits closed 1 year ago

cheesegrits commented 1 year ago

Any chance we can get embedded JS in Alpine x-data strings formatted?

Big ask, I know, but this is one of my biggest headaches with Blade formatting.

Thanks for all the hard work on this. It's awesome having someone show Blade formatting some serious love.

    <div
        x-ignore
        ax-load
        ax-load-src="{{ \Filament\Support\Facades\FilamentAsset::getAlpineComponentSrc('file-upload', 'filament/forms') }}"
        x-data="fileUploadFormComponent({
            acceptedFileTypes: @js($getAcceptedFileTypes()),
            deleteUploadedFileUsing: async (fileKey) => {
                return await $wire.deleteUploadedFile(@js($statePath), fileKey)
            },
            getUploadedFilesUsing: async () => {
                return await $wire.getFormUploadedFiles(@js($statePath))
            },
            uploadUsing: (fileKey, file, success, error, progress) => {
                $wire.upload(`{{ $statePath }}.${fileKey}`, file, () => {
                    success(fileKey)
                }, error, progress)
            },
        })"
        wire:ignore
    >
zepfietje commented 1 year ago

Just for context, @cheesegrits brought this up with me and I told him to create an issue for it, @JohnathonKoster. I'd also already been thinking about this for the Filament codebase. Would be nice if this worked in all Alpine directives (like x-text, x-show).

Let us know your thoughts, John! 😄

JohnathonKoster commented 1 year ago

This is definitely something I can look into. Will update here as I know more 🙂

zepfietje commented 1 year ago

Awesome!

JohnathonKoster commented 1 year ago

WIP todo-list (to be updated as review/prototype work continues):

Need to add test coverage and ensure safe behavior with the following structures, even if their placement inside an attribute might not always make sense:

Files with interesting output requiring review before general availability:

Filament 3:

Currently the attribute name cannot be determined during the lookback, as it breaks on whitespace. Additionally, there are challenges with any number of strings within embedded Blade content. * Original content will be returned to prevent layout changes from impacting generated JavaScript, as there is no reliable way to predict what the final output will be in all situations. Simple directives, echos, etc. will be fine. *** This is to account for the fact that the final output will be embedded in double quotes for HTML-attributes The pre-processor approach works well, however the replacement takes place before the layout process happens and prettier just wrecks everything due to print width settings ** The shadow document will be used behind the scenes to help resolve structures when the main document has been significantly altered to assist with formatting.

JohnathonKoster commented 1 year ago

This is now available starting with v1.6 🎉 - there are some configuration options available. I've added them in this comment for convenience, but this information is also available within the readme:

Formatting JavaScript Inside Attributes

The Blade formatter will format JavaScript inside Alpine.js directives by default (starting with 1.6.0). This can be disabled by adding a formatJsAttributes configuration item to your .blade.format.json:

{
    "formatJsAttributes": false,
}

If you would like to exclude a list of attributes from being formatted, you may add a list of regular expressions to the .blade.format.json file. By default, it contains the following items:

{
    "formatJsAttributes": true,
    "excludeJsAttributes": [
        "^v-"
    ]
}

If you'd like to expand the list of attributes to be formatted, you may add a list of regular expressions to the .blade.format.json file. By default this list contains the following items:

{
    "formatJsAttributes": true,
    "includeJsAttributes": [
        "^x-",
        "^ax-"
    ]
}

Modifying JavaScript Prettier Options

You can change which prettier options are applied to attribute content by adding a attributeJsOptions configuration object to your .blade.format.json file. For example, to increase the print width and disable the insertion of semicolons, you could add the following:

{
    "attributeJsOptions": {
        "semi": false,
        "printWidth": 120
    }
}
zepfietje commented 1 year ago

Great work, @JohnathonKoster! I'll give it a go soon.