In this recipe, we’ll create a WebC component that uses Luxon to format
<time> elements for you. Eleventy already has a dependency on Luxon, so we don’t even have to install anything.
Using the Component
Before we look at how to build the component, let’s look at what it will look to use the component. The component we’ll build will be invoked like this:
Date object or an ISO date string. We use
:@ to ensure that the property is private (
@) and doesn’t end up on the final HTML output and that WebC knows to evaluate the attribute value as a variable reference (
machine-format property provides a format string used to format the date for use in the
datetime attribute. We’ll make this property optional and use an ISO datetime format if it’s missing. We use an
@ here to ensure that the property is also private, but we skip the
format property is another Luxon format string. This one is used to define the format displayed as the
<time> element’s text content. We can also make this property optional, if we have a default format we like for dates. Again, we use an
@ when we invoke the component to avoid this attribute ending up in our final HTML.
Implementing the Component
WebC allows us to create components with the same name as built-in HTML elements. We’ll override the
<time> element to allow ourselves to pass in a
Date object or ISO string, as well as format strings for Luxon. Of course, you can name your component anything you want. In a previous iteration of this recipe, it was called
The component itself is relatively short.
The first thing we do is we import the
DateTime object from Luxon and parse the date value passed to the component. We check to see if
Date object or not. If it is, we call
DateTime.fromJSDate, otherwise we assume it’s an ISO string and we call
DateTime.fromISO. We pass UTC for the timezone when we parse a
Date object to avoid the dates off-by-one pitfall.
Next, we use our format strings to generate two formatted dates for our final output. First, we generate the string for the
datetime attribute. If
machineFormat is present, call
toFormat with the format string, otherwise generate an ISO string. Then we generate the string used as the text content of the
<time> element—the text that is displayed to readers. Again, we check if a custom format string has been provided. If no format string is provided, we use a fallback format string. You can either define this string in the component itself as a string literal, or—the way I like to do—you can add some global data for your whole site containing your default date format.
Finally, we generate a valid HTML
<time> element using our formatted strings.
If you override the HTML
<time> element, do not forget to include
webc:raw in the output from your render function. WebC re-processes output from render functions as WebC. If you call your element
time.webc and return a
<time> element without
webc:raw, you’ll get an error because WebC will loop infinitely.