Improve customizability and v3 color support (#216)

* Start scaffolding out components/modifiers

* WIP

* Updated pre-code and pre-bg colors

* WIP

* Add some notes

* WIP

* handle nested objects, e.g.: `@media`

* WIP

* simplify invert mode

* simplify base styles

* add `prose-XXX` variants

* update demo pages

* bump tailwind version

* mark insiders as a valid peer dependency

* bump next

* use package-lock.json file

* cleanup

* add more variants

* rename `rules` to `hr`

* update test snapshots

We probably want to look at other testing mechanisms here.

* cleanup index file

* improve API

* Simplify variants, add more element variants

* Refactor to use ::marker

* Tweak marker positions to work better across multiple browsers

* Simplify testing strategy

Co-authored-by: sschoger <[email protected]>
Co-authored-by: Robin Malfait <[email protected]>
This commit is contained in:
Adam Wathan
2021-11-07 10:45:07 -05:00
committed by GitHub
co-authored by sschoger Robin Malfait
parent 284f6409f1
commit 2d25ef39f6
16 changed files with 31508 additions and 41179 deletions
+1 -1
View File
@@ -28,7 +28,7 @@ jobs:
uses: actions/cache@v2
with:
path: node_modules
key: nodeModules-${{ hashFiles('**/yarn.lock') }}-${{ matrix.node-version }}
key: nodeModules-${{ hashFiles('**/package-lock.json') }}-${{ matrix.node-version }}
restore-keys: |
nodeModules-
- name: Install dependencies
+1 -2
View File
@@ -1,5 +1,4 @@
.next
node_modules
package-lock.json
/demo/out
coverage/
coverage/
+60
View File
@@ -0,0 +1,60 @@
<p className="lead">
Until now, trying to style an article, document, or blog post with Tailwind has been a very
tedious task.
</p>
The `@tailwindcss/typography` plugin is our attempt to give you what you _actually_ want, without any of the downsides of doing something stupid like disabling our base styles.
> Why is Tailwind removing the default styles on my `h1` elements? How do I disable this? What do you mean I lose all the other base styles too?
<div className="not-prose">
<h2>Shouldn't be colored</h2>
</div>
```html
<p>
But a recent study shows that the celebrated appetizer may be linked to a series of rabies cases
springing up around the country.
</p>
```
For more information about how to use the plugin and the features it includes, [read the documentation](https://github.com/tailwindcss/typography/blob/master/README.md).
---
## This is a heading
1. We want everything to look good out of the box.
2. Really just the first reason, that's the whole point of the plugin.
3. Here's a third pretend reason though a list with three items looks more realistic than a list with two items.
Now **I'm going to show you** an example of an unordered list to make sure that looks good, too:
- So here is the first item in this list.
- In this example we're keeping the items short.
- Later, we'll use longer, more complex list items.
Let's even style a table:
| Wrestler | Origin | Finisher |
| ----------------------- | ------------ | ------------------ |
| Bret "The Hitman" Hart | Calgary, AB | Sharpshooter |
| Stone Cold Steve Austin | Austin, TX | Stone Cold Stunner |
| Randy Savage | Sarasota, FL | Elbow Drop |
| Vader | Boulder, CO | Vader Bomb |
| Razor Ramon | Chuluota, FL | Razor's Edge |
Finally, a figure with a caption:
<figure>
<img
src="https://images.unsplash.com/photo-1556740758-90de374c12ad?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1000&h=500&q=80"
alt=""
/>
<figcaption>
Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of
classical Latin literature from 45 BC, making it over 2000 years old.
</figcaption>
</figure>
And that's the end of our little demo.
+2 -8
View File
@@ -1,12 +1,6 @@
import 'tailwindcss/tailwind.css'
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps } = this.props
return <Component {...pageProps} />
}
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
+24
View File
@@ -0,0 +1,24 @@
import Head from 'next/head'
import MarkdownSampleShort from '../components/MarkdownSampleShort.mdx'
export default function Index() {
return (
<div className="antialiased text-gray-900">
<Head>
<title>Tailwind CSS Typography</title>
</Head>
<div className="grid">
<div className="bg-white dark:bg-gray-900">
<article className="py-12 px-4 prose prose-gray dark:prose-invert mx-auto">
<h1>Are you happy now?</h1>
<MarkdownSampleShort />
</article>
</div>
</div>
</div>
)
}
export const config = {
unstable_runtimeJS: false,
}
+1 -1
View File
@@ -45,7 +45,7 @@ export default function Index() {
</a>
</div>
</div>
<div className="prose prose-sm sm:prose lg:prose-lg xl:prose-2xl mx-auto">
<div className="prose prose-sm sm:prose-base lg:prose-lg xl:prose-xl 2xl:prose-2xl mx-auto">
<MarkdownSample />
</div>
</div>
+176
View File
@@ -0,0 +1,176 @@
import Head from 'next/head'
import MarkdownSampleShort from '../components/MarkdownSampleShort.mdx'
export default function Index() {
return (
<div className="antialiased text-gray-900 py-12 pl-32 space-y-12">
<Head>
<title>Tailwind CSS Typography</title>
</Head>
<div className="relative">
<div className="absolute inset-0 flex prose prose-sm opacity-0">
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
</div>
<div className="relative prose prose-sm">
<h3>prose-sm</h3>
<p>It's important to cover all of these use cases for a few reasons:</p>
<ol>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
<li>
Here's a third pretend reason though a list with three items looks more realistic than
a list with two items.
</li>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
</ol>
<p>Now we're going to try out another header style.</p>
<ul>
<li>So here is the first item in this list.</li>
<li>In this example we're keeping the items short.</li>
<li>Later, we'll use longer, more complex list items.</li>
</ul>
</div>
</div>
<div className="relative">
<div className="absolute inset-0 flex prose prose-base opacity-0">
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
</div>
<div className="relative prose prose-base">
<h3>prose-base</h3>
<p>It's important to cover all of these use cases for a few reasons:</p>
<ol>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
<li>
Here's a third pretend reason though a list with three items looks more realistic than
a list with two items.
</li>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
</ol>
<p>Now we're going to try out another header style.</p>
<ul>
<li>So here is the first item in this list.</li>
<li>In this example we're keeping the items short.</li>
<li>Later, we'll use longer, more complex list items.</li>
</ul>
</div>
</div>
<div className="relative">
<div className="absolute inset-0 flex prose prose-lg opacity-0">
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
</div>
<div className="relative prose prose-lg">
<h3>prose-lg</h3>
<p>It's important to cover all of these use cases for a few reasons:</p>
<ol>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
<li>
Here's a third pretend reason though a list with three items looks more realistic than
a list with two items.
</li>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
</ol>
<p>Now we're going to try out another header style.</p>
<ul>
<li>So here is the first item in this list.</li>
<li>In this example we're keeping the items short.</li>
<li>Later, we'll use longer, more complex list items.</li>
</ul>
</div>
</div>
<div className="relative">
<div className="absolute inset-0 flex prose prose-xl opacity-0">
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
</div>
<div className="relative prose prose-xl">
<h3>prose-xl</h3>
<p>It's important to cover all of these use cases for a few reasons:</p>
<ol>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
<li>
Here's a third pretend reason though a list with three items looks more realistic than
a list with two items.
</li>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
</ol>
<p>Now we're going to try out another header style.</p>
<ul>
<li>So here is the first item in this list.</li>
<li>In this example we're keeping the items short.</li>
<li>Later, we'll use longer, more complex list items.</li>
</ul>
</div>
</div>
<div className="relative">
<div className="absolute inset-0 flex prose prose-2xl opacity-0">
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-200" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
<div className="border-l border-red-100" style={{ width: '1em' }}></div>
</div>
<div className="relative prose prose-2xl">
<h3>prose-2xl</h3>
<p>It's important to cover all of these use cases for a few reasons:</p>
<ol>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
<li>
Here's a third pretend reason though a list with three items looks more realistic than
a list with two items.
</li>
<li>We want everything to look good out of the box.</li>
<li>Really just the first reason, that's the whole point of the plugin.</li>
</ol>
<p>Now we're going to try out another header style.</p>
<ul>
<li>So here is the first item in this list.</li>
<li>In this example we're keeping the items short.</li>
<li>Later, we'll use longer, more complex list items.</li>
</ul>
</div>
</div>
</div>
)
}
export const config = {
unstable_runtimeJS: false,
}
+282
View File
@@ -0,0 +1,282 @@
import Head from 'next/head'
import MarkdownSampleShort from '../components/MarkdownSampleShort.mdx'
export default function Index() {
return (
<div className="antialiased text-gray-900">
<Head>
<title>Tailwind CSS Typography</title>
</Head>
<div className="grid grid-cols-2">
<div className="bg-white dark:bg-slate-900">
<article className="py-12 px-4 prose prose-slate prose-red dark:prose-invert mx-auto prose-headings:text-green-400">
<h1>Slate</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-slate-900">
<article className="py-12 px-4 prose prose-slate prose-invert mx-auto">
<h1>Slate</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-50">
<article className="py-12 px-4 prose prose-gray mx-auto">
<h1>Gray</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-gray prose-invert mx-auto">
<h1>Gray</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-zinc-50">
<article className="py-12 px-4 prose prose-zinc mx-auto">
<h1>Zinc</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-zinc-900">
<article className="py-12 px-4 prose prose-zinc prose-invert mx-auto">
<h1>Zinc</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-neutral-50">
<article className="py-12 px-4 prose prose-neutral mx-auto">
<h1>Neutral</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-neutral-900">
<article className="py-12 px-4 prose prose-neutral prose-invert mx-auto">
<h1>Neutral</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-stone-50">
<article className="py-12 px-4 prose prose-stone mx-auto">
<h1>Stone</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-stone-900">
<article className="py-12 px-4 prose prose-stone prose-invert mx-auto">
<h1>Stone</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-red mx-auto">
<h1>Red Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-red prose-invert mx-auto">
<h1>Red Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-orange mx-auto">
<h1>Orange Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-orange prose-invert mx-auto">
<h1>Orange Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-amber mx-auto">
<h1>Amber Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-amber prose-invert mx-auto">
<h1>Amber Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-yellow mx-auto">
<h1>Yellow Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-yellow prose-invert mx-auto">
<h1>Yellow Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-lime mx-auto">
<h1>Lime Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-lime prose-invert mx-auto">
<h1>Lime Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-green mx-auto">
<h1>Green Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-green prose-invert mx-auto">
<h1>Green Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-emerald mx-auto">
<h1>Emerald Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-emerald prose-invert mx-auto">
<h1>Emerald Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-teal mx-auto">
<h1>Teal Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-teal prose-invert mx-auto">
<h1>Teal Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-cyan mx-auto">
<h1>Cyan Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-cyan prose-invert mx-auto">
<h1>Cyan Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-sky mx-auto">
<h1>Sky Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-sky prose-invert mx-auto">
<h1>Sky Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-blue mx-auto">
<h1>Blue Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-blue prose-invert mx-auto">
<h1>Blue Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-indigo mx-auto">
<h1>Indigo Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-indigo prose-invert mx-auto">
<h1>Indigo Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-violet mx-auto">
<h1>Violet Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-violet prose-invert mx-auto">
<h1>Violet Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-purple mx-auto">
<h1>Purple Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-purple prose-invert mx-auto">
<h1>Purple Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-fuchsia mx-auto">
<h1>Fuchsia Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-fuchsia prose-invert mx-auto">
<h1>Fuchsia Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-pink mx-auto">
<h1>Pink Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-pink prose-invert mx-auto">
<h1>Pink Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-white">
<article className="py-12 px-4 prose prose-rose mx-auto">
<h1>Rose Links</h1>
<MarkdownSampleShort />
</article>
</div>
<div className="bg-gray-900">
<article className="py-12 px-4 prose prose-rose prose-invert mx-auto">
<h1>Rose Links</h1>
<MarkdownSampleShort />
</article>
</div>
</div>
</div>
)
}
export const config = {
unstable_runtimeJS: false,
}
+64
View File
@@ -0,0 +1,64 @@
import Head from 'next/head'
import MarkdownSampleShort from '../components/MarkdownSampleShort.mdx'
export default function Variants() {
return (
<div className="antialiased text-gray-900 md:bg-gray-900 lg:bg-white">
<Head>
<title>Tailwind CSS Typography</title>
</Head>
<div className="px-4 py-10 max-w-3xl mx-auto sm:px-6 sm:py-12 lg:max-w-4xl lg:py-16 lg:px-8 xl:max-w-6xl">
<article>
<h1 className="sr-only">Tailwind CSS Typography</h1>
<div className="space-y-10 sm:space-y-12 lg:space-y-20 xl:space-y-24">
<div className="space-y-10 sm:space-y-0 sm:flex sm:items-center sm:justify-between">
<svg className="h-6 sm:h-8" fill="none" viewBox="0 0 297 24">
<path
fill="#16BDCA"
fillRule="evenodd"
d="M19.418.523c-5.178 0-8.415 2.589-9.71 7.767 1.943-2.59 4.208-3.56 6.797-2.913 1.477.37 2.533 1.44 3.702 2.627 1.903 1.933 4.107 4.17 8.92 4.17 5.178 0 8.414-2.59 9.708-7.768-1.941 2.59-4.207 3.56-6.796 2.913-1.477-.37-2.533-1.441-3.702-2.628C26.434 2.76 24.23.523 19.417.523zm-9.71 11.65c-5.177 0-8.413 2.59-9.708 7.767 1.942-2.589 4.207-3.56 6.796-2.913 1.477.37 2.533 1.441 3.702 2.628 1.904 1.932 4.107 4.169 8.92 4.169 5.178 0 8.414-2.59 9.709-7.767-1.942 2.589-4.208 3.56-6.797 2.912-1.477-.369-2.533-1.44-3.701-2.627-1.904-1.932-4.108-4.169-8.92-4.169z"
clipRule="evenodd"
/>
<path
fill="#1a202c"
d="M59.31 8.962v-2.79h-3.328V2.414l-2.898.858v2.898h-2.468v2.79h2.468v6.44c0 3.489 1.771 4.723 6.225 4.186v-2.602c-2.2.107-3.327.134-3.327-1.584v-6.44h3.327zM72.013 6.171v1.905c-1.02-1.395-2.603-2.254-4.696-2.254-3.649 0-6.68 3.06-6.68 7.057 0 3.971 3.031 7.057 6.68 7.057 2.093 0 3.676-.859 4.696-2.28v1.931h2.897V6.171h-2.897zm-4.24 11.001c-2.415 0-4.24-1.797-4.24-4.293 0-2.495 1.825-4.293 4.24-4.293s4.24 1.798 4.24 4.293c0 2.496-1.825 4.293-4.24 4.293zM79.737 4.159c1.02 0 1.852-.859 1.852-1.851 0-1.02-.832-1.852-1.852-1.852s-1.851.832-1.851 1.852c0 .992.832 1.85 1.851 1.85zm-1.449 15.428h2.898V6.171h-2.898v13.416zM84.55 19.587h2.898V0h-2.897v19.587zM106.268 6.171l-2.629 9.257-2.791-9.257h-2.763l-2.818 9.257-2.602-9.257h-3.06l4.213 13.416h2.844l2.818-9.042 2.79 9.042h2.844l4.213-13.416h-3.059zM112.91 4.159c1.019 0 1.851-.859 1.851-1.851 0-1.02-.832-1.852-1.851-1.852-1.02 0-1.852.832-1.852 1.852 0 .992.832 1.85 1.852 1.85zm-1.449 15.428h2.898V6.171h-2.898v13.416zM124.78 5.822c-1.824 0-3.273.671-4.159 2.067V6.17h-2.898v13.416h2.898v-7.19c0-2.738 1.503-3.865 3.408-3.865 1.824 0 3.005 1.074 3.005 3.113v7.942h2.898V11.35c0-3.488-2.147-5.528-5.152-5.528zM143.677.805v7.271c-1.019-1.395-2.602-2.254-4.695-2.254-3.649 0-6.681 3.06-6.681 7.057 0 3.971 3.032 7.057 6.681 7.057 2.093 0 3.676-.859 4.695-2.28v1.931h2.898V.805h-2.898zm-4.239 16.367c-2.415 0-4.239-1.797-4.239-4.293 0-2.495 1.824-4.293 4.239-4.293s4.239 1.798 4.239 4.293c0 2.496-1.824 4.293-4.239 4.293z"
/>
<path
fill="#16BDCA"
d="M161.544 5.748h-10.182v2.61h3.717v11.23h2.728V8.357h3.737v-2.61zM175.997 5.748h-3.084l-3.005 5.773-3.006-5.773h-3.084l4.725 8.442v5.397h2.709V14.19l4.745-8.442zM184.461 5.748h-5.16v13.84h2.728V15.04h2.432c2.669 0 4.725-2.056 4.725-4.646s-2.056-4.646-4.725-4.646zm0 6.741h-2.432V8.3h2.432c1.166 0 2.016.889 2.016 2.095 0 1.186-.85 2.095-2.016 2.095zM199.387 19.864c3.994 0 7.196-3.163 7.196-7.197 0-4.053-3.202-7.196-7.196-7.196-3.994 0-7.177 3.143-7.177 7.196 0 4.034 3.183 7.197 7.177 7.197zm0-2.67c-2.511 0-4.468-1.877-4.468-4.527 0-2.669 1.957-4.547 4.468-4.547s4.468 1.878 4.468 4.547c0 2.65-1.957 4.528-4.468 4.528zM224.061 12.153h-6.94v2.412h4.191c-.474 1.582-1.858 2.63-4.033 2.63-2.886 0-4.725-1.938-4.725-4.508 0-2.63 1.898-4.567 4.527-4.567 1.681 0 3.085.81 3.717 1.918l2.333-1.345c-1.166-1.897-3.4-3.222-6.03-3.222-4.132 0-7.256 3.203-7.256 7.216 0 3.954 3.085 7.177 7.414 7.177 3.974 0 6.802-2.65 6.802-6.643v-1.068zM235.57 19.587h2.946l-3.064-5.22c1.581-.73 2.669-2.293 2.669-4.033 0-2.53-2.057-4.586-4.607-4.586h-5.536v13.84h2.729v-4.805h2.076l2.787 4.804zm-4.863-11.289h2.807c1.028 0 1.878.89 1.878 2.037 0 1.146-.85 2.056-1.878 2.056h-2.807V8.298zM250.996 19.587h2.966l-4.864-13.84h-3.38l-4.844 13.84h2.946l.83-2.491h5.516l.83 2.491zm-5.476-5.041l1.898-5.655 1.898 5.655h-3.796zM262.443 5.748h-5.16v13.84h2.728V15.04h2.432c2.669 0 4.725-2.056 4.725-4.646s-2.056-4.646-4.725-4.646zm0 6.741h-2.432V8.3h2.432c1.167 0 2.017.889 2.017 2.095 0 1.186-.85 2.095-2.017 2.095zM278.79 5.748v5.496h-5.14V5.748h-2.728v13.84h2.728v-5.734h5.14v5.733h2.709V5.747h-2.709zM297 5.748h-3.084l-3.005 5.773-3.006-5.773h-3.084l4.725 8.442v5.397h2.709V14.19L297 5.748z"
/>
</svg>
<div>
<a
href="https://github.com/tailwindcss/typography"
className="inline-flex items-center py-2 px-3 space-x-2 rounded-md bg-gray-800 text-gray-300 text-sm leading-5 font-medium shadow-lg hover:bg-gray-700 transition ease-in-out duration-100"
>
<svg className="h-5 w-5 text-gray-500" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 0C4.477 0 0 4.484 0 10.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0110 4.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.203 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.942.359.31.678.921.678 1.856 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0020 10.017C20 4.484 15.522 0 10 0z"
clipRule="evenodd"
/>
</svg>
<span>View on GitHub</span>
</a>
</div>
</div>
<div
className="prose
marker:prose-ol:text-red-500
prose-bullets:bg-red-500
marker:prose-ul:text-red-500
prose-img:rounded-xl prose-img:shadow-xl prose-pre:bg-blue-900 prose-pre:text-pink-200 hover:prose-pre:font-bold prose-headings:text-pink-800 sm:prose-base md:prose-invert lg:prose-slate"
>
<MarkdownSampleShort />
</div>
</div>
</article>
</div>
</div>
)
}
+23 -1
View File
@@ -7,7 +7,29 @@ module.exports = {
mdx: (content) => mdx.sync(content),
},
},
theme: {},
theme: {
extend: {
colors: {
red: { 1000: '#530F0F' },
orange: { 1000: '#521C0B' },
amber: { 1000: '#54240B' },
yellow: { 1000: '#4D280A' },
lime: { 1000: '#213708' },
green: { 1000: '#0F3D23' },
emerald: { 1000: '#02392C' },
teal: { 1000: '#073937' },
cyan: { 1000: '#09364A' },
sky: { 1000: '#072F49' },
blue: { 1000: '#17275C' },
indigo: { 1000: '#1F1C53' },
violet: { 1000: '#2F1265' },
purple: { 1000: '#3D1061' },
fuchsia: { 1000: '#4C0C4F' },
pink: { 1000: '#4E0B26' },
rose: { 1000: '#4E071B' },
},
},
},
variants: {},
plugins: [require('../src/index.js')],
}
+150
View File
@@ -0,0 +1,150 @@
const prettier = require('prettier')
const { diff } = require('jest-diff')
function format(input) {
return prettier.format(input, {
parser: 'css',
printWidth: 100,
})
}
expect.extend({
// Compare two CSS strings with all whitespace removed
// This is probably naive but it's fast and works well enough.
toMatchCss(received, argument) {
function stripped(str) {
return str.replace(/\s/g, '').replace(/;/g, '')
}
const options = {
comment: 'stripped(received) === stripped(argument)',
isNot: this.isNot,
promise: this.promise,
}
const pass = stripped(received) === stripped(argument)
const message = pass
? () => {
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(format(received))}\n` +
`Received: ${this.utils.printReceived(format(argument))}`
)
}
: () => {
const actual = format(received)
const expected = format(argument)
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
toIncludeCss(received, argument) {
function stripped(str) {
return str.replace(/\s/g, '').replace(/;/g, '')
}
const options = {
comment: 'stripped(received).includes(stripped(argument))',
isNot: this.isNot,
promise: this.promise,
}
const pass = stripped(received).includes(stripped(argument))
const message = pass
? () => {
return (
this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(format(received))}\n` +
`Received: ${this.utils.printReceived(format(argument))}`
)
}
: () => {
const actual = format(received)
const expected = format(argument)
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toIncludeCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
})
expect.extend({
// Compare two CSS strings with all whitespace removed
// This is probably naive but it's fast and works well enough.
toMatchFormattedCss(received, argument) {
function format(input) {
return prettier.format(input.replace(/\n/g, ''), {
parser: 'css',
printWidth: 100,
})
}
const options = {
comment: 'stripped(received) === stripped(argument)',
isNot: this.isNot,
promise: this.promise,
}
let formattedReceived = format(received)
let formattedArgument = format(argument)
const pass = formattedReceived === formattedArgument
const message = pass
? () => {
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(formattedReceived)}\n` +
`Received: ${this.utils.printReceived(formattedArgument)}`
)
}
: () => {
const actual = formattedReceived
const expected = formattedArgument
const diffString = diff(expected, actual, {
expand: this.expand,
})
return (
this.utils.matcherHint('toMatchCss', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(actual)}`)
)
}
return { actual: received, message, pass }
},
})
+29137
View File
File diff suppressed because it is too large Load Diff
+9 -3
View File
@@ -26,7 +26,7 @@
"start": "next start demo"
},
"peerDependencies": {
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1"
"tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || insiders"
},
"devDependencies": {
"@mdx-js/loader": "^1.0.19",
@@ -38,18 +38,24 @@
"dedent": "^0.7.0",
"highlight.js": "^10.4.1",
"jest": "^26.6.1",
"next": "^11.1.2",
"jest-diff": "^27.3.1",
"next": "^12.0.1",
"postcss": "^8.2.3",
"prettier": "^2.1.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"snapshot-diff": "^0.8.1",
"tailwindcss": "next"
"tailwindcss": "^0.0.0-insiders.ec1f7b0"
},
"dependencies": {
"lodash.castarray": "^4.4.0",
"lodash.isplainobject": "^4.0.6",
"lodash.merge": "^4.6.2",
"lodash.uniq": "^4.5.0"
},
"jest": {
"setupFilesAfterEnv": [
"<rootDir>/jest/customMatchers.js"
]
}
}
+78 -44
View File
@@ -1,9 +1,7 @@
const plugin = require('tailwindcss/plugin')
const merge = require('lodash.merge')
const castArray = require('lodash.castarray')
const uniq = require('lodash.uniq')
const styles = require('./styles')
const { isUsableColor } = require('./utils')
const computed = {
// Reserved for future "magic properties", for example:
@@ -22,11 +20,18 @@ function inWhere(selector, { className, prefix }) {
if (selector.endsWith('::after')) {
if (selector.startsWith('>')) {
return `> :where(${selector.slice(2, -8)}):not(:where([class~="${prefixedNot}"] *))::before`
return `> :where(${selector.slice(2, -7)}):not(:where([class~="${prefixedNot}"] *))::after`
}
return `:where(${selector.slice(0, -7)}):not(:where([class~="${prefixedNot}"] *))::after`
}
if (selector.endsWith('::marker')) {
if (selector.startsWith('>')) {
return `> :where(${selector.slice(2, -8)}):not(:where([class~="${prefixedNot}"] *))::marker`
}
return `:where(${selector.slice(0, -8)}):not(:where([class~="${prefixedNot}"] *))::marker`
}
if (selector.startsWith('>')) {
return `> :where(${selector.slice(2)}):not(:where([class~="${prefixedNot}"] *))`
}
@@ -34,7 +39,28 @@ function inWhere(selector, { className, prefix }) {
return `:where(${selector}):not(:where([class~="${prefixedNot}"] *))`
}
function isObject(value) {
return typeof value === 'object' && value !== null
}
function configToCss(config = {}, { target, className, prefix }) {
function updateSelector(k, v) {
if (target === 'legacy') {
return [k, v]
}
if (isObject(v)) {
let nested = Object.values(v).some(isObject)
if (nested) {
return [k, Object.fromEntries(Object.entries(v).map(([k, v]) => updateSelector(k, v)))]
}
return [inWhere(k, { className, prefix }), v]
}
return [k, v]
}
return Object.fromEntries(
Object.entries(
merge(
@@ -44,57 +70,65 @@ function configToCss(config = {}, { target, className, prefix }) {
.map((key) => computed[key](config[key])),
...castArray(config.css || {})
)
).map(([k, v]) => {
if (target === 'legacy') {
return [k, v]
}
if (typeof v == 'object' && v.constructor == Object) {
return [inWhere(k, { className, prefix }), v]
}
return [k, v]
})
).map(([k, v]) => updateSelector(k, v))
)
}
module.exports = plugin.withOptions(
({ modifiers, className = 'prose', target = 'modern' } = {}) => {
return function ({ addComponents, theme, variants, prefix }) {
const DEFAULT_MODIFIERS = [
'DEFAULT',
'sm',
'lg',
'xl',
'2xl',
...Object.entries(theme('colors'))
.filter(([color, values]) => {
return isUsableColor(color, values)
})
.map(([color]) => color),
]
modifiers = modifiers === undefined ? DEFAULT_MODIFIERS : modifiers
const config = theme('typography')
({ className = 'prose', target = 'modern' } = {}) => {
return function ({ addVariant, addComponents, theme, prefix }) {
let modifiers = theme('typography')
const all = uniq([
'DEFAULT',
...modifiers,
...Object.keys(config).filter((modifier) => !DEFAULT_MODIFIERS.includes(modifier)),
])
let options = { className, prefix }
for (let [name, selector = name] of [
['headings', 'h1, h2, h3, h4, th'],
['lead', '[class~="lead"]'],
['h1'],
['h2'],
['h3'],
['h4'],
['p'],
['a'],
['blockquote'],
['figure'],
['figcaption'],
['strong'],
['em'],
['code'],
['pre'],
['ol'],
['ul'],
['li'],
['table'],
['thead'],
['tr'],
['th'],
['td'],
['img'],
['video'],
['hr'],
]) {
addVariant(`${className}-${name}`, `& :is(${inWhere(selector, options)})`)
}
addComponents(
all.map((modifier) => ({
Object.keys(modifiers).map((modifier) => ({
[modifier === 'DEFAULT' ? `.${className}` : `.${className}-${modifier}`]: configToCss(
config[modifier],
{ target, className, prefix }
modifiers[modifier],
{
target,
className,
prefix,
}
),
})),
variants('typography')
}))
)
}
},
() => ({
theme: { typography: styles },
variants: { typography: ['responsive'] },
})
() => {
return {
theme: { typography: styles },
}
}
)
+775 -40697
View File
File diff suppressed because it is too large Load Diff
+725 -422
View File
File diff suppressed because it is too large Load Diff