kiliman / tailwindui-crawler

tailwindui-crawler downloads the component HTML files locally
MIT License
763 stars 95 forks source link

Optionally parse HTML to create React-ready output #5

Closed stevecastaneda closed 4 years ago

stevecastaneda commented 4 years ago

I've integrated @robinmalfait's React find/replace tool for TUI code.

https://gist.github.com/RobinMalfait/a90e8651196c273dfa51eec0f43e1676

Would you be interested in a PR to merge this? I've added an env variable to enable it, and it's still optional in index.js.

kiliman commented 4 years ago

Ha. Were going to have a whole community around building tools for Tailwind UI.

I've actually working on a transformer process which allows you to plug in different functions in the pipeline. This way you can simply add a new exported function and the crawler will call it with the current HTML and you return the updated HTML which is piped to the next transformer.

Once I push that, feel free to include your function as a new transformer.

stevecastaneda commented 4 years ago

Nice! Sounds like a plan. Will watch for the next release.

kiliman commented 4 years ago

Here are some example transformers. I use the cheeriojs library that gives you a jQuery like API.

// addTailwindCss.js
const tui =
  '<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tailwindcss/ui@latest/dist/tailwind-ui.min.css">'

module.exports = function($) {
  // add stylesheets to <head/>
  $('head').append(tui)
}
// prefixSrc.js
module.exports = function($, { rootUrl }) {
  $('img').each((_, img) => {
    const $img = $(img)
    const src = $img.attr('src')
    const startsWithHttp = src.indexOf('http') === 0
    $img.attr('src', startsWithHttp ? src : `${rootUrl}${src}`)
  })
}
kiliman commented 4 years ago

Ok, so I have transformer pipeline working pretty well. Now the main decision is how to add them to your config.

Currently, I just added it to the .env files as another key/value pair (with the values being comma-delimited list of transformers).

TRANSFORMERS=addTailwindCss,prefixSrc,useInter

I want to create a transformer that allows you to add a prefix to the class names. However, that will require you to configure the prefix name.

I can do something like:

TRANSFORMERS=...,prefixClassNames
prefixClassNames-prefix=tw

Another option is to move away from .env files and use a config.json file.

{
  "transformers": [
    "addTailwindCss",
    "prefixSrc",
    "useInter",
    "prefixClassNames"
  ],
  "env": {
    "prefixClassNames": {
      "prefix": "tw"
    }
  }
}

Does anyone have a preference?

kiliman commented 4 years ago

So I created a transformer from that gist and it generated the following:

<div className="relative bg-gray-50 overflow-hidden">
  <div className="hidden sm:block sm:absolute sm:inset-y-0 sm:h-full sm:w-full">
    <div className="relative h-full max-w-screen-xl mx-auto">
      <svg className="absolute right-full transform translate-y-1/4 translate-x-1/4 lg:translate-x-1/2" width="404" height="784" fill="none" viewBox="0 0 404 784">
        <defs>
          <pattern id="f210dbf6-a58d-4871-961e-36d5016a0f49" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
            <rect x="0" y="0" width="4" height="4" className="text-gray-200" fill="currentColor"/>
          </pattern>
        </defs>
        <rect width="404" height="784" fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"/>
      </svg>
      <svg className="absolute left-full transform -translate-y-3/4 -translate-x-1/4 md:-translate-y-1/2 lg:-translate-x-1/2" width="404" height="784" fill="none" viewBox="0 0 404 784">
        <defs>
          <pattern id="5d0dd344-b041-4d26-bec4-8d33ea57ec9b" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
            <rect x="0" y="0" width="4" height="4" className="text-gray-200" fill="currentColor"/>
          </pattern>
        </defs>
        <rect width="404" height="784" fill="url(#5d0dd344-b041-4d26-bec4-8d33ea57ec9b)"/>
      </svg>
    </div>
  </div>

  <div data-todo-x-data="{ open: false }" className="relative pt-6 pb-12 sm:pb-16 md:pb-20 lg:pb-28 xl:pb-32">
    <div className="max-w-screen-xl mx-auto px-4 sm:px-6">
      <nav className="relative flex items-center justify-between sm:h-10 md:justify-center">
        <div className="flex items-center flex-1 md:absolute md:inset-y-0 md:left-0">
          <div className="flex items-center justify-between w-full md:w-auto">
            <a href="/">
              <img className="h-8 w-auto sm:h-10" src="https://tailwindui.com/img/logos/workflow-mark-on-white.svg" alt=""/>
            </a>
            <div className="-mr-2 flex items-center md:hidden">
              <button data-todo-at-click="open = true" type="button" className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out">
                <svg className="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 6h16M4 12h16M4 18h16"/>
                </svg>
              </button>
            </div>
          </div>
        </div>
        <div className="hidden md:block">
          <a href="/" className="font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Product</a>
          <a href="/" className="ml-10 font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Features</a>
          <a href="/" className="ml-10 font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Marketplace</a>
          <a href="/" className="ml-10 font-medium text-gray-500 hover:text-gray-900 focus:outline-none focus:text-gray-900 transition duration-150 ease-in-out">Company</a>
        </div>
        <div className="hidden md:absolute md:flex md:items-center md:justify-end md:inset-y-0 md:right-0">
          <span className="inline-flex rounded-md shadow">
            <a href="/" className="inline-flex items-center px-4 py-2 border border-transparent text-base leading-6 font-medium rounded-md text-indigo-600 bg-white hover:text-indigo-500 focus:outline-none focus:shadow-outline-blue active:bg-gray-50 active:text-indigo-700 transition duration-150 ease-in-out">
              Log in
            </a>
          </span>
        </div>
      </nav>
    </div>

    <div data-todo-x-show="open" style="display: none;" className="absolute top-0 inset-x-0 p-2 md:hidden">
      <div className="rounded-lg shadow-md transition transform origin-top-right" data-todo-x-show="open" data-todo-x-transition-enter="duration-150 ease-out" data-todo-x-transition-enter-start="opacity-0 scale-95" data-todo-x-transition-enter-end="opacity-100 scale-100" data-todo-x-transition-leave="duration-100 ease-in" data-todo-x-transition-leave-start="opacity-100 scale-100" data-todo-x-transition-leave-end="opacity-0 scale-95">
        <div className="rounded-lg bg-white shadow-xs overflow-hidden">
          <div className="px-5 pt-4 flex items-center justify-between">
            <div>
              <img className="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-mark-on-white.svg" alt=""/>
            </div>
            <div className="-mr-2">
              <button data-todo-at-click="open = false" type="button" className="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 focus:text-gray-500 transition duration-150 ease-in-out">
                <svg className="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12"/>
                </svg>
              </button>
            </div>
          </div>
          <div className="px-2 pt-2 pb-3">
            <a href="/" className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:text-gray-900 focus:bg-gray-50 transition duration-150 ease-in-out">Product</a>
            <a href="/" className="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:text-gray-900 focus:bg-gray-50 transition duration-150 ease-in-out">Features</a>
            <a href="/" className="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:text-gray-900 focus:bg-gray-50 transition duration-150 ease-in-out">Marketplace</a>
            <a href="/" className="mt-1 block px-3 py-2 rounded-md text-base font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:text-gray-900 focus:bg-gray-50 transition duration-150 ease-in-out">Company</a>
          </div>

...

Pretty cool.

stevecastaneda commented 4 years ago

Yup, that's it! But you might want to remove the code due to licensing restrictions.

No preference on how to set the options for the output, personally.

Edit: I don't recognize this from the output though. <pattern id="f210dbf6-a58d-4871-961e-36d5016a0f49" ...

kiliman commented 4 years ago

Not sure about the <pattern />... could be a side-effect of the cheerio HTML serialization.

kiliman commented 4 years ago

Just about finished with my transformer pipeline. I had to patch cheerios serializer to more closely match the HTML in TailwindUI so you wouldn't get a bunch of spurious changes.

Anyway, I looked into <pattern id="..."/> and it turns out it's in the original TUI code.

image

kiliman commented 4 years ago

v2.0 has been pushed with support for convertReact transformer.