Giter Site home page Giter Site logo

nunomaduro / termwind Goto Github PK

View Code? Open in Web Editor NEW
2.2K 20.0 74.0 8.81 MB

๐Ÿƒ In short, it's like Tailwind CSS, but for the PHP command-line applications.

License: MIT License

PHP 99.15% Makefile 0.71% Dockerfile 0.14%
php console css tailwind

termwind's Introduction

Termwind logo

Termwind

Termwind example

GitHub Workflow Status (master) Total Downloads Latest Version License


Termwind allows you to build unique and beautiful PHP command-line applications, using the Tailwind CSS API. In short, it's like Tailwind CSS, but for the PHP command-line applications.

Installation

Requires PHP 8.0+

Require Termwind using Composer:

composer require nunomaduro/termwind

Usage

use function Termwind\{render};

// single line html...
render('<div class="px-1 bg-green-300">Termwind</div>');

// multi-line html...
render(<<<'HTML'
    <div>
        <div class="px-1 bg-green-600">Termwind</div>
        <em class="ml-1">
          Give your CLI apps a unique look
        </em>
    </div>
HTML);

// Laravel or Symfony console commands...
class UsersCommand extends Command
{
    public function handle()
    {
        render(
            view('users.index', [
                'users' => User::all()
            ])
        );
    }
}

style()

The style() function may be used to add own custom styles and also update colors.

use function Termwind\{style};

style('green-300')->color('#bada55');
style('btn')->apply('p-4 bg-green-300 text-white');

render('<div class="btn">Click me</div>');

ask()

The ask() function may be used to prompt the user with a question.

use function Termwind\{ask};

$answer = ask(<<<HTML
    <span class="mt-1 ml-2 mr-1 bg-green px-1 text-black">
        What is your name?
    </span>
HTML);

The return provided from the ask method will be the answer provided from the user.

terminal()

The terminal() function returns an instance of the Terminal class, with the following methods:

  • ->width(): Returns the full width of the terminal.
  • ->height(): Returns the full height of the terminal.
  • ->clear(): It clears the terminal screen.

Classes Supported

All the classes supported use exactly the same logic that is available on tailwindcss.com/docs.

Responsive Design

Like TailwindCSS we also support Responsive Design media queries and this are the breakpoints supported:

  • sm: 64 spaces (640px)
  • md: 76 spaces (768px)
  • lg: 102 spaces (1024px)
  • xl: 128 spaces (1280px)
  • 2xl: 153 spaces (1536px)
render(<<<'HTML'
    <div class="bg-blue-500 sm:bg-red-600">
        If bg is blue is sm, if red > than sm breakpoint.
    </div>
HTML);

All the sizes for the CLI are based on Font Size 15.

HTML Elements Supported

All the elements have the capability to use the class attribute.

<div>

The <div> element can be used as a block type element.

Default Styles: block

render(<<<'HTML'
    <div>This is a div element.</div>
HTML);

<p>

The <p> element can be used as a paragraph.

Default Styles: block

render(<<<'HTML'
    <p>This is a paragraph.</p>
HTML);

<span>

The <span> element can be used as an inline text container.

render(<<<'HTML'
    <p>
        This is a CLI app built with <span class="text-green-300">Termwind</span>.
    </p>
HTML);

<a>

The <a> element can be used as a hyperlink. It allows to use the href attribute to open the link when clicked.

render(<<<'HTML'
    <p>
        This is a CLI app built with Termwind. <a href="/">Click here to open</a>
    </p>
HTML);

<b> and <strong>

The <b>and <strong> elements can be used to mark the text as bold.

Default Styles: font-bold

render(<<<'HTML'
    <p>
        This is a CLI app built with <b>Termwind</b>.
    </p>
HTML);

<i> and <em>

The <i> and <em> elements can be used to mark the text as italic.

Default Styles: italic

render(<<<'HTML'
    <p>
        This is a CLI app built with <i>Termwind</i>.
    </p>
HTML);

<s>

The <s> element can be used to add a line through the text.

Default Styles: line-through

render(<<<'HTML'
    <p>
        This is a CLI app built with <s>Termwind</s>.
    </p>
HTML);

<br>

The <br> element can be used to do a line break.

render(<<<'HTML'
    <p>
        This is a CLI <br>
        app built with Termwind.
    </p>
HTML);

<ul>

The <ul> element can be used for an unordered list. It can only accept <li> elements as childs, if there is another element provided it will throw an InvalidChild exception.

Default Styles: block, list-disc

render(<<<'HTML'
    <ul>
        <li>Item 1</li>
        <li>Item 2</li>
    </ul>
HTML);

<ol>

The <ol> element can be used for an ordered list. It can only accept <li> elements as childs, if there is another element provided it will throw an InvalidChild exception.

Default Styles: block, list-decimal

render(<<<'HTML'
    <ol>
        <li>Item 1</li>
        <li>Item 2</li>
    </ol>
HTML);

<li>

The <li> element can be used as a list item. It should only be used as a child of <ul> and <ol> elements.

Default Styles: block, list-decimal

render(<<<'HTML'
    <ul>
        <li>Item 1</li>
    </ul>
HTML);

<dl>

The <dl> element can be used for a description list. It can only accept <dt> or <dd> elements as childs, if there is another element provided it will throw an InvalidChild exception.

Default Styles: block

render(<<<'HTML'
    <dl>
        <dt>๐Ÿƒ Termwind</dt>
        <dd>Give your CLI apps a unique look</dd>
    </dl>
HTML);

<dt>

The <dt> element can be used as a description title. It should only be used as a child of <dl> elements.

Default Styles: block, font-bold

render(<<<'HTML'
    <dl>
        <dt>๐Ÿƒ Termwind</dt>
    </dl>
HTML);

<dd>

The <dd> element can be used as a description title. It should only be used as a child of <dl> elements.

Default Styles: block, ml-4

render(<<<'HTML'
    <dl>
        <dd>Give your CLI apps a unique look</dd>
    </dl>
HTML);

<hr>

The <hr> element can be used as a horizontal line.

render(<<<'HTML'
    <div>
        <div>๐Ÿƒ Termwind</div>
        <hr>
        <p>Give your CLI apps a unique look</p>
    </div>
HTML);

<table>

The <table> element can have columns and rows.

render(<<<'HTML'
    <table>
        <thead>
            <tr>
                <th>Task</th>
                <th>Status</th>
            </tr>
        </thead>
        <tr>
            <th>Termwind</th>
            <td>โœ“ Done</td>
        </tr>
    </table>
HTML);

<pre>

The <pre> element can be used as preformatted text.

render(<<<'HTML'
    <pre>
        Text in a pre element
        it preserves
        both      spaces and
        line breaks
    </pre>
HTML);

<code>

The <code> element can be used as code highlighter. It accepts line and start-line attributes.

render(<<<'HTML'
    <code line="22" start-line="20">
        try {
            throw new \Exception('Something went wrong');
        } catch (\Throwable $e) {
            report($e);
        }
    </code>
HTML);

Termwind is an open-sourced software licensed under the MIT license.

termwind's People

Contributors

2bj avatar abenerd avatar adamgaskins avatar amirsadeghi1 avatar ash-jc-allen avatar butschster avatar caneco avatar devacse avatar fabio-ivona avatar freekmurze avatar grahamcampbell avatar hosmelq avatar ju5t avatar krsriq avatar lakuapik avatar lukeraymonddowning avatar mabar avatar madshadow avatar marcreichel avatar nunofmmarques avatar nunomaduro avatar opuu avatar ryangjchandler avatar sebdesign avatar shahlin avatar tenios avatar thecrypticace avatar wendelladriel avatar xico2k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

termwind's Issues

Add support for using the user's terminal's theme colors

Modern terminals allow users to configure a "theme", which is 16 predefined colors that work well together, and with the terminal background.

image
A theme in iTerm2

Most command line binaries use these 16 colors, so the output looks good in every theme. Here's msgcat output in a light and dark terminal theme:

image
image

It would be awesome to make use of these in Termwind! That's the main thing keeping me from using it currently, since it feels less professional to show colors that may clash with the background (e.g. some people use a Solarized Light theme). I'm thinking something like text-ansi-red / bg-ansi-red for the class names?

[Bug] Console output does not affect `--no-ansi` option

Hi,

coming from a different project, which uses termwind to style command output: TomasVotruba/lines#35 (comment)

It's a symfony command, which uses build in options for coloring console output (or leave it as it is).

Using termwind as styling leads to ignoring the --no-ansi option.

Screenshot 2023-09-08 at 09 43 00

The screenshot shows the output, which shows ansi colors. That the colors are coliding with my iTerm2 agnoster theme leads me to that problem, that --no-ansi is not working.

[bug] Empty spaces between two elements

Hi guys!

Let's imagine two situations

Fist
Two elements, each on a new line

<div>
    <span class="px-1">hello</span>
    <span class="px-1">world</span>
</div>

Second
Two element on one line with space

<div>
    <span class="px-1">hello</span> <span class="px-1">world</span>
</div>

And what behavior we should expect on each case. I suggest the following behavior

In the first case we can remove empty space

&nbsp;hello&nbsp;&nbsp;world&nbsp;

In the second case we can keep space

&nbsp;hello&nbsp;&nbsp;&nbsp;world&nbsp;

Wrong behavior with node text content trimming.

There is a promlem with content trimming at this line https://github.com/nunomaduro/termwind/blob/master/src/HtmlRenderer.php#L69

For example, when we use strong element inside div then a space between Hello and world will be deleted because of trim function.

<p class="bg-red text-color-white">Hello <strong>world</strong></p>

The best solution is to use ltrim

I prepared a test for this problem

it('renders the element inside another element', function () {
    $html = parse('<div>Hello <strong>world</strong></div>');
    expect($html)->toBe("Hello \e[1mworld\e[0m");
});

Missing after the last line space when inheriting the width on more of more than three lines.

Now termwind can inherit width on two lines like:

termwind/tests/render.php

Lines 213 to 222 in 9c030e6

it('can inherit width on multiple lines', function () {
$html = parse(<<<'HTML'
<div class="w-10">
<div class="w-full bg-red">AAAAAAAAAA</div>
<div class="w-full bg-blue">BBBBBBBBBB</div>
</div>
HTML);
expect($html)->toBe("<bg=red>AAAAAAAAAA</>\n<bg=blue>BBBBBBBBBB</>");
});

But if add more than three lines, it will be missing after the last line space.

This unit test is failed:

$html = parse(<<<'HTML'
    <div class="w-10">
        <div class="w-full bg-red">AAA</div>
        <div class="w-full bg-blue">BBB</div>
        <div class="w-full bg-yellow">CCC</div>
    </div>
HTML);

// this is expected
expect($html)->toBe("<bg=red>AAA       </>\n<bg=blue>BBB       </>\n<bg=yellow>CCC       </>");

// // this is actual
// expect($html)->toBe("<bg=red>AAA       </>\n<bg=blue>BBB       </>\n<bg=yellow>CCC</>");

Elements with classes that apply escape codes do not work with classes that manipulate the content

Since #52 was merged, classes like font-bold italic underline line-through invisible are wrapping the content of the element with escape codes.

But classes like uppercase, truncate, snacecase are transforming the content of the element.

So when these classes are combined, e.g. font-bold uppercase, the escape codes will be capitalized which breaks them.
Also, if the classes are set in reverse order, e.g. uppercase font-bold this does not happen because the classes are applied in the order they appear (it should not).

E.g. <div class="font-bold uppercase">text</div> renders <bg=default;options=>\e[1MTEXT\e[0M</> instead of <bg=default;options=>\e[1mTEXT\e[0m</>.

Add function to just return string output instead of echoing it.

TL;DR: Would you be ok with an added function, maybe something like asString or something that just returns the final formatted string instead of echoing it (like render)?

I created a function similar to Laravel prompts task in CraftCms that shows either a check or an x depending on whether the task completed or not. However what I ran into was needing to know how many actual lines are output to the terminal, so I could move the cursor up that many lines and replace the text with an appended checkmark.

I ended up just directly using the HtmlRender class like so to accomplish what I needed to.

$html = (new HtmlRenderer())->parse('<div>hi!</div>')->toString();
// count the lines
// replace the line with an appended check or x.

It's marked as internal and crossed out in my ide however. Not a huge deal, but I think just having a function similar to render that just does the above would be a nice QoL improvement. So instead if people needed the raw string for whatever reason they could do

$string = asString('<div>hi!</div>');

instead of having to code dive.

I don't mind doing the pull request if you're ok with this.

Flex with padding

Heyho,

when using flex to render columns besided each other and then applying padding to each of the boxes causes a weird result.

Working, without padding

        render(<<<HTML
            <div class="flex mt-1 justify-evenly">
                <span class="flex-1 bg-green-100">
                    Today:
                </span>
                <span class="flex-1 bg-green-200">
                    Tomorrow:
                </span>
            </div>
        HTML);

CleanShot 2022-11-20 at 02 41 23


But when applying padding to the boxes they are not properly aligned anymore:

        render(<<<HTML
            <div class="flex mt-1 justify-evenly">
                <span class="flex-1 bg-green-100 p-1">
                    Today:
                </span>
                <span class="flex-1 bg-green-200 p-1">
                    Tomorrow:
                </span>
            </div>
        HTML);

CleanShot 2022-11-20 at 02 41 34

Did I something wrong? I will try to look into the library to figure it out, but maybe I'm just using it wrong ๐Ÿ˜… Thanks for the awesome library!

when <p> label with background style disorder

I found that my will take effect on the blank line, and this blank line will be applied with the background color, resulting in style confusion.

render(<<<'HTML'
    <div class="mx-2 my-1 space-y-1">

        <div class="bg-red"><p>xcccccccccccccccccccccccccccccccccccccccccccccccc</p></div>

    </div>
HTML);

image
If this is a BUG, I am willing to fix it, but I may need some guidance.

Missing styles for unknown elements

When HtmlRenerder detects element for given tag and it doesn't find it, it uses a default element (https://github.com/nunomaduro/termwind/blob/master/src/HtmlRenderer.php#L86). I think, default element should take styles.

Here is an example where you can see the problem.

it('renders the element inside another element', function () {
    $html = parse('<p class="bg-red text-color-white">Hello <strong>world</strong></p>');
    expect($html)->toBe("Hello \e[1mworld\e[0m");
});

Overwrite previous render

I'm working on this table with progress for specific items. This all works fine and well, but when using terminal clear and repainting it there is a lot of flickering in the terminal. Is there a suggested way to overwrite a previous render?

image

Incorrect spaces count of East Asian characters.

I using the Laravel's alert and two columns components, If enter the English it will works fine:

termwind-1

But if enter East Asian characters such as full-width characters (such as Chinese or Japanese) it will show incorrect spaces:

termwind-2
termwind-3

HTML

I read your post on Twitter about using the span()-method as a way to render lines. I feel a bit sad that it has been changed already. I hope to make a case to at least make line() available aside any HTML-tags. And link instead of a.

  1. If you go through some of the bash/zsh manuals for commands like echo, grep, awk and others there is no mention of a span, a div or an a-tag. Every manual calls it a line, not a div.
  2. It's command LINE interface. Although the README calls it a command-span application these days :)
  3. It's not a span if it has a line break (again, a line). It's a block element. But why bother with semantics? It's a line, after all.
  4. HTML elements are too opinionated.

Now that we're on the subject. You've also mentioned including h1. I personally don't like that. The command line doesn't know or care about headings. I would argue that if you need a heading, you'd extend line (wouldn't a class for it make more sense?) and give it all its classes to be a header.

All grumpiness aside. The idea of using Tailwind colours (or any type of colour) is awesome. Oh, yea. Another small feature request: the Color enum should probably be configurable :)

No matter what you decide, this is still a cool package that's going to be really useful.

Line-wrapped / nested elements don't behave as expected

Would like to use in a few more advanced scenarios, but there's a few cases where line-wrapping and nesting elements cause different behaviors from what I'd expect in HTML:

Line automatically wrapping example

<div class="m-1 p-1 bg-gray w-35">
    Lorem ipsum dolor, sit amet consectetur adipisicing elit.
</div>

image

Nested elements with padding example

<div class="w-64 bg-gray p-1">
    <span class="w-1/2 bg-red mr-1 p-1">
        Left
    </span>

    <span class="w-1/2 bg-red p-1">
        Right
    </span>
</div>

image

Thanks again for this project!

Support for borders?

I think something like this would be quite cool.

<div class="p-4 border-green-500">
   Hello World!
</div>
โ•ญโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚                  โ”‚
โ”‚   Hello World!   โ”‚
โ”‚                  โ”‚
โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ

Table renderer

It would be great to render tables from HTML

Something like this

<table style="box">
    <thead>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td><div class="width-5 px-4">4</div></td>
            <td rowspan="2">9</td>
            <td>6</td>
        </tr>
        <tr>
            <td class="width-10">7</td>
            <td colspan="2"><div>4</div></td>
        </tr>
    </tbody>
</table>

To this

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”
โ”‚ 1             โ”‚ 2 โ”‚ 3 โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ค
โ”‚     4         โ”‚ 9 โ”‚ 6 โ”‚
โ”‚ 7             โ”‚   โ”‚ 4 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”˜

I scetched a concept of TableRenderer

<?php
declare(strict_types=1);

namespace Termwind\Html;

use DOMNode;
use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Helper\TableCell;
use Symfony\Component\Console\Output\BufferedOutput;
use Termwind\Components\Element;
use Termwind\HtmlRenderer;
use function Termwind\div;

final class TableRenderer
{
    private Table $table;
    private BufferedOutput $output;
    private string $styles;

    public function __construct(DOMNode $node)
    {
        $this->output = new BufferedOutput();
        $this->table = new Table($this->output);

        $style = $node->getAttribute('style');
        $this->styles = $node->getAttribute('class');

        if (!empty($style)) {
            $this->table->setStyle($style);
        }

        $this->convert($node);
    }

    private function convert(DOMNode $node)
    {
        foreach ($node->childNodes as $child) {
            if ($child->nodeName === 'thead') {
                $this->parseHeader($child);
            }

            if ($child->nodeName === 'tbody') {
                $this->parseBody($child);
            }

            if ($child->nodeName === 'tr') {
                foreach ($this->parseRow($child) as $row) {
                    $this->table->addRow($row);
                }
            }
        }
    }

    private function parseHeader(DOMNode $node)
    {
        foreach ($node->childNodes as $child) {
            if ($child->nodeName === 'tr') {
                foreach ($this->parseRow($child) as $row) {
                    $this->table->setHeaders($row);
                }
            }
        }
    }

    private function parseBody(DOMNode $node)
    {
        foreach ($node->childNodes as $child) {
            if ($child->nodeName === 'tr') {
                foreach ($this->parseRow($child) as $row) {
                    $this->table->addRow($row);
                }
            }
        }
    }

    private function parseRow(DOMNode $node): \Iterator
    {
        $row = [];

        foreach ($node->childNodes as $child) {
            if ($child->nodeName === 'th' || $child->nodeName === 'td') {
                $row[] = new TableCell(
                    (string)(new HtmlRenderer())->parse($child->ownerDocument->saveXML($child)),
                    [
                        'colspan' => max((int)$child->getAttribute('colspan'), 1),
                        'rowspan' => max((int)$child->getAttribute('rowspan'), 1),
                    ]
                );
            }
        }

        if ($row !== []) {
            yield $row;
        }
    }

    public function render(): Element
    {
        $this->table->render();

        return div($this->output->fetch(), $this->styles);
    }
}

And changes for HtmlRenderer

    ...

    /**
     * Convert a tree of DOM nodes to a tree of termwind elements.
     */
    private function convert(DOMNode $node): Components\Element|string
    {
        ...

        if ($node->nodeName === 'table') {
            return (new TableRenderer($node))->render();
        }

        ...
    }
    ...

I hope my sketch will be a good starting point for better solution with ability to use background colors and text colors in a table cell.

Thank you for an amazing package. I want to use it in my project, but I need tables as well.

Is there a way to have a default answer for the ask() methods?

Hello there,

Thank you so much for this amazing package. I am sorry to create and issue as this is more of a question.

Would it be possible to have a default answer for the ask() method? Something "a la" Symfony\Component\Console\Question\ConfirmationQuestion; where the second param (I believe optional) is the default aswer in case the user press the 'return' key.

Let me know.

All the best

Eliott

Update the Readme

The $message variable is undefined.

And call to undefined method bgColor() . Its defined as bg(). Either update the readme or change the method name

Add line break after div element

I thinks it's a wrong behavior with div elements.

Content of every div element should be on a new line.

<div>
    <div>text text</div>
    <div>text text</div>
</div>

Should render

text text
text text

Now it looks like

text texttext text

Render unicode entities

I love the output, except that it doesn't render unicode entities like (&check;). Are you planning to add support for that?

Fatal Error when running schedule:work

Hello ๐Ÿ‘‹

I'm using this package as part of Laravel Zero. Within my application, If I run schedule:work, it'll start successfully but then sometimes after ~10 seconds, fail with:

Symfony\Component\ErrorHandler\Error\FatalError: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes)

Looking at the error in our Sentry instance, the error seems to be in /vendor/nunomaduro/termwind/src/ValueObjects/Styles.php and is:

public function with(array $properties): self
{
    $this->properties = array_replace_recursive($this->properties, $properties);
    return $this;
}

As an additional note, we've not actually done anything with Termwind in the application. The only Termwind usage I can see is in the default InspireCommand class, but that has the schedule commented out so it's not even included when running schedule:work.

I'd appreciate someone looking into this, if you need any more information, let me know!

Thanks

Styles are not applied on iterm

Hello everyone

I didn't know whether to create this issue in this repository or in the Laravel repository. I have created the issue here since in the latest version of Laravel this package is used under the hood for the refreshed UI.

New Laravel commands don't render properly when using iterm, for example, the new php artisan about command:

Iterm:
Captura de Pantalla 2022-07-20 a las 10 40 37

Terminal:
Captura de Pantalla 2022-07-20 a las 10 41 28

Is there something I have to configure beforehand or am I missing something?

Thanks a lot

Disable output during tests

Maybe it's a dumb question, but I didn't find any solutions.

Is it possible to disable termwind output when tests are running?
Let's say there is a simple command which outputs text with $this->info() and render():

    public function handle(): int
    {
        $this->info("Green text");
        render('<div class="text-red-500">Red text</div>');

        return self::SUCCESS;
    }

and a simple test (Pest):

<?php

use App\Console\Commands\TestCommand;

use function Pest\Laravel\artisan;

it('returns a successful response', function () {
    artisan(TestCommand::class)
        ->assertOk();
});

When tests are running, "Green text" will not show, while "Red text" will.
I think both should not be rendered while tests are running.

What's the best way to make render() behave like standard output functions?

Thank you

Add support for pre tag

I have a following text and I want to print it as is without trimming.

# Introduction

The body of your message.

Thanks,
Laravel

ยฉ 2021 Laravel. All rights reserved.

It would be great to have <pre> element

Supported Colors Listing

Really awesome project, thanks for creating it. I had a quick question related to colors.

According to the docs we should be able to use any of the colors within Tailwind CSS, but it seems like not all variations or colors are supported? I do not remember running into this issue during other previous projects which used Termwind. I am wondering if there is another issue at play here.

Are the specific supported colors related to the terminal software you are using? Bash vs. ZSH? or maybe other terminal settings/plugins/themes? Or is there a more refined list of colors which Termwind supports that is not as extensive as everything available via Tailwind.

Required the support of branching and looping

Can you please provide support for loops and conditional statements like native PHP?

image

This is my code and I want a list of all directories to be printed with for loop.

image

Let me know how can I help.

Thanks.

unexpected '|' in Functions.php on line 17

I'm using spatie/laravel-health which requires nunomaduro/termwind 1.1 but receveing the following error.

I can not figure out why. It's not happening in dev environment but when I try and deploy to staging environment on Laravel Forge.

PHP Parse error: syntax error, unexpected '|', expecting variable (T_VARIABLE) in /home/user/site/vendor/nunomaduro/termwind/src/Functions.php on line 17

There is a pipe on line 17 but not sure on usage, I presume its used correctly?

function renderUsing(OutputInterface|null $renderer): void

Styling issues with \e[0m

Check this example

image

I am trying to use green-text color for the entire div. But after font-bold it resets all the styles.

image

Its because of \e[0m. Why are we resetting all the stylings?

Check this gist => https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797

To reset each style it has its own number (i.e bold=> \e[22m, italic => \e[23m ...)

Is there any specific reason for going with \e[0m?

This is after I used the style specific ending sequences instead of \e[0m.

image

Injecting variable when rendering a template

Hi,

I was recently trying to use Termwind with Laravel Zero to make a small cli/php app.

After trying to print the first layout with Termwind, I can't get my head around the possibility to inject a variable in the template before rendering it.

Either I miss something, either I'm in a specific case (Laravel Zero, which has striped a lot of functionality of Laravel).

  1. First attempt is with a nowdoc and trying different way to print write a variable but with no luck
use function Termwind\render;

$test = 'hello';
render(<<<'HTML'
        <div>
            <div class="px-1 bg-green-600">test : </div>
            <div class="ml-1">
                {$test}<br>
                $test<br>
                ${test}<br>
                {{ $test }}<br>
                <?php $test; <br>
            </div>
        </div>
HTML);

With this as an output :

 test : 
 {$test}
$test
${test}
{{ $test }}
  1. Second attempt : I tried to use the view helper with a blade file. Since in Laravel Zero there's no resources folder with blade files, I created thoses folder resources/views and the file termwind.blade.php with the template with the previous template.
    I found out that the view helper is present but there was no ViewServiceProvider.
    'providers' => [
        App\Providers\AppServiceProvider::class,
        Illuminate\View\ViewServiceProvider::class,
    ],

This was a good try but Laravel Zero just have a subset of laravel/framework. Just the Foundation folder not the View one.
I could try to pull the whole laravel/framework but I think it's not the way to go.
Here was the code I wanted to try :

use function Termwind\render;

$test = 'hello';
render(view('termwind', compact('test')));
  1. The last attempt : I've seen another way to build the HTML template with chained methods :
use function Termwind\div;
use function Termwind\render;

$test = 'hello';
div([
    div('test', 'px-1 bg-green-600'),
    div($test, 'ml-1'),
])->render();

I get the following error :

 Error

  Call to undefined function Termwind\div()

I am actually now out of idea to try this. Any help appreciated!
I'm using :

  • php 8.1.2
  • nunomaduro/termwind : v1.4.3
  • laravel-zero/framework : v8.9.1
  • laravel-zero/foundation : v8.81.0

Thanks for reading me and I'm hoping this can help others that want to use this wonderful tool you created !

[Feature] Ability to extend HTML renderer

There is only one way to increase amount of elements in termwind - Add PRs with new features.

But sometimes requires an ability to extend HtmlRenderer for specific project.

Something like this

HtmlRenderer::extend('code', static function(\DOMNode $node): Raw {
    $highlighter = new Highlighter();

    $line = (int) $node->getAttribute('line');

    $html = array_reduce(
        iterator_to_array($node->childNodes),
        static fn(string $html, \DOMNode $child) => $html .= $child->ownerDocument->saveXML($child),
        ''
    );

    $html = html_entity_decode($html);

    return Termwind::raw(
        $highlighter->highlight(html_entity_decode($html), $line)
    );
});

As you understood, this package fits me on 100%. I have a pet project where one of the features is rendering debug output into a terminal and I have a lot of legacy code I'm trying to move to this package.

Feature: parse html using a `render` function

At this point, we already have an HTML-like API where you can do stuff like so:

use function Termwind\{div};

div('Hello World', 'ml-2')->render(); // renders "  Hello World" on the console

The goal of this issue to create a new function with the name render that accepts an HTML string and renders the console output like so:

use function Termwind\{render};

render('<div class="m-2">Hello World</div>'); // renders "  Hello World" on the console

Using `passthru()` produces jumbled output

Hello, fantastic work on this library. The new Artisan improvements are great.

Problem - Using passthru() produces jumbled output.

POC - Any Laravel console command that calls passthru to call commands, so they do not share the main process.

public function handle()
{
    passthru('composer update');
}

Using Laravel 9.20 - Output normal

image

Using Laravel 9.21 - Actual output

image

Using Laravel 9.21 - Expected output

image

Error when running `vendor:publish` in laravel

When running vendor:publish in Laravel following error is thrown

  Which provider or tag's files would you like to publish?

   Error 

  Call to undefined function Termwind\ValueObjects\mb_strimwidth()

  at vendor/nunomaduro/termwind/src/ValueObjects/Styles.php:1053
    1049โ–•      */
    1050โ–•     private static function trimText(string $text, int $width): string
    1051โ–•     {
    1052โ–•         preg_match_all(self::STYLING_REGEX, $text, $matches, PREG_OFFSET_CAPTURE);
  โžœ 1053โ–•         $text = rtrim(mb_strimwidth(preg_replace(self::STYLING_REGEX, '', $text) ?? '', 0, $width, '', 'UTF-8'));
    1054โ–• 
    1055โ–•         foreach ($matches[0] ?? [] as [$part, $index]) {
    1056โ–•             $text = substr($text, 0, $index).$part.substr($text, $index, null);
    1057โ–•         }

      +4 vendor frames 
  5   [internal]:0
      Termwind\Components\Element::__toString()

      +32 vendor frames 
  38  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

Color is not applied on windows terminal with wsl.

Default colors are not being applied to html element on windows terminal (using windows sub system for linux).
Also the parser trying to parse special characters as html, in this case <== gives an warning.

require __DIR__ . '/vendor/autoload.php';

use function Termwind\{render};

// single line html...
render('<div class="p-1 bg-green-300">Termwind</div><span class="text-red-200"><== this was supposed to be green.<span>');

Output

image

[Feature] Code highlighter

What do you think if use Highlighter from nunomaduro/collision for rendering code snippets.

Something like this

<code line="18" start-line="14">
  /** @test */
  function sentryReport()
  {
    try {
      throw new \Exception('Something went wrong');
    } catch (\Throwable $e) {
      report($e);
    }
  }
</code>

Will output

      14โ–•     /** @test */
      15โ–•     function sentryReport()
      16โ–•     {
      17โ–•         try {
  โžœ  18โ–•             throw new \Exception('Something went wrong');
      19โ–•         } catch (\Throwable $e) {
      20โ–•             report($e);
      21โ–•         }
      22โ–•     }

Testing an Artisan command using render()

Is it possible to test an Artisan command's console output (via expectsOutput, doesntExpectOutput) which is using, for example, render() function?

Artisan command foo:

...
render('bar'); // even with no styling/HTML
...

Unit PEST:

it('does not show output foo string', function () {
    $this->artisan('foo')
        ->doesntExpectOutput('bar');
});

Apparently, there is no difference between using render('bar') or not: the test always passes.
Am I doing anything wrong?

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.