ericmorand / drupal-attribute

Apache License 2.0
4 stars 7 forks source link

Using the drupal-attribute class as an async Twing function #12

Closed philwolstenholme closed 2 years ago

philwolstenholme commented 3 years ago

(This is a duplicate of me asking the same question at https://github.com/NightlyCommit/twing/issues/535)

I'm trying to use this package alongside Twing in Storybook to demonstrate Twig templates that will be used on a Drupal 9 site. The Drupal templates contain a lot of this sort of thing: {% set attributes = attributes|default(create_attribute()) %} and I'd like to be able to use the Attribute class inside Storybook. Is this possible? If so I would love some help as I've been stuck on this for a while and I am reaching the limits of my JavaScript knowledge in this area.

I am using drupal-attribute 1.0.2, Twing 5.0.2 and twing-loader 0.5.5.

In my Twing environment file I am defining a create_attribute function like this:

const drupalAttribute = require('drupal-attribute');

const createAttribute = new TwingFunction('create_attribute', () =>
  return Promise.resolve(new drupalAttribute()),
);

const environment = new TwingEnvironment(loader, { autoescape: false });
environment.addFunction(createAttribute);

module.exports = environment;

My templates are rendering, but with no attributes, so I know I am doing something wrong. There's no TwingErrorSyntax: Unknown "create_attribute" function error though. It looks like my create_attribute function can be found, but it is not usable by the templates because of how I have set things up at the moment.

My templates are pretty basic, they look like this sort of thing:

{% set attributes = attributes|default(create_attribute()) %}
{% set attributes = attributes.addClass(['btn']) %}

<button {{ attributes }}>Stripped down example</button>

Twing and using the JavaScript version of create_attribute() is new to me and I have a feeling I'm doing something silly. Is Promise.resolve(new drupalAttribute()), likely to work or am I being over optimistic here? I read something about classes not being callable? I know this isn't a Twing issue (sorry) but I wondered if anyone here had encountered the same issue, especially as Eric is also a Twing maintainer.

Other things I have tried

const createAttribute = new TwingFunction('create_attribute', () => {
  const create_attribute = new drupalAttribute();
  return Promise.resolve(create_attribute);
});
const createAttribute = function() {
  return Promise.resolve(() => {
    return new drupalAttribute();
  });
};

environment.addFunction(new TwingFunction('create_attribute', createAttribute));
JohnAlbin commented 2 years ago

@philwolstenholme I've added the glue necessary to use Attribute inside Twing as part of https://github.com/JohnAlbin/drupal-twig-extensions

Even if you don't use that package, you can probably re-use some of its GPL code.

ericmorand commented 2 years ago

@JohnAlbin amazing!!!

philwolstenholme commented 2 years ago

Thanks @JohnAlbin that's great! I'll pass this on to the team who are working on the project that I initially raised this question about. How did you get it working in the end, I'm interested in how far off I was! 😄 I'll take a look at the code next week and see if I can spot what I was missing.

tjheffner commented 2 years ago

@philwolstenholme Did you/your team ever get attributes printing properly in Storybook HTML?

I'm able to render .twig templates using Twing (thanks to the approach from @MichaelAllenWarner in https://github.com/MichaelAllenWarner/dte-storybook) but the attributes never appear to print for me.

import block from './block.twig';
import drupalAttribute from 'drupal-attribute'
import './block.css';
import './block.js';

export default { title: 'Blocks' };

export const Block = (_, { loaded: { component } }) => component;

Block.args = {
  attributes: new drupalAttribute(),
  title_attributes: new drupalAttribute(),
  plugin_id: "Some plugin",
  title_prefix: "",
  title_suffix: "",
  label: "I'm a block!",
  content: "Lorem ipsum dolor sit amet.",
  configuration: {
    provider: "Some module"
  }
}

Block.render = async args => {
  return await block({
    ...Block.args
  })
}

other args come through just fine, but the attributes are dropped:

<div>
      <h2>I'm a block!</h2>

      Lorem ipsum dolor sit amet.
  </div>
MichaelAllenWarner commented 2 years ago

@tjheffner

https://github.com/MichaelAllenWarner/dte-storybook/tree/drupal-attribute

tjheffner commented 2 years ago

@MichaelAllenWarner ah, I should have checked the other branches 😅 your repo has been extremely helpful as a reference. thank you!!

MichaelAllenWarner commented 2 years ago

@tjheffner I only just made it in response to your question (got me curious).