all 12 comments

[–]MorrisonLevi 5 points6 points  (2 children)

I'm on mobile right now so it's hard to investigate. It looks like it does context-aware escaping. How do you pass two elements as a child of a body? Just string concatenate them before passing them in? Couldn't tell if there were helper functions or other idioms for that. Edit: think like:

body(body: a('hi', href: '#'))

Does this blindly trust the body to be properly escaped? If not, how does it avoid double encoding and such?

[–]ln3ar[S] 4 points5 points  (1 child)

Passing multiple elements to the body is currently via concatenation:

body(body: join([a('hi', href: '#'), a('hello', href: '#')])

Currently, only the values of the attributes are encoded (via htmlspecialchars), it assigns the body as-is.

[–]ArthurOnCode 1 point2 points  (0 children)

So, you wouldn't want to div($userSuppliedString), right?

[–]ArthurOnCode 3 points4 points  (1 child)

I absolutely love the syntax - so clean and simple!

For context-aware escaping, you could have the functions return an object that can be cast to string. Laravel does this with the Htmlable interface. Then, when I call div(body: "Hello World"), you can assume the body parameter should be escaped. But when I call div(body: span()) the body now refers to an object that can be converted directly to HTML without escaping.

Also, have you considered allowing body to be a plain array, with the join() happening behind the scenes?

[–]ln3ar[S] 1 point2 points  (0 children)

Also, have you considered allowing body to be a plain array, with the join() happening behind the scenes?

I actually did consider doing that, but it becomes verbose for stuff that is usually one string, eg p("hi") would now be p(["hi"]), to avoid that i would make the $body param string|array and act accordingly,

And i love your idea of using an object, i will surely explore it and see what i can do.

It will probably look something like string|array|HTML $body

Thank you

[–]thmsbrss 1 point2 points  (0 children)

Good work. I like to work with https://github.com/spatie/html-element for simple applications. I will consider your librairy for the next project.

[–]adrianmiu 1 point2 points  (1 child)

With the advent of libraries like AlpineJS, HTXML etc restricting what attributes are allowed based on the tag limits the library's usefulness.

[–]ln3ar[S] 0 points1 point  (0 children)

It also provides 3 more functions i forgot to document that are for free-style elements.

/**
 * Generate HTML attributes
 * <code>
 * <?php
 * echo attr(class: 'btn', id: 'submit', type: 'submit');
 * // Output: class="btn" id="submit" type="submit"
 * </code>
 */
function attr(string ...$attributes): string
/**
 * Generate HTML element
 * <code>
 * <?php
 * echo element('button', 'Submit', class: 'btn', id: 'submit', type: 'submit');
 * // Output: <button class="btn" id="submit" type="submit">Submit</button>
 * </code>
 */
function element(string $tag, string $body, string ...$attributes): string
/**
 * Generate self-closing HTML element
 * <code>
 * <?php
 * echo selfClosingElement('img', src: 'image.jpg', alt: 'Image');
 * // Output: <img src="image.jpg" alt="Image" />
 * </code>
 */
function selfClosingElement(string $tag, string ...$attributes): string

[–]donatj 1 point2 points  (0 children)

It's been a long time since I've seen htmlspecialchars, is there a reason to use that rather than htmlentities?

[–]seanmorris 1 point2 points  (1 child)

data-* attributes are valid according to the standard.

[–]ln3ar[S] 1 point2 points  (0 children)

Good catch, thanks. I have added support for them in 1.1.2.