shufo / prettier-plugin-blade

Format your blade template using Prettier
https://www.npmjs.com/package/@shufo/prettier-plugin-blade
MIT License
318 stars 8 forks source link

[Feature Request]: Format JS inside of AlpineJS attributes #220

Closed calebdw closed 2 months ago

calebdw commented 11 months ago

Description

Hello!

It would be awesome if this plugin could automatically format javascript inside of AlpineJS attributes. Would it be possible to have the existing JS parser in prettier format the text in any attribute that starts with x-[a-z] (should cover all of Alpine)?

For example, below is a treesitter query I wrote to inject JS into any attribute that starts with x-[a-z].

; AlpineJS attributes
(attribute
  (attribute_name) @_attr
    (#lua-match? @_attr "^x%-%l")
  (quoted_attribute_value
    (attribute_value) @injection.content)
  (#set! injection.language "javascript"))

Thanks!

Suggested Solution

I'd like the javascript in my AplineJS attributes to be automatically formatted with the rest of the blade file.

Alternatives

No response

Additional Context

No response

shufo commented 11 months ago

Hi @CalebDW AlpineJS attributes are already formatted automatically in prettier-plugin-blade.

Before formatting

 $  cat __tests__/fixtures/alpine_attributes.blade.php
@section('body')
    <div id="app" class="wrapper" x-data="{
              show: true,
                actine: @js($user->isActiveOnTeam($team->id) ?? false)
                    toggle() {
            this.show = !this.show;
        },
               get state() {
            return show ? 'open' : 'close';
        }
    }" x-init="()        => alert(@js($class->id))">
        <div id="app" x-data="{
            multi_line: @true,
                          multi_line() {
                console.log()
            }
        }" class="wrapper">
            <div x-data="{ userId: @entangle('userId'), @entangle($attributes->wire('model').defer), me: '{{$userName}}'}" id='div1'></div>
            <div class='bg-red-500' x-data="{ error: @entangle('error') }" x-show='error' id='div1'></div>
            <div class='bg-yellow-500' x-data="{ error: @entangle('error'),
                warning: false }" x-show='error' id='div1'></div>

        </div>
    </div>
@stop

After formatting

 $  yarn run prettier __tests__/fixtures/alpine_attributes.blade.php
yarn run v1.22.19
$ prettier --plugin @shufo/prettier-plugin-blade __tests__/fixtures/alpine_attributes.blade.php
@section('body')
    <div id="app" class="wrapper" x-data="{
        show: true,
        actine: @js($user->isActiveOnTeam($team->id) ?? false)
        toggle() {
            this.show = !this.show;
        },
        get state() {
            return show ? 'open' : 'close';
        }
    }" x-init="() => alert(@js($class->id))">
        <div id="app" x-data="{
            multi_line: @true,
            multi_line() {
                console.log()
            }
        }" class="wrapper">
            <div x-data="{ userId: @entangle('userId'), @entangle($attributes->wire('model') . defer), me: '{{ $userName }}' }" id='div1'></div>
            <div class='bg-red-500' x-data="{ error: @entangle('error') }" x-show='error' id='div1'></div>
            <div class='bg-yellow-500' x-data="{
                error: @entangle('error'),
                warning: false
            }" x-show='error' id='div1'></div>

        </div>
    </div>
@stop
Done in 0.79s.
calebdw commented 11 months ago

@shufo,

Ah okay great! It looks like there's some discrepancies in how the JS is formatted between the plugin and prettier, for example, given the following JS code:

Unformatted JS ```js return { tasks: { task: null }, actionId: '', system: {}, showRoute: '{{ $showRoute }}', toggleTask( taskId ) { let route = '{{ $toggleRoute }}' axios.patch(route, { task_id: taskId }) .then(resp => this.tasks = this.tasks.filter(t => t.id !== taskId)) .catch(error => { swal('Request Failed', error.response.data.message, 'error') }) }, addTask() { let route = '{{ $addRoute }}' if (! this.system.id) { this.$notify.alert('No system selected!') return } else if (! this.actionId) { this.$notify.alert('No action selected!') return } axios.patch(route, { action_id: this.actionId, system_id: this.system.id, }) .then(resp => { if (resp.data.task) { this.tasks.push(resp.data.task) this.$notify.success('Task Added') this.clearInputs() return } this.$notify.info(resp.data.message) }) .catch(error => { swal('Request Failed', error.response.data.message, 'error') }) $modals.close('maintenanceTaskAddViaActionSystem') }, } ```
Formatted JS ```js return { tasks: { task: null }, actionId: "", system: {}, showRoute: "{{ $showRoute }}", toggleTask(taskId) { let route = "{{ $toggleRoute }}"; axios .patch(route, { task_id: taskId }) .then( (resp) => (this.tasks = this.tasks.filter((t) => t.id !== taskId)), ) .catch((error) => { swal("Request Failed", error.response.data.message, "error"); }); }, addTask() { let route = "{{ $addRoute }}"; if (!this.system.id) { this.$notify.alert("No system selected!"); return; } else if (!this.actionId) { this.$notify.alert("No action selected!"); return; } axios .patch(route, { action_id: this.actionId, system_id: this.system.id, }) .then((resp) => { if (resp.data.task) { this.tasks.push(resp.data.task); this.$notify.success("Task Added"); this.clearInputs(); return; } this.$notify.info(resp.data.message); }) .catch((error) => { swal("Request Failed", error.response.data.message, "error"); }); $modals.close("maintenanceTaskAddViaActionSystem"); }, }; ```
Formatted Blade ```js @section('testing')
@endsection ```

The js prettier parser formats differently than the blade parser:

Not sure if it's possible to pass off responsibility for that code range to the js parser, but you would generally expect the js to be formatted the same when when using prettier (e.g., lets say you move an x-data to a separate JS file and use Alpine.data to bring it in)

github-actions[bot] commented 9 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

0528Makoto commented 9 months ago

interested in the possible solution

github-actions[bot] commented 7 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

github-actions[bot] commented 4 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days

github-actions[bot] commented 2 months ago

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days