diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000000..42cfd773e461 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +/lib +/docs +defaultConfig.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000000..ff4ccca480a9 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,26 @@ +{ + "env": { + "jest": true + }, + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module" + }, + "extends": ["eslint-config-postcss", "prettier"], + "plugins": ["prettier"], + "rules": { + "prettier/prettier": [ + "error", + { + "semi": false, + "singleQuote": true, + "printWidth": 100, + "tabWidth": 2, + "useTabs": false, + "trailingComma": "es5", + "bracketSpacing": true, + "parser": "flow" + } + ] + } +} diff --git a/.github/COMMUNITY_GUIDELINES.md b/.github/COMMUNITY_GUIDELINES.md new file mode 100644 index 000000000000..7ce9543c5173 --- /dev/null +++ b/.github/COMMUNITY_GUIDELINES.md @@ -0,0 +1,10 @@ +# Tailwind CSS Community Guidelines + +The following community guidelines are based on [The Ruby Community Conduct Guidelines](https://www.ruby-lang.org/en/conduct/). + +This document provides community guidelines for a respectful, productive, and collaborative place for any person who is willing to contribute to the Tailwind CSS project. It applies to all “collaborative space”, which is defined as community communications channels (such as mailing lists, submitted patches, commit comments, etc.). + +- Participants will be tolerant of opposing views. +- Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. +- When interpreting the words and actions of others, participants should always assume good intentions. +- Behaviour which can be reasonably considered harassment will not be tolerated. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000000..1f88972b5232 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,85 @@ +# Contributing + +Thanks for your interest in contributing to Tailwind CSS! Please take a moment to review this document **before submitting a pull request**. + +## Pull requests + +**Please ask first before starting work on any significant new features.** + +It's never a fun experience to have your pull request declined after investing a lot of time and effort into a new feature. To avoid this from happening, we request that contributors create [an issue](https://github.com/tailwindcss/tailwindcss/issues) to first discuss any significant new features. This includes things like adding new utilities, creating new at-rules, or adding new component examples to the documentation. + +## Coding standards + +Our code formatting rules are defined in [.eslintrc](https://github.com/tailwindcss/tailwindcss/blob/master/.eslintrc). You can check your code against these standards by running: + +```sh +npm run style +``` + +To automatically fix any style violations in your code, you can run: + +```sh +npm run style --fix +``` + +## Running tests + +You can run the test suite using the following commands: + +```sh +npm test +``` + +Please ensure that the tests are passing when submitting a pull request. If you're adding new features to Tailwind, please include tests. + +## Building the documentation + +Tailwind uses the [Jigsaw](http://jigsaw.tighten.co/) static site generator for its documentation. Here is how you can generate the documentation locally: + +1. Go to your Tailwind folder + + ```sh + cd tailwindcss + ``` + +2. Install JS dependencies + + ```sh + npm install + ``` + +3. Transpile the source code + + ```sh + npm run prepare + ``` + +4. Go to docs folder + + ```sh + cd docs + ``` + +5. Install PHP dependencies for docs (requires Composer: https://getcomposer.org) + + ```sh + composer install + ``` + +6. Install JS dependencies for docs + + ```sh + npm install + ``` + +7. Run the build to generate the static site + + ```sh + npm run dev + ``` + +8. View the static site at `/tailwind/docs/build_local`, or you can run the Jigsaw server: + + ```sh + ./vendor/bin/jigsaw serve + ``` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000000..ce7fafb97dc0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,11 @@ + diff --git a/.gitignore b/.gitignore index b070f0117d72..60fd5ef5ade3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -/dist /node_modules /lib /example diff --git a/README.md b/README.md index 45c03f47a101..e6ceb335752a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,21 @@ -# Tailwind CSS +

+
+ A utility-first CSS framework for rapidly building custom user interfaces. +

-[ ![Codeship Status for tailwindcss/tailwindcss](https://app.codeship.com/projects/cdd4ad20-a319-0135-c87c-02251d502cd2/status?branch=master)](https://app.codeship.com/projects/254859) +

+ Codeship Status + Total Downloads + Latest Release + License +

-A utility-first CSS framework for rapidly building custom user interfaces. +------ ## Documentation -For full documentation, visit: https://tailwindcss.com/ +For full documentation, visit [tailwindcss.com](https://tailwindcss.com/). + +## Contributing + +If you're interested in contributing to Tailwind CSS, please read our [contributing docs](https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md) **before submitting a pull request**. diff --git a/__tests__/applyAtRule.test.js b/__tests__/applyAtRule.test.js index 1829a3f9dd0a..90bc8e0cfd64 100644 --- a/__tests__/applyAtRule.test.js +++ b/__tests__/applyAtRule.test.js @@ -2,20 +2,20 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteClassApplyAtRules' function run(input, opts = () => {}) { - return postcss([plugin(opts)]).process(input) + return postcss([plugin(opts)]).process(input) } test("it copies a class's declarations into itself", () => { - const output = '.a { color: red; } .b { color: red; }' + const output = '.a { color: red; } .b { color: red; }' - return run('.a { color: red; } .b { @apply .a; }').then(result => { - expect(result.css).toEqual(output) - expect(result.warnings().length).toBe(0) - }) + return run('.a { color: red; } .b { @apply .a; }').then(result => { + expect(result.css).toEqual(output) + expect(result.warnings().length).toBe(0) + }) }) test("it doesn't copy a media query definition into itself", () => { - const output = `.a { + const output = `.a { color: red; } @@ -27,8 +27,8 @@ test("it doesn't copy a media query definition into itself", () => { color: red; }` - return run( - `.a { + return run( + `.a { color: red; } @@ -38,15 +38,15 @@ test("it doesn't copy a media query definition into itself", () => { .b { @apply .a; - }`) - .then(result => { - expect(result.css).toEqual(output) - expect(result.warnings().length).toBe(0) - }) + }` + ).then(result => { + expect(result.css).toEqual(output) + expect(result.warnings().length).toBe(0) + }) }) test('it fails if the class does not exist', () => { - run('.b { @apply .a; }').catch(error => { - expect(error.reason).toEqual('No .a class found.') - }) + run('.b { @apply .a; }').catch(error => { + expect(error.reason).toEqual('No .a class found.') + }) }) diff --git a/__tests__/configFunction.test.js b/__tests__/configFunction.test.js index 11f93876ad1b..32d2a5a3d906 100644 --- a/__tests__/configFunction.test.js +++ b/__tests__/configFunction.test.js @@ -5,7 +5,7 @@ function run(input, opts = {}) { return postcss([plugin(() => opts)]).process(input) } -test("it looks up values in the config using dot notation", () => { +test('it looks up values in the config using dot notation', () => { const input = ` .banana { color: config('colors.yellow'); } ` @@ -17,14 +17,14 @@ test("it looks up values in the config using dot notation", () => { return run(input, { colors: { yellow: '#f7cc50', - } + }, }).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) }) -test("quotes are optional around the lookup path", () => { +test('quotes are optional around the lookup path', () => { const input = ` .banana { color: config(colors.yellow); } ` @@ -36,14 +36,14 @@ test("quotes are optional around the lookup path", () => { return run(input, { colors: { yellow: '#f7cc50', - } + }, }).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) }) -test("a default value can be provided", () => { +test('a default value can be provided', () => { const input = ` .cookieMonster { color: config('colors.blue', #0000ff); } ` @@ -55,14 +55,14 @@ test("a default value can be provided", () => { return run(input, { colors: { yellow: '#f7cc50', - } + }, }).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) }) }) -test("quotes are preserved around default values", () => { +test('quotes are preserved around default values', () => { const input = ` .heading { font-family: config('fonts.sans', "Helvetica Neue"); } ` @@ -73,8 +73,8 @@ test("quotes are preserved around default values", () => { return run(input, { fonts: { - serif: "Constantia", - } + serif: 'Constantia', + }, }).then(result => { expect(result.css).toEqual(output) expect(result.warnings().length).toBe(0) diff --git a/__tests__/defineClass.test.js b/__tests__/defineClass.test.js index 9d14286d5ca4..cb8fe09b5f07 100644 --- a/__tests__/defineClass.test.js +++ b/__tests__/defineClass.test.js @@ -1,6 +1,3 @@ -import postcss from 'postcss' -import fs from 'fs' -import _ from 'lodash' import c from '../src/util/collapseWhitespace' import defineClass from '../src/util/defineClass' @@ -8,21 +5,23 @@ import defineClass from '../src/util/defineClass' * Tests */ it('creates a proper single-word class with rules', () => { - let output = defineClass('flex', {display: 'flex'}) + let output = defineClass('flex', { display: 'flex' }) expect(c(output.toString())).toEqual(`.flex { display: flex }`) }) it('does not modify the case of selector names', () => { - let output = defineClass('inlineBlock', {display: 'inline-block'}) + let output = defineClass('inlineBlock', { display: 'inline-block' }) expect(c(output.toString())).toEqual(`.inlineBlock { display: inline-block }`) }) it('does not modify the case of property names', () => { - let output = defineClass('smooth', {'-webkit-font-smoothing': 'antialiased'}) + let output = defineClass('smooth', { + '-webkit-font-smoothing': 'antialiased', + }) expect(c(output.toString())).toEqual(`.smooth { -webkit-font-smoothing: antialiased }`) }) it('escapes non-standard characters in selectors', () => { - let output = defineClass('w-1/4', {'width': '25%'}) + let output = defineClass('w-1/4', { width: '25%' }) expect(c(output.toString())).toEqual(`.w-1\\/4 { width: 25% }`) }) diff --git a/__tests__/defineClasses.test.js b/__tests__/defineClasses.test.js index c33bdc9af95f..4c60874403df 100644 --- a/__tests__/defineClasses.test.js +++ b/__tests__/defineClasses.test.js @@ -1,6 +1,3 @@ -import postcss from 'postcss' -import fs from 'fs' -import _ from 'lodash' import c from '../src/util/collapseWhitespace' import defineClasses from '../src/util/defineClasses' @@ -9,7 +6,7 @@ import defineClasses from '../src/util/defineClasses' */ it('it generates a set of helper classes from a config', () => { let output = defineClasses({ - 'flex': { + flex: { display: 'flex', }, 'inline-flex': { diff --git a/__tests__/fixtures/tailwind-output.css b/__tests__/fixtures/tailwind-output.css index 8bdb4a3d730e..012fa8425ea5 100644 --- a/__tests__/fixtures/tailwind-output.css +++ b/__tests__/fixtures/tailwind-output.css @@ -548,7 +548,8 @@ textarea { font-family: inherit; } -input::placeholder { +input::placeholder, +textarea::placeholder { color: inherit; opacity: .5; } diff --git a/__tests__/focusableAtRule.test.js b/__tests__/focusableAtRule.test.js index 04fb8ba64f8c..2241105cf770 100644 --- a/__tests__/focusableAtRule.test.js +++ b/__tests__/focusableAtRule.test.js @@ -5,7 +5,7 @@ function run(input, opts = () => {}) { return postcss([plugin(opts)]).process(input) } -test("it adds a focusable variant to each nested class definition", () => { +test('it adds a focusable variant to each nested class definition', () => { const input = ` @focusable { .banana { color: yellow; } diff --git a/__tests__/hoverableAtRule.test.js b/__tests__/hoverableAtRule.test.js index afcd5096f8df..b52d02ed485a 100644 --- a/__tests__/hoverableAtRule.test.js +++ b/__tests__/hoverableAtRule.test.js @@ -5,7 +5,7 @@ function run(input, opts = () => {}) { return postcss([plugin(opts)]).process(input) } -test("it adds a hoverable variant to each nested class definition", () => { +test('it adds a hoverable variant to each nested class definition', () => { const input = ` @hoverable { .banana { color: yellow; } diff --git a/__tests__/sanity.test.js b/__tests__/sanity.test.js index d452f62578e7..ece2537093cf 100644 --- a/__tests__/sanity.test.js +++ b/__tests__/sanity.test.js @@ -12,7 +12,10 @@ it('generates the right CSS', () => { return postcss([tailwind()]) .process(input) .then(result => { - const expected = fs.readFileSync(path.resolve(`${__dirname}/fixtures/tailwind-output.css`), 'utf8') + const expected = fs.readFileSync( + path.resolve(`${__dirname}/fixtures/tailwind-output.css`), + 'utf8' + ) expect(result.css).toBe(expected) }) diff --git a/css/preflight.css b/css/preflight.css index ee20e96c7dcc..1d333f2b9c51 100644 --- a/css/preflight.css +++ b/css/preflight.css @@ -536,7 +536,7 @@ svg { fill: currentColor; } button, input, optgroup, select, textarea { font-family: inherit; } -input::placeholder { +input::placeholder, textarea::placeholder { color: inherit; opacity: .5; } diff --git a/dist/.gitignore b/dist/.gitignore new file mode 100644 index 000000000000..d6b7ef32c847 --- /dev/null +++ b/dist/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/docs/source/_assets/less/docsearch.less b/docs/source/_assets/less/docsearch.less new file mode 100644 index 000000000000..50084efc0961 --- /dev/null +++ b/docs/source/_assets/less/docsearch.less @@ -0,0 +1,37 @@ +.algolia-autocomplete { + width: 100% !important; + + [class^="ds-dataset-"] { + .algolia-docsearch-suggestion--text { + .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 rgba(68, 168, 179,.8); + } + } + + .algolia-docsearch-suggestion--highlight { + color: config('colors.tailwind-teal'); + background: rgba(68, 168, 179, .1); + } + } + + @media (max-width: config('screens.md')) { + .ds-dropdown-menu { + width: 100% !important; + max-width: 100% !important; + min-width: 0 !important; + } + + .algolia-docsearch-suggestion--subcategory-column { + display: none !important; + } + + .algolia-docsearch-suggestion--content { + width: 100% !important; + padding: 0 !important; + + &:before { + display: none !important; + } + } + } +} diff --git a/docs/source/_assets/less/main.less b/docs/source/_assets/less/main.less index 744a9e7eb4e4..5e52af6d872e 100644 --- a/docs/source/_assets/less/main.less +++ b/docs/source/_assets/less/main.less @@ -18,6 +18,7 @@ ul { @apply .list-reset; } +@import "docsearch"; @import "prism"; @import "markdown"; diff --git a/docs/source/_layouts/documentation.blade.php b/docs/source/_layouts/documentation.blade.php index a84a0a1abfb4..3bfbc82fd16e 100644 --- a/docs/source/_layouts/documentation.blade.php +++ b/docs/source/_layouts/documentation.blade.php @@ -1,11 +1,17 @@ @extends('_layouts.master') @section('meta') + + + + + + @endsection @section('body')
-