posthtml / posthtml-expressions

Use variables, JS-like expressions, and even markup-powered logic in your HTML.
Other
123 stars 20 forks source link

feat: allow script locals to use global locals #133

Closed juliovedovatto closed 1 year ago

juliovedovatto commented 1 year ago

Proposed Changes

The intent of this PR is to add support to allow script locals to use global locals defined.

I faced a situation simular to https://github.com/posthtml/posthtml-expressions/issues/132, where I needed to access a global value from my template file, while using the posthtml-include plugin.

Example:

posthtml({
      plugins: [
        include({ posthtmlExpressionsOptions: { 
         removeScriptLocals: true, 
         locals: {}
       })
      ],
})
<!-- src/components/ordered-list.html -->
<script locals>
  module.exports = {
    start: locals?.props?.startAt || 1,
  }
</script>

<div class="w-full ordered-list">
  <each loop="item, index in (props.list || [])">
    <p
      class="border-b-2 border-gray-400 font-stabil font-medium uppercase pb-1 sm:pb-3 3xl:pb-4">
      <span class="text-sm"> ({{ start++ }}) </span>
      <span class="text-left"> {{ item }} </span>
    </p>
  </each>
</div>
<include src="src/components/ordered-list.html">
{
  "props": {
    "list": [
      "activista la",
      "activista la",
    ],
    "startAt": 10
  }
}
</include>

Generated output:

<div class="w-full ordered-list">
    <p class="border-b-2 border-gray-400 font-stabil font-medium uppercase pb-1 sm:pb-3 3xl:pb-4">
      <span class="text-sm"> (20) </span>
      <span class="text-left"> activista la </span>
    </p>

    <p class="border-b-2 border-gray-400 font-stabil font-medium uppercase pb-1 sm:pb-3 3xl:pb-4">
      <span class="text-sm"> (21) </span>
      <span class="text-left"> activista la </span>
    </p>
</div>

Types of Changes

What types of changes does your code introduce Put an x in the boxes that apply

Checklist

Put an x in the boxes that apply. You can also fill these out after creating the PR. If you're unsure about any of them, don't hesitate to ask. We're here to help! This is a reminder of what we are going to look for before merging your code.

Further Comments

If this is a large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...

Reviewers: @mrmlnc, @jescalan, @michael-ciniawsky, @posthtml/collaborators

thewebartisan7 commented 1 year ago

@juliovedovatto if we here https://github.com/posthtml/posthtml-expressions/blob/master/lib/index.js#L164 change the order of options.locals and locals like below:

return normalizeTree(clearRawTag(walk({ locals: { ...locals, ...options.locals }, strictMode: options.strictMode }, tree)), tree.options)

Then we could just pass default values in script locals like below.

<script locals>
    module.exports = {
        title: 'Really default title',
    }
</script>

I did test and seem works, did am I missing something?

What do you think?

Scrum commented 1 year ago

...locals, ...options.locals This order is more correct.

thewebartisan7 commented 1 year ago

Yes I understand that it's better if you do something with locals inside the script, but in that case you can create new local, example:

<script locals>
    const first = 'John';
    const last = 'Doe';

    module.exports = {
        firstName: first,
        lastName: last,
        fullName: (locals.firstName || first) + ' ' + (locals.lastName || last);
    }
</script>

But yes it's depend.. If you want just return always default or provided, then it's better do like now.

In my new component plugin I added both way where you can define if locals is overridden (default behavior) or if it's being used by locals script (named computed).

I will write more about it in next days.