├── .compositor
├── .gitignore
├── .prettierrc
├── docs
└── index.html
├── example
├── .compositor
├── app.pcss
├── compositor.config.js
├── fonts
│ ├── inter
│ │ ├── Inter-Bold.woff
│ │ ├── Inter-Bold.woff2
│ │ ├── Inter-BoldItalic.woff
│ │ ├── Inter-BoldItalic.woff2
│ │ ├── Inter-Italic.woff
│ │ ├── Inter-Italic.woff2
│ │ ├── Inter-Regular.woff
│ │ ├── Inter-Regular.woff2
│ │ ├── Inter-SemiBold.woff
│ │ ├── Inter-SemiBold.woff2
│ │ ├── Inter-SemiBoldItalic.woff
│ │ ├── Inter-SemiBoldItalic.woff2
│ │ └── Inter-italic.var.woff2
│ └── playfair
│ │ ├── PlayfairDisplay-Black.ttf
│ │ ├── PlayfairDisplay-BlackItalic.ttf
│ │ ├── PlayfairDisplay-Bold.ttf
│ │ ├── PlayfairDisplay-BoldItalic.ttf
│ │ ├── PlayfairDisplay-ExtraBold.ttf
│ │ ├── PlayfairDisplay-ExtraBoldItalic.ttf
│ │ ├── PlayfairDisplay-Italic.ttf
│ │ ├── PlayfairDisplay-Medium.ttf
│ │ ├── PlayfairDisplay-MediumItalic.ttf
│ │ ├── PlayfairDisplay-Regular.ttf
│ │ ├── PlayfairDisplay-SemiBold.ttf
│ │ └── PlayfairDisplay-SemiBoldItalic.ttf
├── index.html
├── package.json
├── postcss.config.js
└── tailwind.config.js
├── jest.config.base.js
├── jest.config.js
├── jest.setup.js
├── lerna.json
├── licence.md
├── notes.md
├── package.json
├── plugin
├── images
│ ├── baseline-type.gif
│ ├── typeset-differences.gif
│ └── vertical-metrics.png
├── jest.config.js
├── package.json
├── readme.md
├── rollup.config.js
├── src
│ ├── __tests__
│ │ ├── __mocks__
│ │ │ └── styleMock.js
│ │ ├── __snapshots__
│ │ │ ├── compositor.file.test.ts.snap
│ │ │ └── plugin.test.ts.snap
│ │ ├── compositor.file.test.ts
│ │ ├── fixtures
│ │ │ ├── compositor.config.js
│ │ │ ├── inter
│ │ │ │ └── Inter-Regular.woff
│ │ │ ├── playfair
│ │ │ │ ├── PlayfairDisplay-Black.ttf
│ │ │ │ ├── PlayfairDisplay-BlackItalic.ttf
│ │ │ │ ├── PlayfairDisplay-Bold.ttf
│ │ │ │ ├── PlayfairDisplay-BoldItalic.ttf
│ │ │ │ ├── PlayfairDisplay-ExtraBold.ttf
│ │ │ │ ├── PlayfairDisplay-ExtraBoldItalic.ttf
│ │ │ │ ├── PlayfairDisplay-Italic.ttf
│ │ │ │ ├── PlayfairDisplay-Medium.ttf
│ │ │ │ ├── PlayfairDisplay-MediumItalic.ttf
│ │ │ │ ├── PlayfairDisplay-Regular.ttf
│ │ │ │ ├── PlayfairDisplay-SemiBold.ttf
│ │ │ │ └── PlayfairDisplay-SemiBoldItalic.ttf
│ │ │ └── tailwind.config.js
│ │ ├── plugin.test.ts
│ │ └── transform.test.ts
│ ├── create-background-styles.ts
│ ├── create-matrix-styles.ts
│ ├── create-measure-styles.ts
│ ├── create-rhythm-styles.ts
│ ├── create-text-styles.ts
│ ├── default-config.ts
│ ├── get-font-metrics.ts
│ ├── index.ts
│ ├── styles
│ │ ├── index.ts
│ │ ├── style-background.ts
│ │ ├── style-font-family.ts
│ │ ├── style-matrix.ts
│ │ ├── style-measure.ts
│ │ ├── style-owl.ts
│ │ └── style-text.ts
│ ├── tailwind-plugin-compositor.ts
│ ├── theme-compositor.ts
│ ├── types.ts
│ └── utils
│ │ ├── baseline-scale-to-px.ts
│ │ ├── baseline-scale-to-rem.ts
│ │ ├── get-rhythm.ts
│ │ ├── get.ts
│ │ ├── index.ts
│ │ ├── is.ts
│ │ ├── mem.ts
│ │ ├── merge.ts
│ │ ├── noop.ts
│ │ ├── px-scale-to-rem.ts
│ │ ├── px-to-rem.ts
│ │ ├── scale-add-suffix.ts
│ │ ├── strip-css.ts
│ │ └── uuid.ts
├── tsconfig.json
└── types.d.ts
├── readme.md
├── scripts
└── rollup.base.js
├── tsconfig.json
├── tsconfig.settings.json
├── tslint.json
└── yarn.lock
/.compositor:
--------------------------------------------------------------------------------
1 | [{"familyName":"Inter","upm":2816,"xHeight":1536,"capHeight":2048,"lineGap":0,"ascent":2728,"descent":-680,"weight":400,"italic":false,"key":"sans-400"}]
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dummy
2 |
3 | # Logs
4 | logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.pid.lock
14 | *.seed
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (http://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | **/node_modules
40 |
41 | # Typescript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # dev
63 | **/dev/
64 | **/**/dev/
65 |
66 |
67 | # dist
68 | **/dist/
69 | **/**/dist/
70 |
71 | # gatsby
72 | **/**/public
73 | **/**/.cache
74 |
75 | # Storybook
76 | storybook-static
77 |
78 |
79 |
80 | # Mac files
81 | .DS_Store
82 |
83 | # Cache files
84 | .cache
85 | **/**/.cache
86 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "endOfLine": "lf",
3 | "semi": true,
4 | "trailingComma": "es5",
5 | "tabWidth": 4,
6 | "useTabs": true,
7 | "singleQuote": true,
8 | "bracketSpacing": true,
9 | "arrowParens": "avoid"
10 | }
11 |
--------------------------------------------------------------------------------
/docs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/example/.compositor:
--------------------------------------------------------------------------------
1 | [{"key":"serif","familyName":"Playfair Display","fallback":"serif","upm":1000,"xHeight":514,"capHeight":708,"ascent":1082,"descent":-251,"lineGap":0,"weight":400,"italic":true},{"familyName":"Inter","upm":2816,"xHeight":1536,"capHeight":2048,"lineGap":0,"ascent":2728,"descent":-680,"weight":400,"italic":false,"key":"sans","fallback":"sans-serif"}]
--------------------------------------------------------------------------------
/example/app.pcss:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/example/compositor.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 |
3 | // root font size
4 | const root = 16;
5 |
6 | // baseline grid row height in px
7 | const baseline = 8;
8 |
9 | // max leading count
10 | const leading = 4;
11 |
12 | const matrix = 12;
13 |
14 | // type scale in px
15 | const type = [
16 | 12,
17 | 14,
18 | 16,
19 | 18,
20 | 20,
21 | 24,
22 | 28,
23 | 32,
24 | 36,
25 | 42,
26 | 48,
27 | 54,
28 | 60,
29 | 68,
30 | 76,
31 | 84,
32 | 92,
33 | ];
34 |
35 | // rhythm scale in baseline units
36 | const rhythm = [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14];
37 | rhythm.px = '1px';
38 | rhythm.half = 0.5;
39 |
40 | // measure scale in characters unit
41 | const measure = [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65];
42 | measure.auto = 'auto';
43 |
44 | // font config
45 | const fonts = [
46 | {
47 | key: 'serif',
48 | familyName: 'Playfair Display',
49 | fallback: 'serif',
50 | upm: 1000,
51 | xHeight: 514,
52 | capHeight: 708,
53 | ascent: 1082,
54 | descent: -251,
55 | lineGap: 0,
56 | weight: 400,
57 | italic: true,
58 | },
59 | {
60 | key: 'sans',
61 | fallback: 'sans-serif',
62 | file: path.resolve('./fonts/inter/Inter-Regular.woff2'),
63 | },
64 | ];
65 |
66 | module.exports = {
67 | root,
68 | baseline,
69 | leading,
70 | matrix,
71 | type,
72 | rhythm,
73 | measure,
74 | fonts,
75 | options: {
76 | useRem: true,
77 | snap: true,
78 | type: true,
79 | rhythm: true,
80 | measure: true,
81 | matrix: true,
82 | xray: true,
83 | },
84 | };
85 |
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Bold.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Bold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Bold.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-BoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-BoldItalic.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-BoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-BoldItalic.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Italic.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Italic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Italic.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Regular.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-Regular.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-SemiBold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-SemiBold.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-SemiBold.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-SemiBold.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-SemiBoldItalic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-SemiBoldItalic.woff
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-SemiBoldItalic.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-SemiBoldItalic.woff2
--------------------------------------------------------------------------------
/example/fonts/inter/Inter-italic.var.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/inter/Inter-italic.var.woff2
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-Black.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-BlackItalic.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-Bold.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-BoldItalic.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-ExtraBold.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-Italic.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-Medium.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-MediumItalic.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-Regular.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-SemiBold.ttf
--------------------------------------------------------------------------------
/example/fonts/playfair/PlayfairDisplay-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/example/fonts/playfair/PlayfairDisplay-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Tailwind Compositor
6 |
7 |
8 |
12 |
16 |
17 |
18 |
19 |
20 |
21 |
Tailwind Compositor
22 |
23 | Amet et non nisi ex ex labore irure pariatur enim quis magna
24 | amet est esse. Dolore ad qui ea laboris labore non anim ad ipsum
25 | laborum est.
26 |
27 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "description": "",
4 | "private": true,
5 | "author": "Apostolos Christodoulou (@a7sc11u)",
6 | "license": "MIT",
7 | "devDependencies": {
8 | "@fullhuman/postcss-purgecss": "^2.2.0",
9 | "fontkit": "^1.8.1",
10 | "parcel": "^1.12.4",
11 | "postcss": "^7.0.32",
12 | "postcss-import": "^12.0.1",
13 | "postcss-preset-env": "^6.7.0",
14 | "stylelint": "^13.5.0",
15 | "stylelint-config-standard": "^20.0.0",
16 | "tailwind-compositor": "^1.0.3",
17 | "tailwindcss": "^1.5.2"
18 | },
19 | "browserslist": "last 1 Chrome version",
20 | "scripts": {
21 | "develop": "rm -rf .cache && parcel index.html -d dev --target browser"
22 | },
23 | "gitHead": "687d4c4559fc4813caff7eca184409c8993455d9"
24 | }
25 |
--------------------------------------------------------------------------------
/example/postcss.config.js:
--------------------------------------------------------------------------------
1 | const tailwindcss = require('tailwindcss');
2 | const { compositor } = require('tailwind-compositor');
3 | const purgecss = require('@fullhuman/postcss-purgecss');
4 |
5 | const compositorConfig = require('./compositor.config.js');
6 | const tailwindConfig = require('./tailwind.config.js');
7 |
8 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
9 | module.exports = {
10 | plugins: [
11 | require('postcss-import')({
12 | plugins: [require('stylelint')],
13 | }),
14 | tailwindcss(tailwindConfigComposed),
15 | ...(process.env.NODE_ENV === 'production'
16 | ? [
17 | purgecss({
18 | defaultExtractor: content =>
19 | content.match(/[\w-/:]+(? 1%', 'last 2 versions', 'Firefox ESR'],
31 | }),
32 | ],
33 | };
34 |
--------------------------------------------------------------------------------
/example/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | theme: {
3 | screens: {
4 | sm: '30rem',
5 | md: '42.5rem',
6 | lg: '80rem',
7 | xl: '105rem',
8 | },
9 | colors: {
10 | transparent: 'transparent',
11 | current: 'currentColor',
12 | mono: [
13 | '#000000',
14 | '#121212',
15 | '#303030',
16 | '#5E5E5E',
17 | '#878787',
18 | '#AAAAAA',
19 | '#C5C5C5',
20 | '#D9D9D9',
21 | '#E9E9E9',
22 | '#F4F4F4',
23 | '#FFFFFF',
24 | ],
25 | },
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/jest.config.base.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: 'ts-jest',
3 | testEnvironment: 'node',
4 | roots: [''],
5 | transform: {
6 | '^.+\\.ts$': 'ts-jest',
7 | '^.+\\.tsx$': 'ts-jest',
8 | },
9 | testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts?|tsx?)?$',
10 | moduleFileExtensions: ['js', 'ts', 'tsx', 'json', 'node', 'css', 'pcss'],
11 | coveragePathIgnorePatterns: ['(tests/.*.mock).(|ts?|tsx?)$'],
12 | verbose: true,
13 | testPathIgnorePatterns: ['/__snapshots__/', '/.cache/', '/lib/', '/dist/'],
14 |
15 | collectCoverage: false,
16 | collectCoverageFrom: ['**/*.{ts,tsx}', '!**/*.d.ts', '!/dist/'],
17 | snapshotSerializers: ['jest-emotion'],
18 | modulePathIgnorePatterns: [
19 | '/__snapshots__/',
20 | 'dummy',
21 | 'scripts',
22 | 'docs',
23 | '__tests__/lib/',
24 | ],
25 | globals: {
26 | 'process.env.__DEV__': true,
27 | 'process.env.__PROD__': false,
28 | 'process.env.__BROWSER__': false,
29 | 'process.env.__SERVER__': false,
30 | },
31 | };
32 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | const base = require('./jest.config.base.js');
2 |
3 | module.exports = {
4 | ...base,
5 | setupFilesAfterEnv: ['./jest.setup.js'],
6 | projects: ['/plugin/jest.config.js'],
7 | };
8 |
--------------------------------------------------------------------------------
/jest.setup.js:
--------------------------------------------------------------------------------
1 | const cssMatcher = require('jest-matcher-css');
2 |
3 | expect.extend({
4 | toMatchCss: cssMatcher,
5 | });
6 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "3.0.0",
3 | "packages": ["plugin", "example"],
4 | "version": "independent",
5 | "npmClient": "yarn",
6 | "licence": "MIT",
7 | "useWorkspaces": true
8 | }
9 |
--------------------------------------------------------------------------------
/licence.md:
--------------------------------------------------------------------------------
1 | # The MIT License (MIT)
2 |
3 | Copyright (c) 2020 Apostolos Christodoulou
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/notes.md:
--------------------------------------------------------------------------------
1 | ```
2 | module.exports = {
3 | options: {
4 | root: 16,
5 | baseline: 8,
6 | leading: 4,
7 | columns: 12,
8 | useRem: true,
9 | useGrid: true,
10 | },
11 | scales: {
12 | type: true,
13 | measure: true,
14 | space: true,
15 | },
16 | fonts: [],
17 | utilities: {
18 | type: ['responsive'],
19 | rhythm: ['responsive'],
20 | measure: ['responsive'],
21 | matrix: ['responsive'],
22 | xray: ['responsive'],
23 | },
24 | };
25 | ```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind-plugin",
3 | "description": "",
4 | "private": true,
5 | "keywords": [
6 | "tailwindcss",
7 | "typography",
8 | "baseline"
9 | ],
10 | "workspaces": [
11 | "plugin",
12 | "example"
13 | ],
14 | "author": "Apostolos Christodoulou (@a7sc11u)",
15 | "main": "index.js",
16 | "license": "MIT",
17 | "scripts": {
18 | "postinstall": "lerna bootstrap",
19 | "develop": "npm-run-all -p plugin example",
20 | "plugin": "lerna exec --scope tailwind-compositor -- yarn develop",
21 | "build": "lerna exec --scope tailwind-compositor -- yarn build",
22 | "example": "lerna exec --scope example -- yarn run develop",
23 | "tdd": "jest --u --watch --onlyChanged --watchman --forceExit --detectOpenHandles --notify --notifyMode=failure",
24 | "release": "yarn test && yarn build && lerna publish --no-git-reset",
25 | "test": "jest --forceExit --detectOpenHandles --notify --notifyMode=failure"
26 | },
27 | "devDependencies": {
28 | "@types/jest": "^25.2.3",
29 | "@types/node": "^12.7.5",
30 | "benchmark": "^2.1.4",
31 | "identity-obj-proxy": "^3.0.0",
32 | "jest": "^26.0.1",
33 | "jest-emotion": "^10.0.32",
34 | "jest-matcher-css": "^1.1.0",
35 | "jshint": "^2.10.2",
36 | "lerna": "^3.20.2",
37 | "npm-run-all": "^4.1.5",
38 | "prun": "^1.0.1",
39 | "typescript": "^3.9.3",
40 | "ts-jest": "^26.0.0"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/plugin/images/baseline-type.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/images/baseline-type.gif
--------------------------------------------------------------------------------
/plugin/images/typeset-differences.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/images/typeset-differences.gif
--------------------------------------------------------------------------------
/plugin/images/vertical-metrics.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/images/vertical-metrics.png
--------------------------------------------------------------------------------
/plugin/jest.config.js:
--------------------------------------------------------------------------------
1 | const base = require('../jest.config.base.js');
2 | const pack = require('./package.json');
3 | const packageName = pack.name;
4 |
5 | module.exports = {
6 | ...base,
7 | name: packageName,
8 | displayName: packageName,
9 | };
10 |
--------------------------------------------------------------------------------
/plugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind-compositor",
3 | "version": "1.0.5-rc.0",
4 | "author": "Apostolos Christodoulou (@a7sc11u)",
5 | "license": "MIT",
6 | "homepage": "https://github.com/a7sc11u/tailwind-compositor#readme",
7 | "keywords": [
8 | "tailwindcss",
9 | "typography",
10 | "baseline",
11 | "baseline-grid",
12 | "baseline-typography",
13 | "grid-system",
14 | "vertical-rhythm"
15 | ],
16 | "main": "dist/index.js",
17 | "module": "dist/index.es.js",
18 | "files": [
19 | "dist"
20 | ],
21 | "types": "dist/index.d.ts",
22 | "publishConfig": {
23 | "access": "public"
24 | },
25 | "scripts": {
26 | "develop": "rollup -cw",
27 | "build": "rollup -c"
28 | },
29 | "peerDependencies": {
30 | "fontkit": "^1.8.1",
31 | "postcss": "^7.0.30",
32 | "tailwindcss": "^1.4.6"
33 | },
34 | "dependencies": {
35 | "lodash.flattendeep": "^4.4.0"
36 | },
37 | "devDependencies": {
38 | "csstype": "^2.6.9",
39 | "fontkit": "^1.8.1",
40 | "postcss": "^7.0.30",
41 | "rollup": "^1.19.4",
42 | "rollup-plugin-typescript2": "^0.24.0",
43 | "tailwindcss": "^1.4.6"
44 | },
45 | "gitHead": "85ecdb3d33bb5ca7fbb1980e5670a8d2661f10fe"
46 | }
47 |
--------------------------------------------------------------------------------
/plugin/readme.md:
--------------------------------------------------------------------------------
1 | # Tailwind Compositor
2 |
3 | Compositor is a system of constraints designed to produce aesthetically pleasing, typographic compositions, based on objective, constant dimensions of space.
4 |
5 | A baseline-grid typography system for [tailwindcss](https://tailwindcss.com/).
6 |
7 | Algorithm Demo: [Styled Baseline](https://styled-baseline.netlify.app/)
8 |
9 | ---
10 |
11 | ## Installation
12 |
13 | You will need fontkit, postcss and tailwindcss installed along with the plugin
14 |
15 | ```
16 | npm install postcss fontkit tailwindcss tailwind-compositor
17 | ```
18 |
19 | #### - postcss.config.js
20 |
21 | In your `postcss.config.js` you will need to import your standard `tailwind.config.js`, but also your `compositor.config.js`.
22 |
23 | The `{ compositor }` will receive both, merge with your tailwind config, and return a standard tailwind configuration.
24 |
25 | ```
26 | const tailwindcss = require('tailwindcss');
27 | const { compositor } = require('tailwind-compositor');
28 |
29 | // import both configurations
30 | const compositorConfig = require('./compositor.config.js');
31 | const tailwindConfig = require('./tailwind.config.js');
32 |
33 | // compose config
34 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
35 |
36 | // use with tailwind
37 | module.exports = {
38 | plugins: [
39 | tailwindcss(tailwindConfigComposed),
40 | ],
41 | };
42 | ```
43 |
44 | ---
45 |
46 | ## Configuration
47 |
48 | #### - compositor.config.js
49 |
50 | ```
51 | const compositorConfig = {
52 | // root unit
53 | root: 16,
54 |
55 | // baseline grid height in px units
56 | baseline: 8,
57 |
58 | // maximum leading
59 | leading: 4,
60 |
61 | // matrix max columns
62 | matrix: 4,
63 |
64 | // type scale in px units
65 | type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56, 60, 72],
66 |
67 | // spacing scale in baseline units
68 | rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12],
69 |
70 | // line width in ch units
71 | measure: [10, 15, 20, 30, 35, 50, 55, 60, 65],
72 |
73 | // webfonts and vertical metrics
74 | fonts: [
75 | {
76 | key: "sans-400",
77 | familyName: "Inter",
78 | fallback: "sans-serif",
79 | weight: 400,
80 | italic: false,
81 | upm: 2816,
82 | xHeight: 1536,
83 | capHeight: 2048,
84 | ascent: 2728,
85 | descent: -680
86 | },
87 | {
88 | key: 'sans-600',
89 | familyName: "Inter",
90 | fallback: 'sans-serif',
91 | file: path.resolve('./fonts/inter/Inter-Semibold.woff2'),
92 | },
93 | ],
94 |
95 | // compositor options
96 | options: {
97 | useRem: true,
98 | snap: true,
99 | type: true,
100 | rhythm: true,
101 | measure: true,
102 | matrix: true,
103 | xray: true,
104 | },
105 | }
106 | ```
107 |
108 | ---
109 |
110 | #### 1/9 - root: integer
111 |
112 | The root font size, in `px` units.
113 |
114 | ---
115 |
116 | #### 2/9 - baseline: integer
117 |
118 | The baseline grid row height, in `px` units.
119 |
120 | ---
121 |
122 | #### 3/9 - leading: integer
123 |
124 | The maximum leading value in baseline units.
125 |
126 | ---
127 |
128 | #### 4/9 - matrix: integer
129 |
130 | The maximum columns on the matrix utility
131 |
132 | ---
133 |
134 | #### 5/9 - type : array[integer]
135 |
136 | ```
137 | type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56, 60, 72]
138 | ```
139 |
140 | The system's typographic scale, in `px` units.
141 |
142 | ---
143 |
144 | #### 6/9 - rhythm : array[integer]
145 |
146 | ```
147 | rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12]
148 | ```
149 |
150 | The system's size and spacing scale, in `baseline` units, used for `rhythm`, `margin`, `padding`, `width/min/max`, `height/min/max` and `grid-gap` utilities
151 |
152 | ---
153 |
154 | #### 7/9 - measure : array[integer]
155 |
156 | ```
157 | measure: [10, 15, 20, 30, 35, 50, 55, 60, 65]
158 | ```
159 |
160 | Separate scale used for `measure` (line-width) utilities, configured in `ch` units.
161 |
162 | ---
163 |
164 | #### 8/9 - fonts : array[opentype]
165 |
166 | The font scale provides all the information needed to render text styles. Each entry describes a font/weight/style set, and only those that are part of the system will be enabled.
167 |
168 | The `file` property, is used to extract the vertical metrics dynamically from the font-file. If you want to configure the metrics manually, you can omit the `file` prop.
169 |
170 | The `key` property is used to name the utility classes. The configuration bellow will produce four font styles. The recommended convention is `${family}-${weight}${style}`.
171 |
172 | 1. `font-sans-400` : Inter Regular
173 | 2. `font-sans-400i` : Inter Regular Italic
174 | 3. `font-sans-600i` : Inter Semibold
175 | 4. `font-sans-600i` : Inter Semibold Italic
176 |
177 | ```
178 | {
179 | key: "sans-400",
180 | familyName: "Inter",
181 | fallback: "sans-serif",
182 | weight: 400,
183 | italic: false,
184 | upm: 2816,
185 | xHeight: 1536,
186 | capHeight: 2048,
187 | lineGap: 0,
188 | ascent: 2728,
189 | descent: -680
190 | },
191 | {
192 | key: 'sans-400i',
193 | familyName: "Inter",
194 | fallback: 'sans-serif',
195 | file: path.resolve('./fonts/inter/Inter-Italic.woff2'),
196 | },
197 | {
198 | key: 'sans-600',
199 | familyName: "Inter",
200 | fallback: 'sans-serif',
201 | file: path.resolve('./fonts/inter/Inter-Semibold.woff2'),
202 | },
203 | {
204 | key: 'sans-600i',
205 | familyName: "Inter",
206 | fallback: 'sans-serif',
207 | file: path.resolve('./fonts/inter/Inter-SemiboldItalic.woff2'),
208 | },
209 | ```
210 |
211 | ---
212 |
213 | #### 9/9 - Options : object
214 |
215 | Options properties, are used to enable/disable individual compositor utilities.
216 |
217 | If `useRem` is set to true, compositor will use the root unit value, to transform all spacing and font-size utilities, to relative units. Line-height will be transformed to unitless ratios.
218 |
219 | If `snap` is true, compositor will align each line text to the nearest baseline grid row, otherwise will trim the line-height above the capHeight and below the baseline, and apply a constant lineGap between lines of text.
220 |
221 | - `useRem: boolean` transform to relative units
222 | - `snap: boolean` Align text styles to a baseline grid
223 | `type: boolean` Enable typographic utilities
224 | - `rhythm: boolean` Enable rhythm utilities
225 | - `measure: boolean` Enable measure utilities
226 | - `matrix: boolean` Enable matrix utilities
227 | - `xray: boolean` Enable debug utilities
228 |
229 | ```
230 | options: {
231 | useRem: true,
232 | snap: true,
233 | type: true,
234 | rhythm: true,
235 | measure: true,
236 | matrix: true,
237 | xray: true,
238 | }
239 | ```
240 |
241 | ---
242 |
243 | ## Tailwind Utility Classes
244 |
245 | #### 1/7 - Typography
246 |
247 | ##### Font & Font Style
248 |
249 | - font: `font-{font-key}`
250 |
251 | ```
252 |
253 | // fonts: [
254 | // { key: "sans-400", ... },
255 | // { key: 'sans-400i', ... },
256 | // { key: 'sans-600', ... },
257 | // { key: 'sans-600i', ... },
258 | // ],
259 |
260 | // sans semibold italic
261 |
262 |
263 | // sans regular
264 |
265 |
266 | // sans regular italic
267 |
268 | ```
269 |
270 | ##### Text Style
271 |
272 | - Text Style : `text-{type_scale_index}/{leading_baseline_units}`
273 |
274 | ```
275 |
276 | // type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56]
277 |
278 | // sans semibold italic - 56px / leading 3
279 |
280 |
281 | // sans regular - 20px / leading 3
282 |
283 |
284 | // sans regular italic - 18px / leading 2
285 |
286 | ```
287 |
288 |
289 | ---
290 |
291 | #### 2/7 - Line Width
292 |
293 | - `measure-{measure_scale_index}`
294 |
295 | ```
296 | // measure: [10, 15, 20, 30, 35, 50, 55, 60, 65]
297 |
298 | // 10ch
299 | Ad proident quis enim duis commodo.
300 |
301 | // 15ch
302 | Ad proident quis enim duis commodo.
303 |
304 | // 20ch
305 | Ad proident quis enim duis commodo.
306 |
307 | // 30ch
308 | Ad proident quis enim duis commodo.
309 | ```
310 |
311 | ---
312 |
313 | #### 3/7 - Spacing
314 |
315 | When the tailwind theme is composed, the rhythm scale is transformed to tailwindcss spacing scale and can be used for all spacing utilities, margin, padding and grid-gap.
316 |
317 | - Margin: `m-{rhythm_scale_index}`
318 | - Margin Left: `ml-{rhythm_scale_index}`
319 | - Padding: `p-{rhythm_scale_index}`
320 | - ...etc
321 |
322 | ```
323 |
324 | // rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12]
325 |
326 |
331 | ```
332 |
333 | ---
334 |
335 | #### 4/7 - Size
336 |
337 | Compositor also applies the spacing scale to tailwind sizing scales, width, min/max width and also height min/max.
338 |
339 | - Height: `h-{rhythm_scale_index}`
340 | - Min Height: `min-h-{rhythm_scale_index}`
341 | - Max Height: `max-h-{rhythm_scale_index}`
342 | - ...etc
343 | -
344 |
345 | ```
346 |
349 | ```
350 |
351 | ---
352 |
353 | #### 5/7 - Lobotomized Owls
354 |
355 | - Vertical rhythm (alias): `rhythm-{rhythm_scale_index}`
356 | - Vertical rhythm: `rhythm-y-{rhythm_scale_index}`
357 | - Horizontal Rhythm: `rhythm-x-{rhythm_scale_index}`
358 |
359 | ```
360 |
361 |
362 |
363 |
364 |
365 | // render horizontally
366 |
367 |
368 |
369 |
370 |
371 | ```
372 |
373 | ---
374 |
375 | #### 6/7 - Matrix Utils
376 |
377 | ##### Matrix
378 | - Matrix: `matrix-{columns_length}`
379 | - Matrix Gap: `matrix-gap-{rhythm_scale_index}`
380 | - Matrix Gap X: `matrix-gap-x-{rhythm_scale_index}`
381 | - Matrix Gap Y: `matrix-gap-y-{rhythm_scale_index}`
382 |
383 | ##### Cells
384 | By default every child of the matrix, will be placed in the next available column and will span for 1 column. In many cases you might not need any cell utilities or only the `cell-span-x` utility.
385 |
386 | - Cell Start X: `cell-start-x-{columns_index}`
387 | - Cell Span X: `cell-span-x-{columns_index}`
388 |
389 | ---
390 |
391 | #### 7/7 - Dev Utils
392 |
393 | - Background grid lines: `bg-baseline`
394 |
395 | ```
396 |
397 | ```
398 |
--------------------------------------------------------------------------------
/plugin/rollup.config.js:
--------------------------------------------------------------------------------
1 | import { createRollupConfig } from '../scripts/rollup.base';
2 | import pkg from './package.json';
3 |
4 | export default createRollupConfig(pkg);
5 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/__mocks__/styleMock.js:
--------------------------------------------------------------------------------
1 | module.exports = {};
2 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/__snapshots__/compositor.file.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`transform with font files 1`] = `
4 | Object {
5 | "corePlugins": false,
6 | "important": false,
7 | "plugins": Array [
8 | [Function],
9 | ],
10 | "prefix": "",
11 | "purge": Array [],
12 | "separator": ":",
13 | "target": "relaxed",
14 | "theme": Object {
15 | "colors": Object {
16 | "black": "#000",
17 | "current": "currentColor",
18 | "transparent": "transparent",
19 | "white": "#fff",
20 | },
21 | "compositor": Object {
22 | "baseline": 10,
23 | "fonts": Array [
24 | Object {
25 | "ascent": 2728,
26 | "capHeight": 2048,
27 | "descent": -680,
28 | "familyName": "Inter",
29 | "italic": false,
30 | "key": "sans-400",
31 | "lineGap": 0,
32 | "upm": 2816,
33 | "weight": 400,
34 | "xHeight": 1536,
35 | },
36 | ],
37 | "leading": 2,
38 | "matrix": 6,
39 | "measure": Object {
40 | "0": "10ch",
41 | "1": "20ch",
42 | },
43 | "options": Object {
44 | "matrix": true,
45 | "measure": true,
46 | "rhythm": true,
47 | "snap": true,
48 | "type": true,
49 | "useRem": false,
50 | "xray": true,
51 | },
52 | "rhythm": Array [
53 | 0,
54 | 1,
55 | 2,
56 | ],
57 | "root": 10,
58 | "styles": Object {
59 | "ruler": Object {
60 | "color": "rgba(255, 0, 255, 0.3)",
61 | },
62 | },
63 | "type": Array [
64 | 10,
65 | 20,
66 | ],
67 | },
68 | "extend": Object {
69 | "height": Object {
70 | "0": "0px",
71 | "1": "10px",
72 | "2": "20px",
73 | },
74 | "maxHeight": Object {
75 | "0": "0px",
76 | "1": "10px",
77 | "100": "100px",
78 | "2": "20px",
79 | },
80 | "maxWidth": Object {
81 | "100": "100px",
82 | },
83 | "minHeight": Object {
84 | "0": "0px",
85 | "1": "10px",
86 | "100": "100px",
87 | "2": "20px",
88 | },
89 | "minWidth": Object {
90 | "100": "100px",
91 | },
92 | },
93 | "flex": Object {
94 | "auto": "1 1 auto",
95 | },
96 | "fontFamily": Object {
97 | "sans": Array [
98 | "system-ui",
99 | ],
100 | },
101 | "fontSize": Array [
102 | 10,
103 | 20,
104 | ],
105 | "fontWeight": Object {
106 | "bold": "700",
107 | "normal": "400",
108 | },
109 | "letterSpacing": Object {
110 | "normal": "0",
111 | "wide": "0.025em",
112 | },
113 | "lineHeight": Object {
114 | "none": "1",
115 | "normal": "1.5",
116 | },
117 | "screens": Object {
118 | "sm": "640px",
119 | },
120 | "spacing": Object {
121 | "0": "0px",
122 | "1": "10px",
123 | "2": "20px",
124 | },
125 | },
126 | "variants": Object {
127 | "accessibility": Array [],
128 | "alignContent": Array [],
129 | "alignItems": Array [],
130 | "alignSelf": Array [],
131 | "appearance": Array [],
132 | "backgroundAttachment": Array [],
133 | "backgroundColor": Array [],
134 | "backgroundOpacity": Array [],
135 | "backgroundPosition": Array [],
136 | "backgroundRepeat": Array [],
137 | "backgroundSize": Array [],
138 | "borderCollapse": Array [],
139 | "borderColor": Array [],
140 | "borderOpacity": Array [],
141 | "borderRadius": Array [],
142 | "borderStyle": Array [],
143 | "borderWidth": Array [],
144 | "boxShadow": Array [],
145 | "boxSizing": Array [],
146 | "clear": Array [],
147 | "cursor": Array [],
148 | "display": Array [],
149 | "divideColor": Array [],
150 | "divideOpacity": Array [],
151 | "divideWidth": Array [],
152 | "fill": Array [],
153 | "flex": Array [],
154 | "flexDirection": Array [],
155 | "flexGrow": Array [],
156 | "flexShrink": Array [],
157 | "flexWrap": Array [],
158 | "float": Array [],
159 | "fontFamily": Array [],
160 | "fontSize": Array [],
161 | "fontSmoothing": Array [],
162 | "fontStyle": Array [],
163 | "fontWeight": Array [],
164 | "gap": Array [],
165 | "gridAutoFlow": Array [],
166 | "gridColumn": Array [],
167 | "gridColumnEnd": Array [],
168 | "gridColumnStart": Array [],
169 | "gridRow": Array [],
170 | "gridRowEnd": Array [],
171 | "gridRowStart": Array [],
172 | "gridTemplateColumns": Array [],
173 | "gridTemplateRows": Array [],
174 | "height": Array [],
175 | "inset": Array [],
176 | "justifyContent": Array [],
177 | "letterSpacing": Array [],
178 | "lineHeight": Array [],
179 | "listStylePosition": Array [],
180 | "listStyleType": Array [],
181 | "margin": Array [],
182 | "maxHeight": Array [],
183 | "maxWidth": Array [],
184 | "minHeight": Array [],
185 | "minWidth": Array [],
186 | "objectFit": Array [],
187 | "objectPosition": Array [],
188 | "opacity": Array [],
189 | "order": Array [],
190 | "outline": Array [],
191 | "overflow": Array [],
192 | "padding": Array [],
193 | "placeholderColor": Array [],
194 | "placeholderOpacity": Array [],
195 | "pointerEvents": Array [],
196 | "position": Array [],
197 | "resize": Array [],
198 | "rotate": Array [],
199 | "scale": Array [],
200 | "skew": Array [],
201 | "space": Array [],
202 | "stroke": Array [],
203 | "strokeWidth": Array [],
204 | "tableLayout": Array [],
205 | "textAlign": Array [],
206 | "textColor": Array [],
207 | "textDecoration": Array [],
208 | "textOpacity": Array [],
209 | "textTransform": Array [],
210 | "transform": Array [],
211 | "transformOrigin": Array [],
212 | "transitionDelay": Array [],
213 | "transitionDuration": Array [],
214 | "transitionProperty": Array [],
215 | "transitionTimingFunction": Array [],
216 | "translate": Array [],
217 | "userSelect": Array [],
218 | "verticalAlign": Array [],
219 | "visibility": Array [],
220 | "whitespace": Array [],
221 | "width": Array [],
222 | "wordBreak": Array [],
223 | "zIndex": Array [],
224 | },
225 | }
226 | `;
227 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/__snapshots__/plugin.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`baseline styles 1`] = `
4 | ".font-sans-400 {
5 | font-family: \\"IBM Plex Sans\\", sans-serif;
6 | font-weight: 400;
7 | font-style: normal;
8 | display: block;
9 | }
10 |
11 | .font-sans-400::before, .font-sans-400::after {
12 | content: '';
13 | display: block;
14 | height: 0;
15 | }
16 |
17 | .font-sans-400.text-0\\\\/0 {
18 | font-size: 10px;
19 | line-height: 10px;
20 | padding-top: 3.42px;
21 | padding-bottom: 0.4px;
22 | }
23 |
24 | .font-sans-400.text-0\\\\/0::before {
25 | margin-top: -2.17px;
26 | }
27 |
28 | .font-sans-400.text-0\\\\/0::after {
29 | margin-bottom: -1.65px;
30 | }
31 |
32 | .font-sans-400.text-0\\\\/1 {
33 | font-size: 10px;
34 | line-height: 20px;
35 | padding-top: 3.4199999999999995px;
36 | padding-bottom: 0.4px;
37 | }
38 |
39 | .font-sans-400.text-0\\\\/1::before {
40 | margin-top: -7.17px;
41 | }
42 |
43 | .font-sans-400.text-0\\\\/1::after {
44 | margin-bottom: -6.65px;
45 | }
46 |
47 | .font-sans-400.text-0\\\\/2 {
48 | font-size: 10px;
49 | line-height: 30px;
50 | padding-top: 3.4199999999999995px;
51 | padding-bottom: 0.4px;
52 | }
53 |
54 | .font-sans-400.text-0\\\\/2::before {
55 | margin-top: -12.17px;
56 | }
57 |
58 | .font-sans-400.text-0\\\\/2::after {
59 | margin-bottom: -11.65px;
60 | }
61 |
62 | .font-sans-400.text-1\\\\/0 {
63 | font-size: 20px;
64 | line-height: 10px;
65 | padding-top: -3.56px;
66 | padding-bottom: 0.4px;
67 | }
68 |
69 | .font-sans-400.text-1\\\\/0::before {
70 | margin-top: 1.06px;
71 | }
72 |
73 | .font-sans-400.text-1\\\\/0::after {
74 | margin-bottom: 2.1px;
75 | }
76 |
77 | .font-sans-400.text-1\\\\/1 {
78 | font-size: 20px;
79 | line-height: 20px;
80 | padding-top: 6.44px;
81 | padding-bottom: 0.4px;
82 | }
83 |
84 | .font-sans-400.text-1\\\\/1::before {
85 | margin-top: -3.94px;
86 | }
87 |
88 | .font-sans-400.text-1\\\\/1::after {
89 | margin-bottom: -2.9px;
90 | }
91 |
92 | .font-sans-400.text-1\\\\/2 {
93 | font-size: 20px;
94 | line-height: 30px;
95 | padding-top: 6.4399999999999995px;
96 | padding-bottom: 0.4px;
97 | }
98 |
99 | .font-sans-400.text-1\\\\/2::before {
100 | margin-top: -8.94px;
101 | }
102 |
103 | .font-sans-400.text-1\\\\/2::after {
104 | margin-bottom: -7.9px;
105 | }
106 |
107 | @media (min-width: 640px) {
108 | .font-sans-400.sm\\\\:text-0\\\\/0 {
109 | font-size: 10px;
110 | line-height: 10px;
111 | padding-top: 3.42px;
112 | padding-bottom: 0.4px;
113 | }
114 |
115 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
116 | margin-top: -2.17px;
117 | }
118 |
119 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
120 | margin-bottom: -1.65px;
121 | }
122 |
123 | .font-sans-400.sm\\\\:text-0\\\\/1 {
124 | font-size: 10px;
125 | line-height: 20px;
126 | padding-top: 3.4199999999999995px;
127 | padding-bottom: 0.4px;
128 | }
129 |
130 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
131 | margin-top: -7.17px;
132 | }
133 |
134 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
135 | margin-bottom: -6.65px;
136 | }
137 |
138 | .font-sans-400.sm\\\\:text-0\\\\/2 {
139 | font-size: 10px;
140 | line-height: 30px;
141 | padding-top: 3.4199999999999995px;
142 | padding-bottom: 0.4px;
143 | }
144 |
145 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
146 | margin-top: -12.17px;
147 | }
148 |
149 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
150 | margin-bottom: -11.65px;
151 | }
152 |
153 | .font-sans-400.sm\\\\:text-1\\\\/0 {
154 | font-size: 20px;
155 | line-height: 10px;
156 | padding-top: -3.56px;
157 | padding-bottom: 0.4px;
158 | }
159 |
160 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
161 | margin-top: 1.06px;
162 | }
163 |
164 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
165 | margin-bottom: 2.1px;
166 | }
167 |
168 | .font-sans-400.sm\\\\:text-1\\\\/1 {
169 | font-size: 20px;
170 | line-height: 20px;
171 | padding-top: 6.44px;
172 | padding-bottom: 0.4px;
173 | }
174 |
175 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
176 | margin-top: -3.94px;
177 | }
178 |
179 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
180 | margin-bottom: -2.9px;
181 | }
182 |
183 | .font-sans-400.sm\\\\:text-1\\\\/2 {
184 | font-size: 20px;
185 | line-height: 30px;
186 | padding-top: 6.4399999999999995px;
187 | padding-bottom: 0.4px;
188 | }
189 |
190 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
191 | margin-top: -8.94px;
192 | }
193 |
194 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
195 | margin-bottom: -7.9px;
196 | }
197 | }"
198 | `;
199 |
200 | exports[`capheight styles 1`] = `
201 | ".font-sans-400 {
202 | font-family: \\"IBM Plex Sans\\", sans-serif;
203 | font-weight: 400;
204 | font-style: normal;
205 | display: block;
206 | }
207 |
208 | .font-sans-400::before, .font-sans-400::after {
209 | content: '';
210 | display: block;
211 | height: 0;
212 | }
213 |
214 | .font-sans-400.text-0\\\\/0 {
215 | font-size: 10px;
216 | line-height: 6.9799999999999995px;
217 | padding-top: 0.4px;
218 | padding-bottom: 0.4px;
219 | }
220 |
221 | .font-sans-400.text-0\\\\/0::before {
222 | margin-top: -0.6599999999999998px;
223 | }
224 |
225 | .font-sans-400.text-0\\\\/0::after {
226 | margin-bottom: -0.1399999999999998px;
227 | }
228 |
229 | .font-sans-400.text-0\\\\/1 {
230 | font-size: 10px;
231 | line-height: 16.98px;
232 | padding-top: 0.4px;
233 | padding-bottom: 0.4px;
234 | }
235 |
236 | .font-sans-400.text-0\\\\/1::before {
237 | margin-top: -5.66px;
238 | }
239 |
240 | .font-sans-400.text-0\\\\/1::after {
241 | margin-bottom: -5.140000000000001px;
242 | }
243 |
244 | .font-sans-400.text-0\\\\/2 {
245 | font-size: 10px;
246 | line-height: 26.98px;
247 | padding-top: 0.4px;
248 | padding-bottom: 0.4px;
249 | }
250 |
251 | .font-sans-400.text-0\\\\/2::before {
252 | margin-top: -10.66px;
253 | }
254 |
255 | .font-sans-400.text-0\\\\/2::after {
256 | margin-bottom: -10.14px;
257 | }
258 |
259 | .font-sans-400.text-1\\\\/0 {
260 | font-size: 20px;
261 | line-height: 13.959999999999999px;
262 | padding-top: 0.4px;
263 | padding-bottom: 0.4px;
264 | }
265 |
266 | .font-sans-400.text-1\\\\/0::before {
267 | margin-top: -0.9199999999999996px;
268 | }
269 |
270 | .font-sans-400.text-1\\\\/0::after {
271 | margin-bottom: 0.12000000000000044px;
272 | }
273 |
274 | .font-sans-400.text-1\\\\/1 {
275 | font-size: 20px;
276 | line-height: 23.96px;
277 | padding-top: 0.4px;
278 | padding-bottom: 0.4px;
279 | }
280 |
281 | .font-sans-400.text-1\\\\/1::before {
282 | margin-top: -5.920000000000001px;
283 | }
284 |
285 | .font-sans-400.text-1\\\\/1::after {
286 | margin-bottom: -4.880000000000001px;
287 | }
288 |
289 | .font-sans-400.text-1\\\\/2 {
290 | font-size: 20px;
291 | line-height: 33.96px;
292 | padding-top: 0.4px;
293 | padding-bottom: 0.4px;
294 | }
295 |
296 | .font-sans-400.text-1\\\\/2::before {
297 | margin-top: -10.92px;
298 | }
299 |
300 | .font-sans-400.text-1\\\\/2::after {
301 | margin-bottom: -9.88px;
302 | }
303 |
304 | @media (min-width: 640px) {
305 | .font-sans-400.sm\\\\:text-0\\\\/0 {
306 | font-size: 10px;
307 | line-height: 6.9799999999999995px;
308 | padding-top: 0.4px;
309 | padding-bottom: 0.4px;
310 | }
311 |
312 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
313 | margin-top: -0.6599999999999998px;
314 | }
315 |
316 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
317 | margin-bottom: -0.1399999999999998px;
318 | }
319 |
320 | .font-sans-400.sm\\\\:text-0\\\\/1 {
321 | font-size: 10px;
322 | line-height: 16.98px;
323 | padding-top: 0.4px;
324 | padding-bottom: 0.4px;
325 | }
326 |
327 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
328 | margin-top: -5.66px;
329 | }
330 |
331 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
332 | margin-bottom: -5.140000000000001px;
333 | }
334 |
335 | .font-sans-400.sm\\\\:text-0\\\\/2 {
336 | font-size: 10px;
337 | line-height: 26.98px;
338 | padding-top: 0.4px;
339 | padding-bottom: 0.4px;
340 | }
341 |
342 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
343 | margin-top: -10.66px;
344 | }
345 |
346 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
347 | margin-bottom: -10.14px;
348 | }
349 |
350 | .font-sans-400.sm\\\\:text-1\\\\/0 {
351 | font-size: 20px;
352 | line-height: 13.959999999999999px;
353 | padding-top: 0.4px;
354 | padding-bottom: 0.4px;
355 | }
356 |
357 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
358 | margin-top: -0.9199999999999996px;
359 | }
360 |
361 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
362 | margin-bottom: 0.12000000000000044px;
363 | }
364 |
365 | .font-sans-400.sm\\\\:text-1\\\\/1 {
366 | font-size: 20px;
367 | line-height: 23.96px;
368 | padding-top: 0.4px;
369 | padding-bottom: 0.4px;
370 | }
371 |
372 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
373 | margin-top: -5.920000000000001px;
374 | }
375 |
376 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
377 | margin-bottom: -4.880000000000001px;
378 | }
379 |
380 | .font-sans-400.sm\\\\:text-1\\\\/2 {
381 | font-size: 20px;
382 | line-height: 33.96px;
383 | padding-top: 0.4px;
384 | padding-bottom: 0.4px;
385 | }
386 |
387 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
388 | margin-top: -10.92px;
389 | }
390 |
391 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
392 | margin-bottom: -9.88px;
393 | }
394 | }"
395 | `;
396 |
397 | exports[`matrix styles 1`] = `
398 | ".font-sans-400 {
399 | font-family: \\"IBM Plex Sans\\", sans-serif;
400 | font-weight: 400;
401 | font-style: normal;
402 | display: block;
403 | }
404 |
405 | .font-sans-400::before, .font-sans-400::after {
406 | content: '';
407 | display: block;
408 | height: 0;
409 | }
410 |
411 | .font-sans-400.text-0\\\\/0 {
412 | font-size: 10px;
413 | line-height: 6.9799999999999995px;
414 | padding-top: 0.4px;
415 | padding-bottom: 0.4px;
416 | }
417 |
418 | .font-sans-400.text-0\\\\/0::before {
419 | margin-top: -0.6599999999999998px;
420 | }
421 |
422 | .font-sans-400.text-0\\\\/0::after {
423 | margin-bottom: -0.1399999999999998px;
424 | }
425 |
426 | .font-sans-400.text-0\\\\/1 {
427 | font-size: 10px;
428 | line-height: 16.98px;
429 | padding-top: 0.4px;
430 | padding-bottom: 0.4px;
431 | }
432 |
433 | .font-sans-400.text-0\\\\/1::before {
434 | margin-top: -5.66px;
435 | }
436 |
437 | .font-sans-400.text-0\\\\/1::after {
438 | margin-bottom: -5.140000000000001px;
439 | }
440 |
441 | .font-sans-400.text-0\\\\/2 {
442 | font-size: 10px;
443 | line-height: 26.98px;
444 | padding-top: 0.4px;
445 | padding-bottom: 0.4px;
446 | }
447 |
448 | .font-sans-400.text-0\\\\/2::before {
449 | margin-top: -10.66px;
450 | }
451 |
452 | .font-sans-400.text-0\\\\/2::after {
453 | margin-bottom: -10.14px;
454 | }
455 |
456 | .font-sans-400.text-1\\\\/0 {
457 | font-size: 20px;
458 | line-height: 13.959999999999999px;
459 | padding-top: 0.4px;
460 | padding-bottom: 0.4px;
461 | }
462 |
463 | .font-sans-400.text-1\\\\/0::before {
464 | margin-top: -0.9199999999999996px;
465 | }
466 |
467 | .font-sans-400.text-1\\\\/0::after {
468 | margin-bottom: 0.12000000000000044px;
469 | }
470 |
471 | .font-sans-400.text-1\\\\/1 {
472 | font-size: 20px;
473 | line-height: 23.96px;
474 | padding-top: 0.4px;
475 | padding-bottom: 0.4px;
476 | }
477 |
478 | .font-sans-400.text-1\\\\/1::before {
479 | margin-top: -5.920000000000001px;
480 | }
481 |
482 | .font-sans-400.text-1\\\\/1::after {
483 | margin-bottom: -4.880000000000001px;
484 | }
485 |
486 | .font-sans-400.text-1\\\\/2 {
487 | font-size: 20px;
488 | line-height: 33.96px;
489 | padding-top: 0.4px;
490 | padding-bottom: 0.4px;
491 | }
492 |
493 | .font-sans-400.text-1\\\\/2::before {
494 | margin-top: -10.92px;
495 | }
496 |
497 | .font-sans-400.text-1\\\\/2::after {
498 | margin-bottom: -9.88px;
499 | }
500 |
501 | .matrix-0 {
502 | display: grid;
503 | grid-template-columns: repeat(1, minmax(auto,1fr));
504 | }
505 |
506 | .matrix-1 {
507 | display: grid;
508 | grid-template-columns: repeat(1, minmax(auto,1fr));
509 | }
510 |
511 | .matrix-2 {
512 | display: grid;
513 | grid-template-columns: repeat(2, minmax(auto,1fr));
514 | }
515 |
516 | .matrix-3 {
517 | display: grid;
518 | grid-template-columns: repeat(3, minmax(auto,1fr));
519 | }
520 |
521 | .matrix-4 {
522 | display: grid;
523 | grid-template-columns: repeat(4, minmax(auto,1fr));
524 | }
525 |
526 | .matrix-5 {
527 | display: grid;
528 | grid-template-columns: repeat(5, minmax(auto,1fr));
529 | }
530 |
531 | .matrix-6 {
532 | display: grid;
533 | grid-template-columns: repeat(6, minmax(auto,1fr));
534 | }
535 |
536 | .matrix-row-h-0 {
537 | grid-auto-rows: minmax(0px, auto);
538 | }
539 |
540 | .matrix-gap-0 {
541 | grid-row-gap: 0px;
542 | grid-column-gap: 0px;
543 | }
544 |
545 | .matrix-gap-x-0 {
546 | grid-column-gap: 0px;
547 | }
548 |
549 | .matrix-gap-y-0 {
550 | grid-row-gap: 0px;
551 | }
552 |
553 | .matrix-row-h-1 {
554 | grid-auto-rows: minmax(10px, auto);
555 | }
556 |
557 | .matrix-gap-1 {
558 | grid-row-gap: 10px;
559 | grid-column-gap: 10px;
560 | }
561 |
562 | .matrix-gap-x-1 {
563 | grid-column-gap: 10px;
564 | }
565 |
566 | .matrix-gap-y-1 {
567 | grid-row-gap: 10px;
568 | }
569 |
570 | .matrix-row-h-2 {
571 | grid-auto-rows: minmax(20px, auto);
572 | }
573 |
574 | .matrix-gap-2 {
575 | grid-row-gap: 20px;
576 | grid-column-gap: 20px;
577 | }
578 |
579 | .matrix-gap-x-2 {
580 | grid-column-gap: 20px;
581 | }
582 |
583 | .matrix-gap-y-2 {
584 | grid-row-gap: 20px;
585 | }
586 |
587 | .cell-start-x-1 {
588 | grid-column-start: 1 !important;
589 | }
590 |
591 | .cell-span-x-1 {
592 | grid-column: auto / span 1;
593 | }
594 |
595 | .cell-start-y-1 {
596 | grid-row-start: 1 !important;
597 | }
598 |
599 | .cell-span-y-1 {
600 | grid-row: auto / span 1;
601 | }
602 |
603 | .cell-start-x-1 {
604 | grid-column-start: 1 !important;
605 | }
606 |
607 | .cell-span-x-1 {
608 | grid-column: auto / span 1;
609 | }
610 |
611 | .cell-start-y-1 {
612 | grid-row-start: 1 !important;
613 | }
614 |
615 | .cell-span-y-1 {
616 | grid-row: auto / span 1;
617 | }
618 |
619 | .cell-start-x-2 {
620 | grid-column-start: 2 !important;
621 | }
622 |
623 | .cell-span-x-2 {
624 | grid-column: auto / span 2;
625 | }
626 |
627 | .cell-start-y-2 {
628 | grid-row-start: 2 !important;
629 | }
630 |
631 | .cell-span-y-2 {
632 | grid-row: auto / span 2;
633 | }
634 |
635 | .cell-start-x-3 {
636 | grid-column-start: 3 !important;
637 | }
638 |
639 | .cell-span-x-3 {
640 | grid-column: auto / span 3;
641 | }
642 |
643 | .cell-start-y-3 {
644 | grid-row-start: 3 !important;
645 | }
646 |
647 | .cell-span-y-3 {
648 | grid-row: auto / span 3;
649 | }
650 |
651 | .cell-start-x-4 {
652 | grid-column-start: 4 !important;
653 | }
654 |
655 | .cell-span-x-4 {
656 | grid-column: auto / span 4;
657 | }
658 |
659 | .cell-start-y-4 {
660 | grid-row-start: 4 !important;
661 | }
662 |
663 | .cell-span-y-4 {
664 | grid-row: auto / span 4;
665 | }
666 |
667 | .cell-start-x-5 {
668 | grid-column-start: 5 !important;
669 | }
670 |
671 | .cell-span-x-5 {
672 | grid-column: auto / span 5;
673 | }
674 |
675 | .cell-start-y-5 {
676 | grid-row-start: 5 !important;
677 | }
678 |
679 | .cell-span-y-5 {
680 | grid-row: auto / span 5;
681 | }
682 |
683 | .cell-start-x-6 {
684 | grid-column-start: 6 !important;
685 | }
686 |
687 | .cell-span-x-6 {
688 | grid-column: auto / span 6;
689 | }
690 |
691 | .cell-start-y-6 {
692 | grid-row-start: 6 !important;
693 | }
694 |
695 | .cell-span-y-6 {
696 | grid-row: auto / span 6;
697 | }
698 |
699 | @media (min-width: 640px) {
700 | .font-sans-400.sm\\\\:text-0\\\\/0 {
701 | font-size: 10px;
702 | line-height: 6.9799999999999995px;
703 | padding-top: 0.4px;
704 | padding-bottom: 0.4px;
705 | }
706 |
707 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
708 | margin-top: -0.6599999999999998px;
709 | }
710 |
711 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
712 | margin-bottom: -0.1399999999999998px;
713 | }
714 |
715 | .font-sans-400.sm\\\\:text-0\\\\/1 {
716 | font-size: 10px;
717 | line-height: 16.98px;
718 | padding-top: 0.4px;
719 | padding-bottom: 0.4px;
720 | }
721 |
722 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
723 | margin-top: -5.66px;
724 | }
725 |
726 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
727 | margin-bottom: -5.140000000000001px;
728 | }
729 |
730 | .font-sans-400.sm\\\\:text-0\\\\/2 {
731 | font-size: 10px;
732 | line-height: 26.98px;
733 | padding-top: 0.4px;
734 | padding-bottom: 0.4px;
735 | }
736 |
737 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
738 | margin-top: -10.66px;
739 | }
740 |
741 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
742 | margin-bottom: -10.14px;
743 | }
744 |
745 | .font-sans-400.sm\\\\:text-1\\\\/0 {
746 | font-size: 20px;
747 | line-height: 13.959999999999999px;
748 | padding-top: 0.4px;
749 | padding-bottom: 0.4px;
750 | }
751 |
752 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
753 | margin-top: -0.9199999999999996px;
754 | }
755 |
756 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
757 | margin-bottom: 0.12000000000000044px;
758 | }
759 |
760 | .font-sans-400.sm\\\\:text-1\\\\/1 {
761 | font-size: 20px;
762 | line-height: 23.96px;
763 | padding-top: 0.4px;
764 | padding-bottom: 0.4px;
765 | }
766 |
767 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
768 | margin-top: -5.920000000000001px;
769 | }
770 |
771 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
772 | margin-bottom: -4.880000000000001px;
773 | }
774 |
775 | .font-sans-400.sm\\\\:text-1\\\\/2 {
776 | font-size: 20px;
777 | line-height: 33.96px;
778 | padding-top: 0.4px;
779 | padding-bottom: 0.4px;
780 | }
781 |
782 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
783 | margin-top: -10.92px;
784 | }
785 |
786 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
787 | margin-bottom: -9.88px;
788 | }
789 |
790 | .sm\\\\:matrix-0 {
791 | display: grid;
792 | grid-template-columns: repeat(1, minmax(auto,1fr));
793 | }
794 |
795 | .sm\\\\:matrix-1 {
796 | display: grid;
797 | grid-template-columns: repeat(1, minmax(auto,1fr));
798 | }
799 |
800 | .sm\\\\:matrix-2 {
801 | display: grid;
802 | grid-template-columns: repeat(2, minmax(auto,1fr));
803 | }
804 |
805 | .sm\\\\:matrix-3 {
806 | display: grid;
807 | grid-template-columns: repeat(3, minmax(auto,1fr));
808 | }
809 |
810 | .sm\\\\:matrix-4 {
811 | display: grid;
812 | grid-template-columns: repeat(4, minmax(auto,1fr));
813 | }
814 |
815 | .sm\\\\:matrix-5 {
816 | display: grid;
817 | grid-template-columns: repeat(5, minmax(auto,1fr));
818 | }
819 |
820 | .sm\\\\:matrix-6 {
821 | display: grid;
822 | grid-template-columns: repeat(6, minmax(auto,1fr));
823 | }
824 |
825 | .sm\\\\:matrix-row-h-0 {
826 | grid-auto-rows: minmax(0px, auto);
827 | }
828 |
829 | .sm\\\\:matrix-gap-0 {
830 | grid-row-gap: 0px;
831 | grid-column-gap: 0px;
832 | }
833 |
834 | .sm\\\\:matrix-gap-x-0 {
835 | grid-column-gap: 0px;
836 | }
837 |
838 | .sm\\\\:matrix-gap-y-0 {
839 | grid-row-gap: 0px;
840 | }
841 |
842 | .sm\\\\:matrix-row-h-1 {
843 | grid-auto-rows: minmax(10px, auto);
844 | }
845 |
846 | .sm\\\\:matrix-gap-1 {
847 | grid-row-gap: 10px;
848 | grid-column-gap: 10px;
849 | }
850 |
851 | .sm\\\\:matrix-gap-x-1 {
852 | grid-column-gap: 10px;
853 | }
854 |
855 | .sm\\\\:matrix-gap-y-1 {
856 | grid-row-gap: 10px;
857 | }
858 |
859 | .sm\\\\:matrix-row-h-2 {
860 | grid-auto-rows: minmax(20px, auto);
861 | }
862 |
863 | .sm\\\\:matrix-gap-2 {
864 | grid-row-gap: 20px;
865 | grid-column-gap: 20px;
866 | }
867 |
868 | .sm\\\\:matrix-gap-x-2 {
869 | grid-column-gap: 20px;
870 | }
871 |
872 | .sm\\\\:matrix-gap-y-2 {
873 | grid-row-gap: 20px;
874 | }
875 |
876 | .sm\\\\:cell-start-x-1 {
877 | grid-column-start: 1 !important;
878 | }
879 |
880 | .sm\\\\:cell-span-x-1 {
881 | grid-column: auto / span 1;
882 | }
883 |
884 | .sm\\\\:cell-start-y-1 {
885 | grid-row-start: 1 !important;
886 | }
887 |
888 | .sm\\\\:cell-span-y-1 {
889 | grid-row: auto / span 1;
890 | }
891 |
892 | .sm\\\\:cell-start-x-1 {
893 | grid-column-start: 1 !important;
894 | }
895 |
896 | .sm\\\\:cell-span-x-1 {
897 | grid-column: auto / span 1;
898 | }
899 |
900 | .sm\\\\:cell-start-y-1 {
901 | grid-row-start: 1 !important;
902 | }
903 |
904 | .sm\\\\:cell-span-y-1 {
905 | grid-row: auto / span 1;
906 | }
907 |
908 | .sm\\\\:cell-start-x-2 {
909 | grid-column-start: 2 !important;
910 | }
911 |
912 | .sm\\\\:cell-span-x-2 {
913 | grid-column: auto / span 2;
914 | }
915 |
916 | .sm\\\\:cell-start-y-2 {
917 | grid-row-start: 2 !important;
918 | }
919 |
920 | .sm\\\\:cell-span-y-2 {
921 | grid-row: auto / span 2;
922 | }
923 |
924 | .sm\\\\:cell-start-x-3 {
925 | grid-column-start: 3 !important;
926 | }
927 |
928 | .sm\\\\:cell-span-x-3 {
929 | grid-column: auto / span 3;
930 | }
931 |
932 | .sm\\\\:cell-start-y-3 {
933 | grid-row-start: 3 !important;
934 | }
935 |
936 | .sm\\\\:cell-span-y-3 {
937 | grid-row: auto / span 3;
938 | }
939 |
940 | .sm\\\\:cell-start-x-4 {
941 | grid-column-start: 4 !important;
942 | }
943 |
944 | .sm\\\\:cell-span-x-4 {
945 | grid-column: auto / span 4;
946 | }
947 |
948 | .sm\\\\:cell-start-y-4 {
949 | grid-row-start: 4 !important;
950 | }
951 |
952 | .sm\\\\:cell-span-y-4 {
953 | grid-row: auto / span 4;
954 | }
955 |
956 | .sm\\\\:cell-start-x-5 {
957 | grid-column-start: 5 !important;
958 | }
959 |
960 | .sm\\\\:cell-span-x-5 {
961 | grid-column: auto / span 5;
962 | }
963 |
964 | .sm\\\\:cell-start-y-5 {
965 | grid-row-start: 5 !important;
966 | }
967 |
968 | .sm\\\\:cell-span-y-5 {
969 | grid-row: auto / span 5;
970 | }
971 |
972 | .sm\\\\:cell-start-x-6 {
973 | grid-column-start: 6 !important;
974 | }
975 |
976 | .sm\\\\:cell-span-x-6 {
977 | grid-column: auto / span 6;
978 | }
979 |
980 | .sm\\\\:cell-start-y-6 {
981 | grid-row-start: 6 !important;
982 | }
983 |
984 | .sm\\\\:cell-span-y-6 {
985 | grid-row: auto / span 6;
986 | }
987 | }"
988 | `;
989 |
990 | exports[`measure styles 1`] = `
991 | ".font-sans-400 {
992 | font-family: \\"IBM Plex Sans\\", sans-serif;
993 | font-weight: 400;
994 | font-style: normal;
995 | display: block;
996 | }
997 |
998 | .font-sans-400::before, .font-sans-400::after {
999 | content: '';
1000 | display: block;
1001 | height: 0;
1002 | }
1003 |
1004 | .font-sans-400.text-0\\\\/0 {
1005 | font-size: 10px;
1006 | line-height: 6.9799999999999995px;
1007 | padding-top: 0.4px;
1008 | padding-bottom: 0.4px;
1009 | }
1010 |
1011 | .font-sans-400.text-0\\\\/0::before {
1012 | margin-top: -0.6599999999999998px;
1013 | }
1014 |
1015 | .font-sans-400.text-0\\\\/0::after {
1016 | margin-bottom: -0.1399999999999998px;
1017 | }
1018 |
1019 | .font-sans-400.text-0\\\\/1 {
1020 | font-size: 10px;
1021 | line-height: 16.98px;
1022 | padding-top: 0.4px;
1023 | padding-bottom: 0.4px;
1024 | }
1025 |
1026 | .font-sans-400.text-0\\\\/1::before {
1027 | margin-top: -5.66px;
1028 | }
1029 |
1030 | .font-sans-400.text-0\\\\/1::after {
1031 | margin-bottom: -5.140000000000001px;
1032 | }
1033 |
1034 | .font-sans-400.text-0\\\\/2 {
1035 | font-size: 10px;
1036 | line-height: 26.98px;
1037 | padding-top: 0.4px;
1038 | padding-bottom: 0.4px;
1039 | }
1040 |
1041 | .font-sans-400.text-0\\\\/2::before {
1042 | margin-top: -10.66px;
1043 | }
1044 |
1045 | .font-sans-400.text-0\\\\/2::after {
1046 | margin-bottom: -10.14px;
1047 | }
1048 |
1049 | .font-sans-400.text-1\\\\/0 {
1050 | font-size: 20px;
1051 | line-height: 13.959999999999999px;
1052 | padding-top: 0.4px;
1053 | padding-bottom: 0.4px;
1054 | }
1055 |
1056 | .font-sans-400.text-1\\\\/0::before {
1057 | margin-top: -0.9199999999999996px;
1058 | }
1059 |
1060 | .font-sans-400.text-1\\\\/0::after {
1061 | margin-bottom: 0.12000000000000044px;
1062 | }
1063 |
1064 | .font-sans-400.text-1\\\\/1 {
1065 | font-size: 20px;
1066 | line-height: 23.96px;
1067 | padding-top: 0.4px;
1068 | padding-bottom: 0.4px;
1069 | }
1070 |
1071 | .font-sans-400.text-1\\\\/1::before {
1072 | margin-top: -5.920000000000001px;
1073 | }
1074 |
1075 | .font-sans-400.text-1\\\\/1::after {
1076 | margin-bottom: -4.880000000000001px;
1077 | }
1078 |
1079 | .font-sans-400.text-1\\\\/2 {
1080 | font-size: 20px;
1081 | line-height: 33.96px;
1082 | padding-top: 0.4px;
1083 | padding-bottom: 0.4px;
1084 | }
1085 |
1086 | .font-sans-400.text-1\\\\/2::before {
1087 | margin-top: -10.92px;
1088 | }
1089 |
1090 | .font-sans-400.text-1\\\\/2::after {
1091 | margin-bottom: -9.88px;
1092 | }
1093 |
1094 | .measure-0 {
1095 | max-width: 10ch;
1096 | }
1097 |
1098 | .measure-1 {
1099 | max-width: 20ch;
1100 | }
1101 |
1102 | @media (min-width: 640px) {
1103 | .font-sans-400.sm\\\\:text-0\\\\/0 {
1104 | font-size: 10px;
1105 | line-height: 6.9799999999999995px;
1106 | padding-top: 0.4px;
1107 | padding-bottom: 0.4px;
1108 | }
1109 |
1110 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
1111 | margin-top: -0.6599999999999998px;
1112 | }
1113 |
1114 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
1115 | margin-bottom: -0.1399999999999998px;
1116 | }
1117 |
1118 | .font-sans-400.sm\\\\:text-0\\\\/1 {
1119 | font-size: 10px;
1120 | line-height: 16.98px;
1121 | padding-top: 0.4px;
1122 | padding-bottom: 0.4px;
1123 | }
1124 |
1125 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
1126 | margin-top: -5.66px;
1127 | }
1128 |
1129 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
1130 | margin-bottom: -5.140000000000001px;
1131 | }
1132 |
1133 | .font-sans-400.sm\\\\:text-0\\\\/2 {
1134 | font-size: 10px;
1135 | line-height: 26.98px;
1136 | padding-top: 0.4px;
1137 | padding-bottom: 0.4px;
1138 | }
1139 |
1140 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
1141 | margin-top: -10.66px;
1142 | }
1143 |
1144 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
1145 | margin-bottom: -10.14px;
1146 | }
1147 |
1148 | .font-sans-400.sm\\\\:text-1\\\\/0 {
1149 | font-size: 20px;
1150 | line-height: 13.959999999999999px;
1151 | padding-top: 0.4px;
1152 | padding-bottom: 0.4px;
1153 | }
1154 |
1155 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
1156 | margin-top: -0.9199999999999996px;
1157 | }
1158 |
1159 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
1160 | margin-bottom: 0.12000000000000044px;
1161 | }
1162 |
1163 | .font-sans-400.sm\\\\:text-1\\\\/1 {
1164 | font-size: 20px;
1165 | line-height: 23.96px;
1166 | padding-top: 0.4px;
1167 | padding-bottom: 0.4px;
1168 | }
1169 |
1170 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
1171 | margin-top: -5.920000000000001px;
1172 | }
1173 |
1174 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
1175 | margin-bottom: -4.880000000000001px;
1176 | }
1177 |
1178 | .font-sans-400.sm\\\\:text-1\\\\/2 {
1179 | font-size: 20px;
1180 | line-height: 33.96px;
1181 | padding-top: 0.4px;
1182 | padding-bottom: 0.4px;
1183 | }
1184 |
1185 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
1186 | margin-top: -10.92px;
1187 | }
1188 |
1189 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
1190 | margin-bottom: -9.88px;
1191 | }
1192 |
1193 | .sm\\\\:measure-0 {
1194 | max-width: 10ch;
1195 | }
1196 |
1197 | .sm\\\\:measure-1 {
1198 | max-width: 20ch;
1199 | }
1200 | }"
1201 | `;
1202 |
1203 | exports[`rhythm styles 1`] = `
1204 | ".font-sans-400 {
1205 | font-family: \\"IBM Plex Sans\\", sans-serif;
1206 | font-weight: 400;
1207 | font-style: normal;
1208 | display: block;
1209 | }
1210 |
1211 | .font-sans-400::before, .font-sans-400::after {
1212 | content: '';
1213 | display: block;
1214 | height: 0;
1215 | }
1216 |
1217 | .font-sans-400.text-0\\\\/0 {
1218 | font-size: 10px;
1219 | line-height: 6.9799999999999995px;
1220 | padding-top: 0.4px;
1221 | padding-bottom: 0.4px;
1222 | }
1223 |
1224 | .font-sans-400.text-0\\\\/0::before {
1225 | margin-top: -0.6599999999999998px;
1226 | }
1227 |
1228 | .font-sans-400.text-0\\\\/0::after {
1229 | margin-bottom: -0.1399999999999998px;
1230 | }
1231 |
1232 | .font-sans-400.text-0\\\\/1 {
1233 | font-size: 10px;
1234 | line-height: 16.98px;
1235 | padding-top: 0.4px;
1236 | padding-bottom: 0.4px;
1237 | }
1238 |
1239 | .font-sans-400.text-0\\\\/1::before {
1240 | margin-top: -5.66px;
1241 | }
1242 |
1243 | .font-sans-400.text-0\\\\/1::after {
1244 | margin-bottom: -5.140000000000001px;
1245 | }
1246 |
1247 | .font-sans-400.text-0\\\\/2 {
1248 | font-size: 10px;
1249 | line-height: 26.98px;
1250 | padding-top: 0.4px;
1251 | padding-bottom: 0.4px;
1252 | }
1253 |
1254 | .font-sans-400.text-0\\\\/2::before {
1255 | margin-top: -10.66px;
1256 | }
1257 |
1258 | .font-sans-400.text-0\\\\/2::after {
1259 | margin-bottom: -10.14px;
1260 | }
1261 |
1262 | .font-sans-400.text-1\\\\/0 {
1263 | font-size: 20px;
1264 | line-height: 13.959999999999999px;
1265 | padding-top: 0.4px;
1266 | padding-bottom: 0.4px;
1267 | }
1268 |
1269 | .font-sans-400.text-1\\\\/0::before {
1270 | margin-top: -0.9199999999999996px;
1271 | }
1272 |
1273 | .font-sans-400.text-1\\\\/0::after {
1274 | margin-bottom: 0.12000000000000044px;
1275 | }
1276 |
1277 | .font-sans-400.text-1\\\\/1 {
1278 | font-size: 20px;
1279 | line-height: 23.96px;
1280 | padding-top: 0.4px;
1281 | padding-bottom: 0.4px;
1282 | }
1283 |
1284 | .font-sans-400.text-1\\\\/1::before {
1285 | margin-top: -5.920000000000001px;
1286 | }
1287 |
1288 | .font-sans-400.text-1\\\\/1::after {
1289 | margin-bottom: -4.880000000000001px;
1290 | }
1291 |
1292 | .font-sans-400.text-1\\\\/2 {
1293 | font-size: 20px;
1294 | line-height: 33.96px;
1295 | padding-top: 0.4px;
1296 | padding-bottom: 0.4px;
1297 | }
1298 |
1299 | .font-sans-400.text-1\\\\/2::before {
1300 | margin-top: -10.92px;
1301 | }
1302 |
1303 | .font-sans-400.text-1\\\\/2::after {
1304 | margin-bottom: -9.88px;
1305 | }
1306 |
1307 | .rhythm-0 > * + * {
1308 | margin-top: 0px;
1309 | }
1310 |
1311 | .rhythm-y-0 > * + * {
1312 | margin-top: 0px;
1313 | }
1314 |
1315 | .rhythm-x-0 > * + * {
1316 | margin-left: 0px;
1317 | }
1318 |
1319 | .rhythm-1 > * + * {
1320 | margin-top: 10px;
1321 | }
1322 |
1323 | .rhythm-y-1 > * + * {
1324 | margin-top: 10px;
1325 | }
1326 |
1327 | .rhythm-x-1 > * + * {
1328 | margin-left: 10px;
1329 | }
1330 |
1331 | .rhythm-2 > * + * {
1332 | margin-top: 20px;
1333 | }
1334 |
1335 | .rhythm-y-2 > * + * {
1336 | margin-top: 20px;
1337 | }
1338 |
1339 | .rhythm-x-2 > * + * {
1340 | margin-left: 20px;
1341 | }
1342 |
1343 | @media (min-width: 640px) {
1344 | .font-sans-400.sm\\\\:text-0\\\\/0 {
1345 | font-size: 10px;
1346 | line-height: 6.9799999999999995px;
1347 | padding-top: 0.4px;
1348 | padding-bottom: 0.4px;
1349 | }
1350 |
1351 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
1352 | margin-top: -0.6599999999999998px;
1353 | }
1354 |
1355 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
1356 | margin-bottom: -0.1399999999999998px;
1357 | }
1358 |
1359 | .font-sans-400.sm\\\\:text-0\\\\/1 {
1360 | font-size: 10px;
1361 | line-height: 16.98px;
1362 | padding-top: 0.4px;
1363 | padding-bottom: 0.4px;
1364 | }
1365 |
1366 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
1367 | margin-top: -5.66px;
1368 | }
1369 |
1370 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
1371 | margin-bottom: -5.140000000000001px;
1372 | }
1373 |
1374 | .font-sans-400.sm\\\\:text-0\\\\/2 {
1375 | font-size: 10px;
1376 | line-height: 26.98px;
1377 | padding-top: 0.4px;
1378 | padding-bottom: 0.4px;
1379 | }
1380 |
1381 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
1382 | margin-top: -10.66px;
1383 | }
1384 |
1385 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
1386 | margin-bottom: -10.14px;
1387 | }
1388 |
1389 | .font-sans-400.sm\\\\:text-1\\\\/0 {
1390 | font-size: 20px;
1391 | line-height: 13.959999999999999px;
1392 | padding-top: 0.4px;
1393 | padding-bottom: 0.4px;
1394 | }
1395 |
1396 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
1397 | margin-top: -0.9199999999999996px;
1398 | }
1399 |
1400 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
1401 | margin-bottom: 0.12000000000000044px;
1402 | }
1403 |
1404 | .font-sans-400.sm\\\\:text-1\\\\/1 {
1405 | font-size: 20px;
1406 | line-height: 23.96px;
1407 | padding-top: 0.4px;
1408 | padding-bottom: 0.4px;
1409 | }
1410 |
1411 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
1412 | margin-top: -5.920000000000001px;
1413 | }
1414 |
1415 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
1416 | margin-bottom: -4.880000000000001px;
1417 | }
1418 |
1419 | .font-sans-400.sm\\\\:text-1\\\\/2 {
1420 | font-size: 20px;
1421 | line-height: 33.96px;
1422 | padding-top: 0.4px;
1423 | padding-bottom: 0.4px;
1424 | }
1425 |
1426 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
1427 | margin-top: -10.92px;
1428 | }
1429 |
1430 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
1431 | margin-bottom: -9.88px;
1432 | }
1433 |
1434 | .sm\\\\:rhythm-0 > * + * {
1435 | margin-top: 0px;
1436 | }
1437 |
1438 | .sm\\\\:rhythm-y-0 > * + * {
1439 | margin-top: 0px;
1440 | }
1441 |
1442 | .sm\\\\:rhythm-x-0 > * + * {
1443 | margin-left: 0px;
1444 | }
1445 |
1446 | .sm\\\\:rhythm-1 > * + * {
1447 | margin-top: 10px;
1448 | }
1449 |
1450 | .sm\\\\:rhythm-y-1 > * + * {
1451 | margin-top: 10px;
1452 | }
1453 |
1454 | .sm\\\\:rhythm-x-1 > * + * {
1455 | margin-left: 10px;
1456 | }
1457 |
1458 | .sm\\\\:rhythm-2 > * + * {
1459 | margin-top: 20px;
1460 | }
1461 |
1462 | .sm\\\\:rhythm-y-2 > * + * {
1463 | margin-top: 20px;
1464 | }
1465 |
1466 | .sm\\\\:rhythm-x-2 > * + * {
1467 | margin-left: 20px;
1468 | }
1469 | }"
1470 | `;
1471 |
1472 | exports[`use px 1`] = `
1473 | ".font-sans-400 {
1474 | font-family: \\"IBM Plex Sans\\", sans-serif;
1475 | font-weight: 400;
1476 | font-style: normal;
1477 | display: block;
1478 | }
1479 |
1480 | .font-sans-400::before, .font-sans-400::after {
1481 | content: '';
1482 | display: block;
1483 | height: 0;
1484 | }
1485 |
1486 | .font-sans-400.text-0\\\\/0 {
1487 | font-size: 10px;
1488 | line-height: 10px;
1489 | padding-top: 3.42px;
1490 | padding-bottom: 0.4px;
1491 | }
1492 |
1493 | .font-sans-400.text-0\\\\/0::before {
1494 | margin-top: -2.17px;
1495 | }
1496 |
1497 | .font-sans-400.text-0\\\\/0::after {
1498 | margin-bottom: -1.65px;
1499 | }
1500 |
1501 | .font-sans-400.text-0\\\\/1 {
1502 | font-size: 10px;
1503 | line-height: 20px;
1504 | padding-top: 3.4199999999999995px;
1505 | padding-bottom: 0.4px;
1506 | }
1507 |
1508 | .font-sans-400.text-0\\\\/1::before {
1509 | margin-top: -7.17px;
1510 | }
1511 |
1512 | .font-sans-400.text-0\\\\/1::after {
1513 | margin-bottom: -6.65px;
1514 | }
1515 |
1516 | .font-sans-400.text-0\\\\/2 {
1517 | font-size: 10px;
1518 | line-height: 30px;
1519 | padding-top: 3.4199999999999995px;
1520 | padding-bottom: 0.4px;
1521 | }
1522 |
1523 | .font-sans-400.text-0\\\\/2::before {
1524 | margin-top: -12.17px;
1525 | }
1526 |
1527 | .font-sans-400.text-0\\\\/2::after {
1528 | margin-bottom: -11.65px;
1529 | }
1530 |
1531 | .font-sans-400.text-1\\\\/0 {
1532 | font-size: 20px;
1533 | line-height: 10px;
1534 | padding-top: -3.56px;
1535 | padding-bottom: 0.4px;
1536 | }
1537 |
1538 | .font-sans-400.text-1\\\\/0::before {
1539 | margin-top: 1.06px;
1540 | }
1541 |
1542 | .font-sans-400.text-1\\\\/0::after {
1543 | margin-bottom: 2.1px;
1544 | }
1545 |
1546 | .font-sans-400.text-1\\\\/1 {
1547 | font-size: 20px;
1548 | line-height: 20px;
1549 | padding-top: 6.44px;
1550 | padding-bottom: 0.4px;
1551 | }
1552 |
1553 | .font-sans-400.text-1\\\\/1::before {
1554 | margin-top: -3.94px;
1555 | }
1556 |
1557 | .font-sans-400.text-1\\\\/1::after {
1558 | margin-bottom: -2.9px;
1559 | }
1560 |
1561 | .font-sans-400.text-1\\\\/2 {
1562 | font-size: 20px;
1563 | line-height: 30px;
1564 | padding-top: 6.4399999999999995px;
1565 | padding-bottom: 0.4px;
1566 | }
1567 |
1568 | .font-sans-400.text-1\\\\/2::before {
1569 | margin-top: -8.94px;
1570 | }
1571 |
1572 | .font-sans-400.text-1\\\\/2::after {
1573 | margin-bottom: -7.9px;
1574 | }
1575 |
1576 | .bg-baseline {
1577 | position: relative;
1578 | background-repeat: repeat;
1579 | background-image: linear-gradient(
1580 | rgba(255, 0, 255, 0.3) 1px,
1581 | transparent 0
1582 | );
1583 | background-size: 100% 10px;
1584 | }
1585 |
1586 | .measure-0 {
1587 | max-width: 10ch;
1588 | }
1589 |
1590 | .measure-1 {
1591 | max-width: 20ch;
1592 | }
1593 |
1594 | .rhythm-0 > * + * {
1595 | margin-top: 0px;
1596 | }
1597 |
1598 | .rhythm-y-0 > * + * {
1599 | margin-top: 0px;
1600 | }
1601 |
1602 | .rhythm-x-0 > * + * {
1603 | margin-left: 0px;
1604 | }
1605 |
1606 | .rhythm-1 > * + * {
1607 | margin-top: 10px;
1608 | }
1609 |
1610 | .rhythm-y-1 > * + * {
1611 | margin-top: 10px;
1612 | }
1613 |
1614 | .rhythm-x-1 > * + * {
1615 | margin-left: 10px;
1616 | }
1617 |
1618 | .rhythm-2 > * + * {
1619 | margin-top: 20px;
1620 | }
1621 |
1622 | .rhythm-y-2 > * + * {
1623 | margin-top: 20px;
1624 | }
1625 |
1626 | .rhythm-x-2 > * + * {
1627 | margin-left: 20px;
1628 | }
1629 |
1630 | .matrix-0 {
1631 | display: grid;
1632 | grid-template-columns: repeat(1, minmax(auto,1fr));
1633 | }
1634 |
1635 | .matrix-1 {
1636 | display: grid;
1637 | grid-template-columns: repeat(1, minmax(auto,1fr));
1638 | }
1639 |
1640 | .matrix-2 {
1641 | display: grid;
1642 | grid-template-columns: repeat(2, minmax(auto,1fr));
1643 | }
1644 |
1645 | .matrix-3 {
1646 | display: grid;
1647 | grid-template-columns: repeat(3, minmax(auto,1fr));
1648 | }
1649 |
1650 | .matrix-4 {
1651 | display: grid;
1652 | grid-template-columns: repeat(4, minmax(auto,1fr));
1653 | }
1654 |
1655 | .matrix-5 {
1656 | display: grid;
1657 | grid-template-columns: repeat(5, minmax(auto,1fr));
1658 | }
1659 |
1660 | .matrix-6 {
1661 | display: grid;
1662 | grid-template-columns: repeat(6, minmax(auto,1fr));
1663 | }
1664 |
1665 | .matrix-row-h-0 {
1666 | grid-auto-rows: minmax(0px, auto);
1667 | }
1668 |
1669 | .matrix-gap-0 {
1670 | grid-row-gap: 0px;
1671 | grid-column-gap: 0px;
1672 | }
1673 |
1674 | .matrix-gap-x-0 {
1675 | grid-column-gap: 0px;
1676 | }
1677 |
1678 | .matrix-gap-y-0 {
1679 | grid-row-gap: 0px;
1680 | }
1681 |
1682 | .matrix-row-h-1 {
1683 | grid-auto-rows: minmax(10px, auto);
1684 | }
1685 |
1686 | .matrix-gap-1 {
1687 | grid-row-gap: 10px;
1688 | grid-column-gap: 10px;
1689 | }
1690 |
1691 | .matrix-gap-x-1 {
1692 | grid-column-gap: 10px;
1693 | }
1694 |
1695 | .matrix-gap-y-1 {
1696 | grid-row-gap: 10px;
1697 | }
1698 |
1699 | .matrix-row-h-2 {
1700 | grid-auto-rows: minmax(20px, auto);
1701 | }
1702 |
1703 | .matrix-gap-2 {
1704 | grid-row-gap: 20px;
1705 | grid-column-gap: 20px;
1706 | }
1707 |
1708 | .matrix-gap-x-2 {
1709 | grid-column-gap: 20px;
1710 | }
1711 |
1712 | .matrix-gap-y-2 {
1713 | grid-row-gap: 20px;
1714 | }
1715 |
1716 | .cell-start-x-1 {
1717 | grid-column-start: 1 !important;
1718 | }
1719 |
1720 | .cell-span-x-1 {
1721 | grid-column: auto / span 1;
1722 | }
1723 |
1724 | .cell-start-y-1 {
1725 | grid-row-start: 1 !important;
1726 | }
1727 |
1728 | .cell-span-y-1 {
1729 | grid-row: auto / span 1;
1730 | }
1731 |
1732 | .cell-start-x-1 {
1733 | grid-column-start: 1 !important;
1734 | }
1735 |
1736 | .cell-span-x-1 {
1737 | grid-column: auto / span 1;
1738 | }
1739 |
1740 | .cell-start-y-1 {
1741 | grid-row-start: 1 !important;
1742 | }
1743 |
1744 | .cell-span-y-1 {
1745 | grid-row: auto / span 1;
1746 | }
1747 |
1748 | .cell-start-x-2 {
1749 | grid-column-start: 2 !important;
1750 | }
1751 |
1752 | .cell-span-x-2 {
1753 | grid-column: auto / span 2;
1754 | }
1755 |
1756 | .cell-start-y-2 {
1757 | grid-row-start: 2 !important;
1758 | }
1759 |
1760 | .cell-span-y-2 {
1761 | grid-row: auto / span 2;
1762 | }
1763 |
1764 | .cell-start-x-3 {
1765 | grid-column-start: 3 !important;
1766 | }
1767 |
1768 | .cell-span-x-3 {
1769 | grid-column: auto / span 3;
1770 | }
1771 |
1772 | .cell-start-y-3 {
1773 | grid-row-start: 3 !important;
1774 | }
1775 |
1776 | .cell-span-y-3 {
1777 | grid-row: auto / span 3;
1778 | }
1779 |
1780 | .cell-start-x-4 {
1781 | grid-column-start: 4 !important;
1782 | }
1783 |
1784 | .cell-span-x-4 {
1785 | grid-column: auto / span 4;
1786 | }
1787 |
1788 | .cell-start-y-4 {
1789 | grid-row-start: 4 !important;
1790 | }
1791 |
1792 | .cell-span-y-4 {
1793 | grid-row: auto / span 4;
1794 | }
1795 |
1796 | .cell-start-x-5 {
1797 | grid-column-start: 5 !important;
1798 | }
1799 |
1800 | .cell-span-x-5 {
1801 | grid-column: auto / span 5;
1802 | }
1803 |
1804 | .cell-start-y-5 {
1805 | grid-row-start: 5 !important;
1806 | }
1807 |
1808 | .cell-span-y-5 {
1809 | grid-row: auto / span 5;
1810 | }
1811 |
1812 | .cell-start-x-6 {
1813 | grid-column-start: 6 !important;
1814 | }
1815 |
1816 | .cell-span-x-6 {
1817 | grid-column: auto / span 6;
1818 | }
1819 |
1820 | .cell-start-y-6 {
1821 | grid-row-start: 6 !important;
1822 | }
1823 |
1824 | .cell-span-y-6 {
1825 | grid-row: auto / span 6;
1826 | }
1827 |
1828 | @media (min-width: 640px) {
1829 | .font-sans-400.sm\\\\:text-0\\\\/0 {
1830 | font-size: 10px;
1831 | line-height: 10px;
1832 | padding-top: 3.42px;
1833 | padding-bottom: 0.4px;
1834 | }
1835 |
1836 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
1837 | margin-top: -2.17px;
1838 | }
1839 |
1840 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
1841 | margin-bottom: -1.65px;
1842 | }
1843 |
1844 | .font-sans-400.sm\\\\:text-0\\\\/1 {
1845 | font-size: 10px;
1846 | line-height: 20px;
1847 | padding-top: 3.4199999999999995px;
1848 | padding-bottom: 0.4px;
1849 | }
1850 |
1851 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
1852 | margin-top: -7.17px;
1853 | }
1854 |
1855 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
1856 | margin-bottom: -6.65px;
1857 | }
1858 |
1859 | .font-sans-400.sm\\\\:text-0\\\\/2 {
1860 | font-size: 10px;
1861 | line-height: 30px;
1862 | padding-top: 3.4199999999999995px;
1863 | padding-bottom: 0.4px;
1864 | }
1865 |
1866 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
1867 | margin-top: -12.17px;
1868 | }
1869 |
1870 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
1871 | margin-bottom: -11.65px;
1872 | }
1873 |
1874 | .font-sans-400.sm\\\\:text-1\\\\/0 {
1875 | font-size: 20px;
1876 | line-height: 10px;
1877 | padding-top: -3.56px;
1878 | padding-bottom: 0.4px;
1879 | }
1880 |
1881 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
1882 | margin-top: 1.06px;
1883 | }
1884 |
1885 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
1886 | margin-bottom: 2.1px;
1887 | }
1888 |
1889 | .font-sans-400.sm\\\\:text-1\\\\/1 {
1890 | font-size: 20px;
1891 | line-height: 20px;
1892 | padding-top: 6.44px;
1893 | padding-bottom: 0.4px;
1894 | }
1895 |
1896 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
1897 | margin-top: -3.94px;
1898 | }
1899 |
1900 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
1901 | margin-bottom: -2.9px;
1902 | }
1903 |
1904 | .font-sans-400.sm\\\\:text-1\\\\/2 {
1905 | font-size: 20px;
1906 | line-height: 30px;
1907 | padding-top: 6.4399999999999995px;
1908 | padding-bottom: 0.4px;
1909 | }
1910 |
1911 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
1912 | margin-top: -8.94px;
1913 | }
1914 |
1915 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
1916 | margin-bottom: -7.9px;
1917 | }
1918 |
1919 | .sm\\\\:measure-0 {
1920 | max-width: 10ch;
1921 | }
1922 |
1923 | .sm\\\\:measure-1 {
1924 | max-width: 20ch;
1925 | }
1926 |
1927 | .sm\\\\:rhythm-0 > * + * {
1928 | margin-top: 0px;
1929 | }
1930 |
1931 | .sm\\\\:rhythm-y-0 > * + * {
1932 | margin-top: 0px;
1933 | }
1934 |
1935 | .sm\\\\:rhythm-x-0 > * + * {
1936 | margin-left: 0px;
1937 | }
1938 |
1939 | .sm\\\\:rhythm-1 > * + * {
1940 | margin-top: 10px;
1941 | }
1942 |
1943 | .sm\\\\:rhythm-y-1 > * + * {
1944 | margin-top: 10px;
1945 | }
1946 |
1947 | .sm\\\\:rhythm-x-1 > * + * {
1948 | margin-left: 10px;
1949 | }
1950 |
1951 | .sm\\\\:rhythm-2 > * + * {
1952 | margin-top: 20px;
1953 | }
1954 |
1955 | .sm\\\\:rhythm-y-2 > * + * {
1956 | margin-top: 20px;
1957 | }
1958 |
1959 | .sm\\\\:rhythm-x-2 > * + * {
1960 | margin-left: 20px;
1961 | }
1962 |
1963 | .sm\\\\:matrix-0 {
1964 | display: grid;
1965 | grid-template-columns: repeat(1, minmax(auto,1fr));
1966 | }
1967 |
1968 | .sm\\\\:matrix-1 {
1969 | display: grid;
1970 | grid-template-columns: repeat(1, minmax(auto,1fr));
1971 | }
1972 |
1973 | .sm\\\\:matrix-2 {
1974 | display: grid;
1975 | grid-template-columns: repeat(2, minmax(auto,1fr));
1976 | }
1977 |
1978 | .sm\\\\:matrix-3 {
1979 | display: grid;
1980 | grid-template-columns: repeat(3, minmax(auto,1fr));
1981 | }
1982 |
1983 | .sm\\\\:matrix-4 {
1984 | display: grid;
1985 | grid-template-columns: repeat(4, minmax(auto,1fr));
1986 | }
1987 |
1988 | .sm\\\\:matrix-5 {
1989 | display: grid;
1990 | grid-template-columns: repeat(5, minmax(auto,1fr));
1991 | }
1992 |
1993 | .sm\\\\:matrix-6 {
1994 | display: grid;
1995 | grid-template-columns: repeat(6, minmax(auto,1fr));
1996 | }
1997 |
1998 | .sm\\\\:matrix-row-h-0 {
1999 | grid-auto-rows: minmax(0px, auto);
2000 | }
2001 |
2002 | .sm\\\\:matrix-gap-0 {
2003 | grid-row-gap: 0px;
2004 | grid-column-gap: 0px;
2005 | }
2006 |
2007 | .sm\\\\:matrix-gap-x-0 {
2008 | grid-column-gap: 0px;
2009 | }
2010 |
2011 | .sm\\\\:matrix-gap-y-0 {
2012 | grid-row-gap: 0px;
2013 | }
2014 |
2015 | .sm\\\\:matrix-row-h-1 {
2016 | grid-auto-rows: minmax(10px, auto);
2017 | }
2018 |
2019 | .sm\\\\:matrix-gap-1 {
2020 | grid-row-gap: 10px;
2021 | grid-column-gap: 10px;
2022 | }
2023 |
2024 | .sm\\\\:matrix-gap-x-1 {
2025 | grid-column-gap: 10px;
2026 | }
2027 |
2028 | .sm\\\\:matrix-gap-y-1 {
2029 | grid-row-gap: 10px;
2030 | }
2031 |
2032 | .sm\\\\:matrix-row-h-2 {
2033 | grid-auto-rows: minmax(20px, auto);
2034 | }
2035 |
2036 | .sm\\\\:matrix-gap-2 {
2037 | grid-row-gap: 20px;
2038 | grid-column-gap: 20px;
2039 | }
2040 |
2041 | .sm\\\\:matrix-gap-x-2 {
2042 | grid-column-gap: 20px;
2043 | }
2044 |
2045 | .sm\\\\:matrix-gap-y-2 {
2046 | grid-row-gap: 20px;
2047 | }
2048 |
2049 | .sm\\\\:cell-start-x-1 {
2050 | grid-column-start: 1 !important;
2051 | }
2052 |
2053 | .sm\\\\:cell-span-x-1 {
2054 | grid-column: auto / span 1;
2055 | }
2056 |
2057 | .sm\\\\:cell-start-y-1 {
2058 | grid-row-start: 1 !important;
2059 | }
2060 |
2061 | .sm\\\\:cell-span-y-1 {
2062 | grid-row: auto / span 1;
2063 | }
2064 |
2065 | .sm\\\\:cell-start-x-1 {
2066 | grid-column-start: 1 !important;
2067 | }
2068 |
2069 | .sm\\\\:cell-span-x-1 {
2070 | grid-column: auto / span 1;
2071 | }
2072 |
2073 | .sm\\\\:cell-start-y-1 {
2074 | grid-row-start: 1 !important;
2075 | }
2076 |
2077 | .sm\\\\:cell-span-y-1 {
2078 | grid-row: auto / span 1;
2079 | }
2080 |
2081 | .sm\\\\:cell-start-x-2 {
2082 | grid-column-start: 2 !important;
2083 | }
2084 |
2085 | .sm\\\\:cell-span-x-2 {
2086 | grid-column: auto / span 2;
2087 | }
2088 |
2089 | .sm\\\\:cell-start-y-2 {
2090 | grid-row-start: 2 !important;
2091 | }
2092 |
2093 | .sm\\\\:cell-span-y-2 {
2094 | grid-row: auto / span 2;
2095 | }
2096 |
2097 | .sm\\\\:cell-start-x-3 {
2098 | grid-column-start: 3 !important;
2099 | }
2100 |
2101 | .sm\\\\:cell-span-x-3 {
2102 | grid-column: auto / span 3;
2103 | }
2104 |
2105 | .sm\\\\:cell-start-y-3 {
2106 | grid-row-start: 3 !important;
2107 | }
2108 |
2109 | .sm\\\\:cell-span-y-3 {
2110 | grid-row: auto / span 3;
2111 | }
2112 |
2113 | .sm\\\\:cell-start-x-4 {
2114 | grid-column-start: 4 !important;
2115 | }
2116 |
2117 | .sm\\\\:cell-span-x-4 {
2118 | grid-column: auto / span 4;
2119 | }
2120 |
2121 | .sm\\\\:cell-start-y-4 {
2122 | grid-row-start: 4 !important;
2123 | }
2124 |
2125 | .sm\\\\:cell-span-y-4 {
2126 | grid-row: auto / span 4;
2127 | }
2128 |
2129 | .sm\\\\:cell-start-x-5 {
2130 | grid-column-start: 5 !important;
2131 | }
2132 |
2133 | .sm\\\\:cell-span-x-5 {
2134 | grid-column: auto / span 5;
2135 | }
2136 |
2137 | .sm\\\\:cell-start-y-5 {
2138 | grid-row-start: 5 !important;
2139 | }
2140 |
2141 | .sm\\\\:cell-span-y-5 {
2142 | grid-row: auto / span 5;
2143 | }
2144 |
2145 | .sm\\\\:cell-start-x-6 {
2146 | grid-column-start: 6 !important;
2147 | }
2148 |
2149 | .sm\\\\:cell-span-x-6 {
2150 | grid-column: auto / span 6;
2151 | }
2152 |
2153 | .sm\\\\:cell-start-y-6 {
2154 | grid-row-start: 6 !important;
2155 | }
2156 |
2157 | .sm\\\\:cell-span-y-6 {
2158 | grid-row: auto / span 6;
2159 | }
2160 | }"
2161 | `;
2162 |
2163 | exports[`use rem 1`] = `
2164 | ".font-sans-400 {
2165 | font-family: \\"IBM Plex Sans\\", sans-serif;
2166 | font-weight: 400;
2167 | font-style: normal;
2168 | display: block;
2169 | }
2170 |
2171 | .font-sans-400::before, .font-sans-400::after {
2172 | content: '';
2173 | display: block;
2174 | height: 0;
2175 | }
2176 |
2177 | .font-sans-400.text-0\\\\/0 {
2178 | font-size: 1rem;
2179 | line-height: 1;
2180 | padding-top: 0.34199999999999997em;
2181 | padding-bottom: 0.04em;
2182 | }
2183 |
2184 | .font-sans-400.text-0\\\\/0::before {
2185 | margin-top: -0.217em;
2186 | }
2187 |
2188 | .font-sans-400.text-0\\\\/0::after {
2189 | margin-bottom: -0.16499999999999998em;
2190 | }
2191 |
2192 | .font-sans-400.text-0\\\\/1 {
2193 | font-size: 1rem;
2194 | line-height: 2;
2195 | padding-top: 0.34199999999999997em;
2196 | padding-bottom: 0.04em;
2197 | }
2198 |
2199 | .font-sans-400.text-0\\\\/1::before {
2200 | margin-top: -0.717em;
2201 | }
2202 |
2203 | .font-sans-400.text-0\\\\/1::after {
2204 | margin-bottom: -0.665em;
2205 | }
2206 |
2207 | .font-sans-400.text-0\\\\/2 {
2208 | font-size: 1rem;
2209 | line-height: 3;
2210 | padding-top: 0.34199999999999997em;
2211 | padding-bottom: 0.04em;
2212 | }
2213 |
2214 | .font-sans-400.text-0\\\\/2::before {
2215 | margin-top: -1.217em;
2216 | }
2217 |
2218 | .font-sans-400.text-0\\\\/2::after {
2219 | margin-bottom: -1.165em;
2220 | }
2221 |
2222 | .font-sans-400.text-1\\\\/0 {
2223 | font-size: 2rem;
2224 | line-height: 0.5;
2225 | padding-top: -0.178em;
2226 | padding-bottom: 0.02em;
2227 | }
2228 |
2229 | .font-sans-400.text-1\\\\/0::before {
2230 | margin-top: 0.053000000000000005em;
2231 | }
2232 |
2233 | .font-sans-400.text-1\\\\/0::after {
2234 | margin-bottom: 0.10500000000000001em;
2235 | }
2236 |
2237 | .font-sans-400.text-1\\\\/1 {
2238 | font-size: 2rem;
2239 | line-height: 1;
2240 | padding-top: 0.322em;
2241 | padding-bottom: 0.02em;
2242 | }
2243 |
2244 | .font-sans-400.text-1\\\\/1::before {
2245 | margin-top: -0.197em;
2246 | }
2247 |
2248 | .font-sans-400.text-1\\\\/1::after {
2249 | margin-bottom: -0.145em;
2250 | }
2251 |
2252 | .font-sans-400.text-1\\\\/2 {
2253 | font-size: 2rem;
2254 | line-height: 1.5;
2255 | padding-top: 0.32199999999999995em;
2256 | padding-bottom: 0.02em;
2257 | }
2258 |
2259 | .font-sans-400.text-1\\\\/2::before {
2260 | margin-top: -0.44699999999999995em;
2261 | }
2262 |
2263 | .font-sans-400.text-1\\\\/2::after {
2264 | margin-bottom: -0.395em;
2265 | }
2266 |
2267 | .bg-baseline {
2268 | position: relative;
2269 | background-repeat: repeat;
2270 | background-size: 100% 1rem;
2271 | background-image: linear-gradient(
2272 | rgba(255, 0, 255, 0.3) 1px,
2273 | transparent 0
2274 | );
2275 | }
2276 |
2277 | .measure-0 {
2278 | max-width: 10ch;
2279 | }
2280 |
2281 | .measure-1 {
2282 | max-width: 20ch;
2283 | }
2284 |
2285 | .rhythm-0 > * + * {
2286 | margin-top: 0rem;
2287 | }
2288 |
2289 | .rhythm-y-0 > * + * {
2290 | margin-top: 0rem;
2291 | }
2292 |
2293 | .rhythm-x-0 > * + * {
2294 | margin-left: 0rem;
2295 | }
2296 |
2297 | .rhythm-1 > * + * {
2298 | margin-top: 1rem;
2299 | }
2300 |
2301 | .rhythm-y-1 > * + * {
2302 | margin-top: 1rem;
2303 | }
2304 |
2305 | .rhythm-x-1 > * + * {
2306 | margin-left: 1rem;
2307 | }
2308 |
2309 | .rhythm-2 > * + * {
2310 | margin-top: 2rem;
2311 | }
2312 |
2313 | .rhythm-y-2 > * + * {
2314 | margin-top: 2rem;
2315 | }
2316 |
2317 | .rhythm-x-2 > * + * {
2318 | margin-left: 2rem;
2319 | }
2320 |
2321 | .matrix-0 {
2322 | display: grid;
2323 | grid-template-columns: repeat(1, minmax(auto,1fr));
2324 | }
2325 |
2326 | .matrix-1 {
2327 | display: grid;
2328 | grid-template-columns: repeat(1, minmax(auto,1fr));
2329 | }
2330 |
2331 | .matrix-2 {
2332 | display: grid;
2333 | grid-template-columns: repeat(2, minmax(auto,1fr));
2334 | }
2335 |
2336 | .matrix-3 {
2337 | display: grid;
2338 | grid-template-columns: repeat(3, minmax(auto,1fr));
2339 | }
2340 |
2341 | .matrix-4 {
2342 | display: grid;
2343 | grid-template-columns: repeat(4, minmax(auto,1fr));
2344 | }
2345 |
2346 | .matrix-5 {
2347 | display: grid;
2348 | grid-template-columns: repeat(5, minmax(auto,1fr));
2349 | }
2350 |
2351 | .matrix-6 {
2352 | display: grid;
2353 | grid-template-columns: repeat(6, minmax(auto,1fr));
2354 | }
2355 |
2356 | .matrix-row-h-0 {
2357 | grid-auto-rows: minmax(0rem, auto);
2358 | }
2359 |
2360 | .matrix-gap-0 {
2361 | grid-row-gap: 0rem;
2362 | grid-column-gap: 0rem;
2363 | }
2364 |
2365 | .matrix-gap-x-0 {
2366 | grid-column-gap: 0rem;
2367 | }
2368 |
2369 | .matrix-gap-y-0 {
2370 | grid-row-gap: 0rem;
2371 | }
2372 |
2373 | .matrix-row-h-1 {
2374 | grid-auto-rows: minmax(1rem, auto);
2375 | }
2376 |
2377 | .matrix-gap-1 {
2378 | grid-row-gap: 1rem;
2379 | grid-column-gap: 1rem;
2380 | }
2381 |
2382 | .matrix-gap-x-1 {
2383 | grid-column-gap: 1rem;
2384 | }
2385 |
2386 | .matrix-gap-y-1 {
2387 | grid-row-gap: 1rem;
2388 | }
2389 |
2390 | .matrix-row-h-2 {
2391 | grid-auto-rows: minmax(2rem, auto);
2392 | }
2393 |
2394 | .matrix-gap-2 {
2395 | grid-row-gap: 2rem;
2396 | grid-column-gap: 2rem;
2397 | }
2398 |
2399 | .matrix-gap-x-2 {
2400 | grid-column-gap: 2rem;
2401 | }
2402 |
2403 | .matrix-gap-y-2 {
2404 | grid-row-gap: 2rem;
2405 | }
2406 |
2407 | .cell-start-x-1 {
2408 | grid-column-start: 1 !important;
2409 | }
2410 |
2411 | .cell-span-x-1 {
2412 | grid-column: auto / span 1;
2413 | }
2414 |
2415 | .cell-start-y-1 {
2416 | grid-row-start: 1 !important;
2417 | }
2418 |
2419 | .cell-span-y-1 {
2420 | grid-row: auto / span 1;
2421 | }
2422 |
2423 | .cell-start-x-1 {
2424 | grid-column-start: 1 !important;
2425 | }
2426 |
2427 | .cell-span-x-1 {
2428 | grid-column: auto / span 1;
2429 | }
2430 |
2431 | .cell-start-y-1 {
2432 | grid-row-start: 1 !important;
2433 | }
2434 |
2435 | .cell-span-y-1 {
2436 | grid-row: auto / span 1;
2437 | }
2438 |
2439 | .cell-start-x-2 {
2440 | grid-column-start: 2 !important;
2441 | }
2442 |
2443 | .cell-span-x-2 {
2444 | grid-column: auto / span 2;
2445 | }
2446 |
2447 | .cell-start-y-2 {
2448 | grid-row-start: 2 !important;
2449 | }
2450 |
2451 | .cell-span-y-2 {
2452 | grid-row: auto / span 2;
2453 | }
2454 |
2455 | .cell-start-x-3 {
2456 | grid-column-start: 3 !important;
2457 | }
2458 |
2459 | .cell-span-x-3 {
2460 | grid-column: auto / span 3;
2461 | }
2462 |
2463 | .cell-start-y-3 {
2464 | grid-row-start: 3 !important;
2465 | }
2466 |
2467 | .cell-span-y-3 {
2468 | grid-row: auto / span 3;
2469 | }
2470 |
2471 | .cell-start-x-4 {
2472 | grid-column-start: 4 !important;
2473 | }
2474 |
2475 | .cell-span-x-4 {
2476 | grid-column: auto / span 4;
2477 | }
2478 |
2479 | .cell-start-y-4 {
2480 | grid-row-start: 4 !important;
2481 | }
2482 |
2483 | .cell-span-y-4 {
2484 | grid-row: auto / span 4;
2485 | }
2486 |
2487 | .cell-start-x-5 {
2488 | grid-column-start: 5 !important;
2489 | }
2490 |
2491 | .cell-span-x-5 {
2492 | grid-column: auto / span 5;
2493 | }
2494 |
2495 | .cell-start-y-5 {
2496 | grid-row-start: 5 !important;
2497 | }
2498 |
2499 | .cell-span-y-5 {
2500 | grid-row: auto / span 5;
2501 | }
2502 |
2503 | .cell-start-x-6 {
2504 | grid-column-start: 6 !important;
2505 | }
2506 |
2507 | .cell-span-x-6 {
2508 | grid-column: auto / span 6;
2509 | }
2510 |
2511 | .cell-start-y-6 {
2512 | grid-row-start: 6 !important;
2513 | }
2514 |
2515 | .cell-span-y-6 {
2516 | grid-row: auto / span 6;
2517 | }
2518 |
2519 | @media (min-width: 640px) {
2520 | .font-sans-400.sm\\\\:text-0\\\\/0 {
2521 | font-size: 1rem;
2522 | line-height: 1;
2523 | padding-top: 0.34199999999999997em;
2524 | padding-bottom: 0.04em;
2525 | }
2526 |
2527 | .font-sans-400.sm\\\\:text-0\\\\/0::before {
2528 | margin-top: -0.217em;
2529 | }
2530 |
2531 | .font-sans-400.sm\\\\:text-0\\\\/0::after {
2532 | margin-bottom: -0.16499999999999998em;
2533 | }
2534 |
2535 | .font-sans-400.sm\\\\:text-0\\\\/1 {
2536 | font-size: 1rem;
2537 | line-height: 2;
2538 | padding-top: 0.34199999999999997em;
2539 | padding-bottom: 0.04em;
2540 | }
2541 |
2542 | .font-sans-400.sm\\\\:text-0\\\\/1::before {
2543 | margin-top: -0.717em;
2544 | }
2545 |
2546 | .font-sans-400.sm\\\\:text-0\\\\/1::after {
2547 | margin-bottom: -0.665em;
2548 | }
2549 |
2550 | .font-sans-400.sm\\\\:text-0\\\\/2 {
2551 | font-size: 1rem;
2552 | line-height: 3;
2553 | padding-top: 0.34199999999999997em;
2554 | padding-bottom: 0.04em;
2555 | }
2556 |
2557 | .font-sans-400.sm\\\\:text-0\\\\/2::before {
2558 | margin-top: -1.217em;
2559 | }
2560 |
2561 | .font-sans-400.sm\\\\:text-0\\\\/2::after {
2562 | margin-bottom: -1.165em;
2563 | }
2564 |
2565 | .font-sans-400.sm\\\\:text-1\\\\/0 {
2566 | font-size: 2rem;
2567 | line-height: 0.5;
2568 | padding-top: -0.178em;
2569 | padding-bottom: 0.02em;
2570 | }
2571 |
2572 | .font-sans-400.sm\\\\:text-1\\\\/0::before {
2573 | margin-top: 0.053000000000000005em;
2574 | }
2575 |
2576 | .font-sans-400.sm\\\\:text-1\\\\/0::after {
2577 | margin-bottom: 0.10500000000000001em;
2578 | }
2579 |
2580 | .font-sans-400.sm\\\\:text-1\\\\/1 {
2581 | font-size: 2rem;
2582 | line-height: 1;
2583 | padding-top: 0.322em;
2584 | padding-bottom: 0.02em;
2585 | }
2586 |
2587 | .font-sans-400.sm\\\\:text-1\\\\/1::before {
2588 | margin-top: -0.197em;
2589 | }
2590 |
2591 | .font-sans-400.sm\\\\:text-1\\\\/1::after {
2592 | margin-bottom: -0.145em;
2593 | }
2594 |
2595 | .font-sans-400.sm\\\\:text-1\\\\/2 {
2596 | font-size: 2rem;
2597 | line-height: 1.5;
2598 | padding-top: 0.32199999999999995em;
2599 | padding-bottom: 0.02em;
2600 | }
2601 |
2602 | .font-sans-400.sm\\\\:text-1\\\\/2::before {
2603 | margin-top: -0.44699999999999995em;
2604 | }
2605 |
2606 | .font-sans-400.sm\\\\:text-1\\\\/2::after {
2607 | margin-bottom: -0.395em;
2608 | }
2609 |
2610 | .sm\\\\:measure-0 {
2611 | max-width: 10ch;
2612 | }
2613 |
2614 | .sm\\\\:measure-1 {
2615 | max-width: 20ch;
2616 | }
2617 |
2618 | .sm\\\\:rhythm-0 > * + * {
2619 | margin-top: 0rem;
2620 | }
2621 |
2622 | .sm\\\\:rhythm-y-0 > * + * {
2623 | margin-top: 0rem;
2624 | }
2625 |
2626 | .sm\\\\:rhythm-x-0 > * + * {
2627 | margin-left: 0rem;
2628 | }
2629 |
2630 | .sm\\\\:rhythm-1 > * + * {
2631 | margin-top: 1rem;
2632 | }
2633 |
2634 | .sm\\\\:rhythm-y-1 > * + * {
2635 | margin-top: 1rem;
2636 | }
2637 |
2638 | .sm\\\\:rhythm-x-1 > * + * {
2639 | margin-left: 1rem;
2640 | }
2641 |
2642 | .sm\\\\:rhythm-2 > * + * {
2643 | margin-top: 2rem;
2644 | }
2645 |
2646 | .sm\\\\:rhythm-y-2 > * + * {
2647 | margin-top: 2rem;
2648 | }
2649 |
2650 | .sm\\\\:rhythm-x-2 > * + * {
2651 | margin-left: 2rem;
2652 | }
2653 |
2654 | .sm\\\\:matrix-0 {
2655 | display: grid;
2656 | grid-template-columns: repeat(1, minmax(auto,1fr));
2657 | }
2658 |
2659 | .sm\\\\:matrix-1 {
2660 | display: grid;
2661 | grid-template-columns: repeat(1, minmax(auto,1fr));
2662 | }
2663 |
2664 | .sm\\\\:matrix-2 {
2665 | display: grid;
2666 | grid-template-columns: repeat(2, minmax(auto,1fr));
2667 | }
2668 |
2669 | .sm\\\\:matrix-3 {
2670 | display: grid;
2671 | grid-template-columns: repeat(3, minmax(auto,1fr));
2672 | }
2673 |
2674 | .sm\\\\:matrix-4 {
2675 | display: grid;
2676 | grid-template-columns: repeat(4, minmax(auto,1fr));
2677 | }
2678 |
2679 | .sm\\\\:matrix-5 {
2680 | display: grid;
2681 | grid-template-columns: repeat(5, minmax(auto,1fr));
2682 | }
2683 |
2684 | .sm\\\\:matrix-6 {
2685 | display: grid;
2686 | grid-template-columns: repeat(6, minmax(auto,1fr));
2687 | }
2688 |
2689 | .sm\\\\:matrix-row-h-0 {
2690 | grid-auto-rows: minmax(0rem, auto);
2691 | }
2692 |
2693 | .sm\\\\:matrix-gap-0 {
2694 | grid-row-gap: 0rem;
2695 | grid-column-gap: 0rem;
2696 | }
2697 |
2698 | .sm\\\\:matrix-gap-x-0 {
2699 | grid-column-gap: 0rem;
2700 | }
2701 |
2702 | .sm\\\\:matrix-gap-y-0 {
2703 | grid-row-gap: 0rem;
2704 | }
2705 |
2706 | .sm\\\\:matrix-row-h-1 {
2707 | grid-auto-rows: minmax(1rem, auto);
2708 | }
2709 |
2710 | .sm\\\\:matrix-gap-1 {
2711 | grid-row-gap: 1rem;
2712 | grid-column-gap: 1rem;
2713 | }
2714 |
2715 | .sm\\\\:matrix-gap-x-1 {
2716 | grid-column-gap: 1rem;
2717 | }
2718 |
2719 | .sm\\\\:matrix-gap-y-1 {
2720 | grid-row-gap: 1rem;
2721 | }
2722 |
2723 | .sm\\\\:matrix-row-h-2 {
2724 | grid-auto-rows: minmax(2rem, auto);
2725 | }
2726 |
2727 | .sm\\\\:matrix-gap-2 {
2728 | grid-row-gap: 2rem;
2729 | grid-column-gap: 2rem;
2730 | }
2731 |
2732 | .sm\\\\:matrix-gap-x-2 {
2733 | grid-column-gap: 2rem;
2734 | }
2735 |
2736 | .sm\\\\:matrix-gap-y-2 {
2737 | grid-row-gap: 2rem;
2738 | }
2739 |
2740 | .sm\\\\:cell-start-x-1 {
2741 | grid-column-start: 1 !important;
2742 | }
2743 |
2744 | .sm\\\\:cell-span-x-1 {
2745 | grid-column: auto / span 1;
2746 | }
2747 |
2748 | .sm\\\\:cell-start-y-1 {
2749 | grid-row-start: 1 !important;
2750 | }
2751 |
2752 | .sm\\\\:cell-span-y-1 {
2753 | grid-row: auto / span 1;
2754 | }
2755 |
2756 | .sm\\\\:cell-start-x-1 {
2757 | grid-column-start: 1 !important;
2758 | }
2759 |
2760 | .sm\\\\:cell-span-x-1 {
2761 | grid-column: auto / span 1;
2762 | }
2763 |
2764 | .sm\\\\:cell-start-y-1 {
2765 | grid-row-start: 1 !important;
2766 | }
2767 |
2768 | .sm\\\\:cell-span-y-1 {
2769 | grid-row: auto / span 1;
2770 | }
2771 |
2772 | .sm\\\\:cell-start-x-2 {
2773 | grid-column-start: 2 !important;
2774 | }
2775 |
2776 | .sm\\\\:cell-span-x-2 {
2777 | grid-column: auto / span 2;
2778 | }
2779 |
2780 | .sm\\\\:cell-start-y-2 {
2781 | grid-row-start: 2 !important;
2782 | }
2783 |
2784 | .sm\\\\:cell-span-y-2 {
2785 | grid-row: auto / span 2;
2786 | }
2787 |
2788 | .sm\\\\:cell-start-x-3 {
2789 | grid-column-start: 3 !important;
2790 | }
2791 |
2792 | .sm\\\\:cell-span-x-3 {
2793 | grid-column: auto / span 3;
2794 | }
2795 |
2796 | .sm\\\\:cell-start-y-3 {
2797 | grid-row-start: 3 !important;
2798 | }
2799 |
2800 | .sm\\\\:cell-span-y-3 {
2801 | grid-row: auto / span 3;
2802 | }
2803 |
2804 | .sm\\\\:cell-start-x-4 {
2805 | grid-column-start: 4 !important;
2806 | }
2807 |
2808 | .sm\\\\:cell-span-x-4 {
2809 | grid-column: auto / span 4;
2810 | }
2811 |
2812 | .sm\\\\:cell-start-y-4 {
2813 | grid-row-start: 4 !important;
2814 | }
2815 |
2816 | .sm\\\\:cell-span-y-4 {
2817 | grid-row: auto / span 4;
2818 | }
2819 |
2820 | .sm\\\\:cell-start-x-5 {
2821 | grid-column-start: 5 !important;
2822 | }
2823 |
2824 | .sm\\\\:cell-span-x-5 {
2825 | grid-column: auto / span 5;
2826 | }
2827 |
2828 | .sm\\\\:cell-start-y-5 {
2829 | grid-row-start: 5 !important;
2830 | }
2831 |
2832 | .sm\\\\:cell-span-y-5 {
2833 | grid-row: auto / span 5;
2834 | }
2835 |
2836 | .sm\\\\:cell-start-x-6 {
2837 | grid-column-start: 6 !important;
2838 | }
2839 |
2840 | .sm\\\\:cell-span-x-6 {
2841 | grid-column: auto / span 6;
2842 | }
2843 |
2844 | .sm\\\\:cell-start-y-6 {
2845 | grid-row-start: 6 !important;
2846 | }
2847 |
2848 | .sm\\\\:cell-span-y-6 {
2849 | grid-row: auto / span 6;
2850 | }
2851 | }"
2852 | `;
2853 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/compositor.file.test.ts:
--------------------------------------------------------------------------------
1 | import { ICompositorConfig } from '../types';
2 | import path from 'path';
3 | import { merge } from '../utils';
4 | import compositor from '../theme-compositor';
5 |
6 | import compositorBaseConfig from './fixtures/compositor.config.js';
7 | import tailwindConfig from './fixtures/tailwind.config.js';
8 |
9 | const createConfig = config => {
10 | const compositorConfig: ICompositorConfig = merge(
11 | compositorBaseConfig,
12 | config
13 | );
14 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
15 | return tailwindConfigComposed;
16 | };
17 |
18 | test('transform with font files', () => {
19 | const tailwindConfig = createConfig({
20 | fonts: [
21 | {
22 | file: path.resolve(
23 | 'plugin/src/__tests__/',
24 | 'fixtures/inter/Inter-Regular.woff'
25 | ),
26 | key: 'sans-400',
27 | },
28 | ],
29 | });
30 | expect(tailwindConfig).toMatchSnapshot();
31 | });
32 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/compositor.config.js:
--------------------------------------------------------------------------------
1 | const root = 10;
2 |
3 | const baseline = 10;
4 |
5 | const leading = 2;
6 |
7 | const matrix = 6;
8 |
9 | const type = [10, 20];
10 |
11 | const rhythm = [0, 1, 2];
12 |
13 | const measure = [10, 20];
14 |
15 | const fonts = [
16 | {
17 | key: 'sans-400',
18 | familyName: 'IBM Plex Sans',
19 | fallback: 'sans-serif',
20 | upm: 1000,
21 | xHeight: 525,
22 | capHeight: 698,
23 | ascent: 1025,
24 | lineGap: 0,
25 | descent: -275,
26 | weight: 400,
27 | italic: false,
28 | },
29 | ];
30 |
31 | module.exports = {
32 | root,
33 | baseline,
34 | leading,
35 | matrix,
36 | type,
37 | rhythm,
38 | measure,
39 | fonts,
40 | options: {
41 | useRem: false,
42 | snap: true,
43 | type: true,
44 | rhythm: true,
45 | measure: true,
46 | matrix: true,
47 | xray: true,
48 | },
49 | };
50 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/inter/Inter-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/inter/Inter-Regular.woff
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Black.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-BlackItalic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Bold.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-BoldItalic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-ExtraBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-ExtraBold.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-ExtraBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-ExtraBoldItalic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Italic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Medium.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-MediumItalic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-Regular.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-SemiBold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-SemiBold.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-SemiBoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/src/__tests__/fixtures/playfair/PlayfairDisplay-SemiBoldItalic.ttf
--------------------------------------------------------------------------------
/plugin/src/__tests__/fixtures/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | purge: [],
3 | target: 'relaxed',
4 | prefix: '',
5 | important: false,
6 | separator: ':',
7 | theme: {
8 | screens: {
9 | sm: '640px',
10 | },
11 | colors: {
12 | transparent: 'transparent',
13 | current: 'currentColor',
14 | black: '#000',
15 | white: '#fff',
16 | },
17 | spacing: {
18 | px: '1px',
19 | '0': '0',
20 | '1': '0.25rem',
21 | '2': '0.5rem',
22 | '3': '0.75rem',
23 | '4': '1rem',
24 | },
25 | flex: {
26 | auto: '1 1 auto',
27 | },
28 | fontFamily: {
29 | sans: ['system-ui'],
30 | },
31 | fontSize: {
32 | base: '1rem',
33 | lg: '1.5rem',
34 | },
35 | fontWeight: {
36 | normal: '400',
37 | bold: '700',
38 | },
39 | letterSpacing: {
40 | normal: '0',
41 | wide: '0.025em',
42 | },
43 | lineHeight: {
44 | none: '1',
45 | normal: '1.5',
46 | },
47 | extend: {
48 | maxHeight: {
49 | '100': '100px',
50 | },
51 | maxWidth: {
52 | '100': '100px',
53 | },
54 | minHeight: {
55 | '100': '100px',
56 | },
57 | minWidth: {
58 | '100': '100px',
59 | },
60 | },
61 | },
62 | variants: {
63 | accessibility: [],
64 | alignContent: [],
65 | alignItems: [],
66 | alignSelf: [],
67 | appearance: [],
68 | backgroundAttachment: [],
69 | backgroundColor: [],
70 | backgroundOpacity: [],
71 | backgroundPosition: [],
72 | backgroundRepeat: [],
73 | backgroundSize: [],
74 | borderCollapse: [],
75 | borderColor: [],
76 | borderOpacity: [],
77 | borderRadius: [],
78 | borderStyle: [],
79 | borderWidth: [],
80 | boxShadow: [],
81 | boxSizing: [],
82 | cursor: [],
83 | display: [],
84 | divideColor: [],
85 | divideOpacity: [],
86 | divideWidth: [],
87 | fill: [],
88 | flex: [],
89 | flexDirection: [],
90 | flexGrow: [],
91 | flexShrink: [],
92 | flexWrap: [],
93 | float: [],
94 | clear: [],
95 | fontFamily: [],
96 | fontSize: [],
97 | fontSmoothing: [],
98 | fontStyle: [],
99 | fontWeight: [],
100 | height: [],
101 | inset: [],
102 | justifyContent: [],
103 | letterSpacing: [],
104 | lineHeight: [],
105 | listStylePosition: [],
106 | listStyleType: [],
107 | margin: [],
108 | maxHeight: [],
109 | maxWidth: [],
110 | minHeight: [],
111 | minWidth: [],
112 | objectFit: [],
113 | objectPosition: [],
114 | opacity: [],
115 | order: [],
116 | outline: [],
117 | overflow: [],
118 | padding: [],
119 | placeholderColor: [],
120 | placeholderOpacity: [],
121 | pointerEvents: [],
122 | position: [],
123 | resize: [],
124 | space: [],
125 | stroke: [],
126 | strokeWidth: [],
127 | tableLayout: [],
128 | textAlign: [],
129 | textColor: [],
130 | textOpacity: [],
131 | textDecoration: [],
132 | textTransform: [],
133 | userSelect: [],
134 | verticalAlign: [],
135 | visibility: [],
136 | whitespace: [],
137 | width: [],
138 | wordBreak: [],
139 | zIndex: [],
140 | gap: [],
141 | gridAutoFlow: [],
142 | gridTemplateColumns: [],
143 | gridColumn: [],
144 | gridColumnStart: [],
145 | gridColumnEnd: [],
146 | gridTemplateRows: [],
147 | gridRow: [],
148 | gridRowStart: [],
149 | gridRowEnd: [],
150 | transform: [],
151 | transformOrigin: [],
152 | scale: [],
153 | rotate: [],
154 | translate: [],
155 | skew: [],
156 | transitionProperty: [],
157 | transitionTimingFunction: [],
158 | transitionDuration: [],
159 | transitionDelay: [],
160 | },
161 | corePlugins: false,
162 | plugins: [],
163 | };
164 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/plugin.test.ts:
--------------------------------------------------------------------------------
1 | test('simple transform', () => {
2 | // const tailwindConfig = createConfig({});
3 | // expect(tailwindConfig).toMatchSnapshot();
4 | expect(true).toBe(true);
5 | });
6 |
7 | import postcss from 'postcss';
8 | import tailwindcss from 'tailwindcss';
9 |
10 | import { merge } from '../utils';
11 | import compositor from '../theme-compositor';
12 |
13 | import compositorBaseConfig from './fixtures/compositor.config.js';
14 | import tailwindConfig from './fixtures/tailwind.config.js';
15 |
16 | const createPostCSSConfig = ({ config, input = '@tailwind utilities;' }) => {
17 | // make config
18 | const compositorConfig = merge(compositorBaseConfig, config);
19 |
20 | // transform tailwind theme
21 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
22 |
23 | // run postcss
24 | return postcss([tailwindcss(tailwindConfigComposed)])
25 | .process(input, {
26 | from: undefined,
27 | })
28 | .then(({ css }) => {
29 | return css;
30 | });
31 | };
32 |
33 | test('use rem', () => {
34 | const config = {
35 | options: {
36 | useRem: true,
37 | },
38 | };
39 | return createPostCSSConfig({ config: config }).then(css => {
40 | expect(css).toMatchSnapshot();
41 | });
42 | });
43 |
44 | test('use px', () => {
45 | const config = {
46 | options: {
47 | useRem: false,
48 | },
49 | };
50 | return createPostCSSConfig({ config: config }).then(css => {
51 | expect(css).toMatchSnapshot();
52 | });
53 | });
54 |
55 | test('baseline styles', () => {
56 | const config = {
57 | options: {
58 | useRem: false,
59 | snap: true,
60 | type: true,
61 | rhythm: false,
62 | measure: false,
63 | matrix: false,
64 | xray: false,
65 | },
66 | };
67 | return createPostCSSConfig({ config: config }).then(css => {
68 | expect(css).toMatchSnapshot();
69 | });
70 | });
71 |
72 | test('capheight styles', () => {
73 | const config = {
74 | options: {
75 | useRem: false,
76 | snap: false,
77 | type: true,
78 | rhythm: false,
79 | measure: false,
80 | matrix: false,
81 | xray: false,
82 | },
83 | };
84 | return createPostCSSConfig({ config: config }).then(css => {
85 | expect(css).toMatchSnapshot();
86 | });
87 | });
88 |
89 | test('rhythm styles', () => {
90 | const config = {
91 | options: {
92 | useRem: false,
93 | snap: false,
94 | type: false,
95 | rhythm: true,
96 | measure: false,
97 | matrix: false,
98 | xray: false,
99 | },
100 | };
101 | return createPostCSSConfig({ config: config }).then(css => {
102 | expect(css).toMatchSnapshot();
103 | });
104 | });
105 |
106 | test('measure styles', () => {
107 | const config = {
108 | options: {
109 | useRem: false,
110 | snap: false,
111 | type: false,
112 | rhythm: false,
113 | measure: true,
114 | matrix: false,
115 | xray: false,
116 | },
117 | };
118 | return createPostCSSConfig({ config: config }).then(css => {
119 | expect(css).toMatchSnapshot();
120 | });
121 | });
122 |
123 | test('matrix styles', () => {
124 | const config = {
125 | options: {
126 | useRem: false,
127 | snap: false,
128 | type: false,
129 | rhythm: false,
130 | measure: false,
131 | matrix: true,
132 | xray: false,
133 | },
134 | };
135 | return createPostCSSConfig({ config: config }).then(css => {
136 | expect(css).toMatchSnapshot();
137 | });
138 | });
139 |
--------------------------------------------------------------------------------
/plugin/src/__tests__/transform.test.ts:
--------------------------------------------------------------------------------
1 | import { ICompositorConfig } from '../types';
2 | import path from 'path';
3 | import { merge } from '../utils';
4 | import compositor from '../theme-compositor';
5 |
6 | import compositorBaseConfig from './fixtures/compositor.config.js';
7 | import tailwindConfig from './fixtures/tailwind.config.js';
8 |
9 | const createConfig = config => {
10 | const compositorConfig: ICompositorConfig = merge(
11 | compositorBaseConfig,
12 | config
13 | );
14 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
15 | return tailwindConfigComposed;
16 | };
17 |
18 | test('simple transform', () => {
19 | // const tailwindConfig = createConfig({});
20 | // expect(tailwindConfig).toMatchSnapshot();
21 | expect(true).toBe(true);
22 | });
23 |
--------------------------------------------------------------------------------
/plugin/src/create-background-styles.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme, ICompositorConfig } from './types';
2 |
3 | import { get } from './utils/get';
4 | import { bgBaselineRel, bgBaseline } from './styles/style-background';
5 |
6 | export const createBackgroundStyles = ({
7 | theme,
8 | e,
9 | addUtilities,
10 | }: {
11 | theme: iTailwindTheme;
12 | e: any;
13 | addUtilities: Function;
14 | }) => {
15 | const { options, root, baseline, styles }: ICompositorConfig = theme(
16 | 'compositor'
17 | );
18 |
19 | const rulerColor = get(styles, 'ruler.color', '#ff00cc');
20 |
21 | if (!options.xray) return;
22 |
23 | const baselineBgStyles = {
24 | [`.bg-baseline`]: options.useRem
25 | ? bgBaselineRel({ baseline, root: root, color: rulerColor })
26 | : bgBaseline({ baseline, color: rulerColor }),
27 | };
28 |
29 | addUtilities(baselineBgStyles, []);
30 | };
31 |
32 | export default createBackgroundStyles;
33 |
--------------------------------------------------------------------------------
/plugin/src/create-matrix-styles.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme, ICompositorConfig } from './types';
2 | import {
3 | matrixColumns,
4 | matrixGap,
5 | matrixGapX,
6 | matrixGapY,
7 | matrixCellStartX,
8 | matrixCellSpanX,
9 | matrixCellStartY,
10 | matrixCellSpanY,
11 | matrixRows,
12 | } from './styles';
13 |
14 | /**
15 | *
16 | *
17 | */
18 | export const createMatrixStyles = ({
19 | theme,
20 | e,
21 | addUtilities,
22 | }: {
23 | theme: iTailwindTheme;
24 | e: any;
25 | addUtilities: Function;
26 | }) => {
27 | const { matrix, options }: ICompositorConfig = theme('compositor');
28 |
29 | if (!options.matrix) return;
30 |
31 | const columnsScale = Array.from(new Array(matrix + 1), (v, i) => i);
32 |
33 | const rhythmScale: Array = theme('spacing');
34 |
35 | const matrixColumnsStyles = columnsScale.map(columnIndex => {
36 | const columns = columnIndex === 0 ? 1 : columnIndex;
37 |
38 | return {
39 | [`.${e(`matrix-${columnIndex}`)}`]: matrixColumns({
40 | columns,
41 | }),
42 | };
43 | });
44 |
45 | const matrixCellStyles = columnsScale.map(columnIndex => {
46 | const column = columnIndex === 0 ? 1 : columnIndex;
47 |
48 | return {
49 | [`.${e(`cell-start-x-${column}`)}`]: matrixCellStartX({
50 | start: column,
51 | }),
52 | [`.${e(`cell-span-x-${column}`)}`]: matrixCellSpanX({
53 | span: column,
54 | }),
55 | [`.${e(`cell-start-y-${column}`)}`]: matrixCellStartY({
56 | start: column,
57 | }),
58 | [`.${e(`cell-span-y-${column}`)}`]: matrixCellSpanY({
59 | span: column,
60 | }),
61 | };
62 | });
63 |
64 | const matrixGapStyles = Object.keys(rhythmScale).map(key => {
65 | const rhythm = rhythmScale[key];
66 | return {
67 | [`.${e(`matrix-row-h-${key}`)}`]: matrixRows({
68 | size: rhythm,
69 | }),
70 | [`.${e(`matrix-gap-${key}`)}`]: matrixGap({ rhythm }),
71 | [`.${e(`matrix-gap-x-${key}`)}`]: matrixGapX({ rhythm }),
72 | [`.${e(`matrix-gap-y-${key}`)}`]: matrixGapY({ rhythm }),
73 | };
74 | });
75 |
76 | addUtilities(matrixColumnsStyles, ['responsive']);
77 | addUtilities(matrixGapStyles, ['responsive']);
78 | addUtilities(matrixCellStyles, ['responsive']);
79 | };
80 |
81 | export default createMatrixStyles;
82 |
--------------------------------------------------------------------------------
/plugin/src/create-measure-styles.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme, ICompositorConfig } from './types';
2 | import { measure } from './styles/style-measure';
3 |
4 | const createMeasureStyles = ({
5 | theme,
6 | e,
7 | addUtilities,
8 | }: {
9 | theme: iTailwindTheme;
10 | e: any;
11 | addUtilities: Function;
12 | }) => {
13 | const { measure: measureScale, options }: ICompositorConfig = theme(
14 | 'compositor'
15 | );
16 |
17 | if (!options.measure) return;
18 |
19 | const measureStyles = Object.keys(measureScale).map(key => {
20 | const space = measureScale[key];
21 | return {
22 | [`.${e(`measure-${key}`)}`]: measure({ space }),
23 | };
24 | });
25 |
26 | addUtilities(measureStyles, ['responsive']);
27 | };
28 |
29 | export default createMeasureStyles;
30 |
--------------------------------------------------------------------------------
/plugin/src/create-rhythm-styles.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme, ICompositorConfig } from './types';
2 | import { owlX, owlY } from './styles';
3 |
4 | /**
5 | *
6 | *
7 | */
8 | export const createRhythmStyles = ({
9 | theme,
10 | e,
11 | addUtilities,
12 | }: {
13 | theme: iTailwindTheme;
14 | e: any;
15 | addUtilities: Function;
16 | }) => {
17 | const { options }: ICompositorConfig = theme('compositor');
18 |
19 | if (!options.rhythm) return;
20 |
21 | const rhythmScale: Array = theme('spacing');
22 |
23 | const rhythmStyles = Object.keys(rhythmScale).map(key => {
24 | const space: string = rhythmScale[key];
25 | return {
26 | [`.${e(`rhythm-${key}`)}`]: owlY({ space }),
27 | [`.${e(`rhythm-y-${key}`)}`]: owlY({ space }),
28 | [`.${e(`rhythm-x-${key}`)}`]: owlX({ space }),
29 | };
30 | });
31 |
32 | addUtilities(rhythmStyles, ['responsive']);
33 | };
34 |
35 | export default createRhythmStyles;
36 |
--------------------------------------------------------------------------------
/plugin/src/create-text-styles.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme, ICompositorConfig, iFontOpenType } from './types';
2 | var flattenDeep = require('lodash.flattendeep');
3 |
4 | import { styleFontFamily, styleText } from './styles';
5 |
6 | /**
7 | *
8 | *
9 | */
10 | export const createTextStyles = ({
11 | theme,
12 | e,
13 | addUtilities,
14 | }: {
15 | theme: iTailwindTheme;
16 | e: any;
17 | addUtilities: Function;
18 | }) => {
19 | const {
20 | root,
21 | baseline,
22 | leading,
23 | fonts,
24 | type,
25 | options,
26 | }: ICompositorConfig = theme('compositor');
27 |
28 | const familyStyles = fonts.map((font: iFontOpenType) => {
29 | return {
30 | [`.font-${font.key}`]: styleFontFamily({ font }),
31 | };
32 | });
33 |
34 | const leadingScale = Array.from(new Array(leading + 1), (v, i) => i);
35 |
36 | const sizeStyles = flattenDeep(
37 | fonts.map((font: iFontOpenType) =>
38 | type.map((size, sizeIdx) => {
39 | return leadingScale.map(lead => {
40 | //
41 | // create baseline styles
42 | const outputTextStyle = styleText({
43 | font: font,
44 | root: root,
45 | baseline: baseline,
46 | size: size,
47 | leading: lead,
48 | snap: options.snap,
49 | useRem: options.useRem,
50 | });
51 |
52 | // apply if variant type is enabled
53 | const textStyles = {
54 | [`&.${e(`text-${sizeIdx}/${lead}`)}`]: outputTextStyle,
55 | };
56 |
57 | return {
58 | [`.font-${font.key}`]: {
59 | ...textStyles,
60 | },
61 | };
62 | });
63 | })
64 | )
65 | );
66 | addUtilities(familyStyles, []);
67 | addUtilities(sizeStyles, ['responsive']);
68 | };
69 |
70 | export default createTextStyles;
71 |
--------------------------------------------------------------------------------
/plugin/src/default-config.ts:
--------------------------------------------------------------------------------
1 | import { ICompositorConfig } from './types';
2 |
3 | // baseline grid row height in px
4 | export const root = 16;
5 |
6 | // baseline grid row height in px
7 | export const baseline = 8;
8 |
9 | // max leading count
10 | export const leading = 4;
11 |
12 | // matrix columns
13 | export const matrix = 12;
14 |
15 | // type scale in px
16 | export const type = [
17 | 12,
18 | 14,
19 | 16,
20 | 18,
21 | 20,
22 | 24,
23 | 28,
24 | 32,
25 | 36,
26 | 42,
27 | 48,
28 | 54,
29 | 60,
30 | 68,
31 | 76,
32 | 84,
33 | 92,
34 | ];
35 |
36 | // rhythm scale in baseline units
37 | export const rhythm = [0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 14];
38 |
39 | // measure scale in characters unit
40 | export const measure = [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65];
41 |
42 | // font config
43 | export const fonts = [
44 | {
45 | key: 'sans-400',
46 | fallback: 'sans-serif',
47 | familyName: 'Inter',
48 | upm: 2816,
49 | xHeight: 1536,
50 | capHeight: 2048,
51 | ascent: 2728,
52 | descent: -680,
53 | weight: 400,
54 | italic: false,
55 | },
56 | {
57 | key: 'sans-400i',
58 | fallback: 'sans-serif',
59 | familyName: 'Inter',
60 | upm: 2816,
61 | xHeight: 1536,
62 | capHeight: 2048,
63 | ascent: 2728,
64 | descent: -680,
65 | weight: 400,
66 | italic: true,
67 | },
68 | {
69 | key: 'sans-600',
70 | fallback: 'sans-serif',
71 | familyName: 'Inter',
72 | upm: 2816,
73 | xHeight: 1536,
74 | capHeight: 2048,
75 | ascent: 2728,
76 | descent: -680,
77 | weight: 600,
78 | italic: false,
79 | },
80 | {
81 | key: 'sans-600i',
82 | fallback: 'sans-serif',
83 | familyName: 'Inter',
84 | upm: 2816,
85 | xHeight: 1536,
86 | capHeight: 2048,
87 | ascent: 2728,
88 | descent: -680,
89 | weight: 600,
90 | italic: true,
91 | },
92 | ];
93 |
94 | export const options = {
95 | snap: true,
96 | useRem: true,
97 | type: true,
98 | rhythm: true,
99 | measure: true,
100 | matrix: true,
101 | xray: true,
102 | };
103 |
--------------------------------------------------------------------------------
/plugin/src/get-font-metrics.ts:
--------------------------------------------------------------------------------
1 | import fontkit from 'fontkit';
2 |
3 | import get from './utils/get';
4 |
5 | type FontKitMetrics = {
6 | familyName: string;
7 | upm: number;
8 | xHeight: number;
9 | capHeight: number;
10 | lineGap: number;
11 | ascent: number;
12 | descent: number;
13 | weight: number;
14 | italic: boolean;
15 | };
16 |
17 | export const getFontMetrics = (file: string): FontKitMetrics => {
18 | const font = fontkit.openSync(file);
19 |
20 | const weight = font['OS/2'].usWeightClass;
21 | const italic = font['OS/2'].fsSelection.italic;
22 |
23 | return {
24 | familyName: font.familyName,
25 | upm: font.unitsPerEm,
26 | xHeight: font.xHeight,
27 | capHeight: font.capHeight,
28 | lineGap: font.lineGap,
29 | ascent: font.ascent,
30 | descent: font.descent,
31 | weight: weight,
32 | italic: italic,
33 | };
34 | };
35 |
36 | export default getFontMetrics;
37 |
--------------------------------------------------------------------------------
/plugin/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './tailwind-plugin-compositor';
2 | export * from './theme-compositor';
3 |
--------------------------------------------------------------------------------
/plugin/src/styles/index.ts:
--------------------------------------------------------------------------------
1 | export * from './style-background';
2 |
3 | export * from './style-text';
4 | export * from './style-font-family';
5 | export * from './style-matrix';
6 | export * from './style-measure';
7 | export * from './style-owl';
8 |
9 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-background.ts:
--------------------------------------------------------------------------------
1 | export const bgBaselineRel = ({
2 | baseline,
3 | root,
4 | color,
5 | }: {
6 | baseline: number;
7 | root: number;
8 | color?: string;
9 | }) => ({
10 | position: 'relative',
11 | backgroundRepeat: 'repeat',
12 | backgroundSize: `100% ${baseline / root}rem`,
13 | backgroundImage: `linear-gradient(
14 | ${color} 1px,
15 | transparent 0
16 | )`,
17 | });
18 |
19 | export const bgBaseline = ({
20 | baseline,
21 | color,
22 | }: {
23 | baseline: number;
24 | color: string;
25 | }) => ({
26 | position: 'relative',
27 | backgroundRepeat: 'repeat',
28 | backgroundImage: `linear-gradient(
29 | ${color} 1px,
30 | transparent 0
31 | )`,
32 | backgroundSize: `100% ${baseline}px`,
33 | });
34 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-font-family.ts:
--------------------------------------------------------------------------------
1 | import { TypeFamilyParams, StyleFamily } from '../types';
2 |
3 | /**
4 | *
5 | *
6 | */
7 | export const styleFontFamily = (params: TypeFamilyParams): StyleFamily => {
8 | //
9 | const { font } = params;
10 |
11 | return {
12 | fontFamily: `"${font.familyName}", ${font.fallback}`,
13 | fontWeight: font.weight,
14 | fontStyle: font.italic ? 'italic' : 'normal',
15 | display: 'block',
16 | ['&::before, &::after']: {
17 | content: `''`,
18 | display: 'block',
19 | height: 0,
20 | },
21 | };
22 | };
23 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-matrix.ts:
--------------------------------------------------------------------------------
1 | import { Style } from '../types';
2 |
3 | export const matrixColumns = ({ columns }: { columns: number }): Style => {
4 | const result: Style = {
5 | display: 'grid',
6 | gridTemplateColumns: `repeat(${columns}, minmax(auto,1fr))`,
7 | };
8 |
9 | return result;
10 | };
11 |
12 | export const matrixRows = ({ size }: { size?: string }): Style => {
13 | const result: Style = {
14 | gridAutoRows: `minmax(${size}, auto)`,
15 | };
16 |
17 | return result;
18 | };
19 |
20 | export const matrixCellStartX = ({ start }: { start: number }): Style => {
21 | const result: Style = {
22 | gridColumnStart: `${start} !important`,
23 | };
24 |
25 | return result;
26 | };
27 |
28 | export const matrixCellSpanX = ({ span }: { span: number }): Style => {
29 | const result: Style = {
30 | gridColumn: `auto / span ${span}`,
31 | };
32 |
33 | return result;
34 | };
35 |
36 | export const matrixCellStartY = ({ start }: { start: number }): Style => {
37 | const result: Style = {
38 | gridRowStart: `${start} !important`,
39 | };
40 |
41 | return result;
42 | };
43 |
44 | export const matrixCellSpanY = ({ span }: { span: number }): Style => {
45 | const result: Style = {
46 | gridRow: `auto / span ${span}`,
47 | };
48 |
49 | return result;
50 | };
51 |
52 | export const matrixGap = ({ rhythm }: { rhythm: string }): Style => {
53 | return {
54 | gridRowGap: rhythm,
55 | gridColumnGap: rhythm,
56 | };
57 | };
58 |
59 | export const matrixGapX = ({ rhythm }: { rhythm: string }): Style => {
60 | return {
61 | gridColumnGap: rhythm,
62 | };
63 | };
64 |
65 | export const matrixGapY = ({ rhythm }: { rhythm: string }): Style => {
66 | return {
67 | gridRowGap: rhythm,
68 | };
69 | };
70 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-measure.ts:
--------------------------------------------------------------------------------
1 | import { Style } from '../types';
2 |
3 | export const measure = ({ space }: { space: string }): Style => {
4 | return {
5 | maxWidth: `${space}`,
6 | };
7 | };
8 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-owl.ts:
--------------------------------------------------------------------------------
1 | import { Style } from '../types';
2 |
3 | export const owlY = ({ space }: { space: string }): Style => {
4 | return {
5 | [`& > * + * `]: {
6 | marginTop: space,
7 | },
8 | };
9 | };
10 |
11 | export const owlX = ({ space }: { space: string }): Style => {
12 | return {
13 | [`& > * + * `]: {
14 | marginLeft: space,
15 | },
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/plugin/src/styles/style-text.ts:
--------------------------------------------------------------------------------
1 | import { StyleTypography, TypeStyleParams } from '../types';
2 |
3 | /**
4 | *
5 | *
6 | */
7 | export const styleText = ({
8 | font,
9 | baseline,
10 | size,
11 | leading = 0,
12 | snap = false,
13 | root = null,
14 | useRem = false,
15 | }: TypeStyleParams): StyleTypography => {
16 | // ratios
17 | const preventCollapse = 0.4;
18 | const descentAbs = Math.abs(font.descent);
19 | const capHeightRatio = font.capHeight / font.upm;
20 | const xHeightRatio = font.xHeight / font.upm;
21 | const ascentRatio = (font.ascent - font.capHeight) / font.upm;
22 | const descentRatio = descentAbs / font.upm;
23 |
24 | // bounding box
25 | const boundingBox = font.ascent + descentAbs + font.lineGap;
26 | const boundingBoxHeight = (boundingBox / font.upm) * size;
27 |
28 | // type height
29 | const capSize = capHeightRatio * size;
30 | const baselineRows = capSize / baseline;
31 | const typeRows = Math.round(baselineRows);
32 | // const typeRows = capSize / baseline % 1 < 0.8 ? Math.floor(baselineRows) : Math.ceil(baselineRows);
33 | const typeHeight = snap ? typeRows * baseline : capSize;
34 |
35 | // leading
36 | const leadingValue = snap ? Math.round(leading) : leading;
37 | const minLeading = snap ? typeRows : typeHeight;
38 | const typeLeading =
39 | leading < 0 ? Math.max(leadingValue, minLeading * -1) : leadingValue;
40 |
41 | // line height
42 | const typeLineGap = typeLeading * baseline;
43 | const typeLineHeight = typeHeight + typeLineGap;
44 |
45 | // leading trim
46 | const lineGapHeight = (font.lineGap / font.upm) * size;
47 | const lineHeightOffset =
48 | (boundingBoxHeight - typeLineHeight - lineGapHeight) / 2;
49 |
50 | const trimTop = ascentRatio * size - lineHeightOffset;
51 | const trimBottom = descentRatio * size - lineHeightOffset;
52 |
53 | // align to baseline
54 | const paddingTop = snap
55 | ? preventCollapse + ((trimBottom + trimTop) % baseline)
56 | : preventCollapse;
57 |
58 | const trimTopSize = trimTop * -1 - preventCollapse;
59 | const trimBottomSize = trimBottom * -1 - preventCollapse;
60 |
61 | const trimTopValue = useRem
62 | ? `${trimTopSize / size}em`
63 | : `${trimTopSize}px`;
64 |
65 | const trimBottomValue = useRem
66 | ? `${trimBottomSize / size}em`
67 | : `${trimBottomSize}px`;
68 |
69 | const fontSizeValue = useRem ? `${size / root}rem` : `${size}px`;
70 |
71 | const lineHeightValue = useRem
72 | ? `${typeLineHeight / size}`
73 | : `${typeLineHeight}px`;
74 |
75 | const paddingTopValue = useRem
76 | ? `${paddingTop / size}em`
77 | : `${paddingTop}px`;
78 |
79 | const paddingBottomValue = useRem
80 | ? `${preventCollapse / size}em`
81 | : `${preventCollapse}px`;
82 |
83 | return {
84 | fontSize: fontSizeValue,
85 | lineHeight: lineHeightValue,
86 | paddingTop: paddingTopValue,
87 | paddingBottom: paddingBottomValue,
88 | ['&::before']: {
89 | marginTop: trimTopValue,
90 | },
91 | ['&::after']: {
92 | marginBottom: trimBottomValue,
93 | },
94 | };
95 | };
96 |
--------------------------------------------------------------------------------
/plugin/src/tailwind-plugin-compositor.ts:
--------------------------------------------------------------------------------
1 | import { iTailwindTheme } from './types';
2 |
3 | import createTextStyles from './create-text-styles';
4 | import createBackgroundStyles from './create-background-styles';
5 | import createMeasureStyles from './create-measure-styles';
6 | import createRhythmStyles from './create-rhythm-styles';
7 | import createMatrixStyles from './create-matrix-styles';
8 |
9 | export const tailwindPluginCompositor = () => {
10 | return ({
11 | theme,
12 | e,
13 | addUtilities,
14 | }: {
15 | theme: iTailwindTheme;
16 | e: any;
17 | addUtilities: Function;
18 | }) => {
19 | createTextStyles({ theme, e, addUtilities });
20 | createBackgroundStyles({ theme, e, addUtilities });
21 | createMeasureStyles({ theme, e, addUtilities });
22 | createRhythmStyles({ theme, e, addUtilities });
23 | createMatrixStyles({ theme, e, addUtilities });
24 | };
25 | };
26 |
27 | export default tailwindPluginCompositor;
28 |
--------------------------------------------------------------------------------
/plugin/src/theme-compositor.ts:
--------------------------------------------------------------------------------
1 | import fs from 'fs';
2 | import {
3 | ICompositorConfig,
4 | iTailwindConfig,
5 | iFontOpenType,
6 | UtilityOptions,
7 | FontsConfig,
8 | } from './types';
9 |
10 | import getFontMetrics from './get-font-metrics';
11 | import tailwindPluginCompositor from './tailwind-plugin-compositor';
12 |
13 | import is from './utils/is';
14 | import merge from './utils/merge';
15 | import baselineScaleToRem from './utils/baseline-scale-to-rem';
16 | import baselineScaleToPx from './utils/baseline-scale-to-px';
17 | import pxScaleToRem from './utils/px-scale-to-rem';
18 | import scaleAddSuffix from './utils/scale-add-suffix';
19 |
20 | const cacheFileName = '.compositor';
21 |
22 | import {
23 | root as defaultRoot,
24 | matrix as defaultMatrix,
25 | type as defaultType,
26 | rhythm as defaultRhythm,
27 | measure as defaultMeasure,
28 | leading as defaultLeading,
29 | baseline as defaultBaseline,
30 | options as defaultOptions,
31 | fonts as defaultFonts,
32 | } from './default-config';
33 |
34 | type TwTheme = {
35 | extend: any;
36 | };
37 |
38 | const defaultStyles = {
39 | ruler: {
40 | color: 'rgba(255, 0, 255, 0.3)',
41 | },
42 | };
43 |
44 | export const compositor = (compositorConfig: ICompositorConfig) => (
45 | tailwindConfig: iTailwindConfig
46 | ): iTailwindConfig => {
47 | let fontsConfig: Array = [];
48 | let fontsCached = false;
49 |
50 | // try {
51 | // if (fs.existsSync(cacheFileName)) {
52 | // const rawCache: any = fs.readFileSync(cacheFileName);
53 | // fontsConfig = JSON.parse(rawCache);
54 | // fontsCached = true;
55 | // }
56 | // } catch (err) {
57 | // console.error(err);
58 | // }
59 |
60 | // first get some tailwind
61 | // tailwind config values
62 | const {
63 | theme = {} as TwTheme,
64 | plugins = [],
65 | ...tailwindRest
66 | } = tailwindConfig;
67 |
68 | // extend is nested under theme
69 | const { extend = {} } = theme;
70 |
71 | // get necessary params from compositor
72 | // we only need type and rhythm
73 | // to transform to px or rem usings
74 | // based on useRem, root and baseline params
75 | const {
76 | root = defaultRoot,
77 | baseline = defaultBaseline,
78 | fonts = defaultFonts as FontsConfig,
79 | type = defaultType,
80 | rhythm = defaultRhythm,
81 | measure = defaultMeasure,
82 | options: configOptions,
83 | } = compositorConfig;
84 | //
85 |
86 | const options: UtilityOptions = merge(defaultOptions, configOptions);
87 |
88 | if (options.useRem && !is.exists(root)) {
89 | throw 'With options.useRem:true, root is required';
90 | }
91 |
92 | if (!fontsCached) {
93 | fontsConfig = [];
94 | fonts.forEach(({ file, ...fontRest }) => {
95 | let fontOT: iFontOpenType;
96 | if (is.string(file) && is.exists(file)) {
97 | fontOT = merge(getFontMetrics(file), { ...fontRest });
98 | } else {
99 | fontOT = { ...fontRest } as iFontOpenType;
100 | }
101 |
102 | fontsConfig.push(fontOT);
103 | });
104 |
105 | fs.writeFileSync(cacheFileName, JSON.stringify(fontsConfig));
106 | }
107 |
108 | // [16,22,30,42,56]
109 | // type scale is described in px units
110 | // so transform to rem or px
111 | // depending on useRem
112 | const typeScale = options.useRem ? pxScaleToRem(root)(type) : type;
113 |
114 | // [1,2,3,4,5]
115 | // rhythm scale is described in baseline units
116 | // transform to tailwind format
117 | // rem or px depending on useRem param
118 | const spacingScale = options.useRem
119 | ? baselineScaleToRem(baseline)(root)(rhythm)
120 | : baselineScaleToPx(baseline)(rhythm);
121 |
122 | //
123 | // measure scale is described in ch units
124 | // transform to tailwind format
125 | // string or ch
126 | const measureScale = scaleAddSuffix('ch')(measure);
127 |
128 | // deconstruct tailwind extend
129 | // and get height, minHeight, maxHeight scales
130 | // to merge with the spacingScale
131 | // don't extend spacing,
132 | const {
133 | height = {},
134 | minHeight = {},
135 | maxHeight = {},
136 | fontSize = {},
137 | ...extendRest
138 | } = extend;
139 |
140 | //
141 | const out = {
142 | ...tailwindRest,
143 | theme: {
144 | ...theme,
145 | fontSize: typeScale, // overwrite type scale
146 | spacing: spacingScale, // overwrite spacing scale
147 | // compositor params via theme
148 | // rather than plugin below
149 | compositor: {
150 | ...compositorConfig,
151 | styles: defaultStyles,
152 | measure: measureScale,
153 | fonts: fontsConfig,
154 | },
155 | extend: {
156 | ...extendRest,
157 | height: merge(height, spacingScale),
158 | minHeight: merge(minHeight, spacingScale),
159 | maxHeight: merge(maxHeight, spacingScale),
160 | },
161 | },
162 | plugins: [...plugins, tailwindPluginCompositor()],
163 | };
164 |
165 | return out;
166 | };
167 |
168 | export default compositor;
169 |
--------------------------------------------------------------------------------
/plugin/src/types.ts:
--------------------------------------------------------------------------------
1 | import * as CSS from 'csstype';
2 |
3 | // type TLengthStyledSystem = string | 0 | number;
4 |
5 | // type ObjectOrArray = T[] | { [K: string]: T | ObjectOrArray };
6 |
7 | export type NumberScale = Array;
8 |
9 | export type FontConfigCache = Array;
10 |
11 | export type iTailwindTheme = Function;
12 |
13 | export type iTailwindConfig = {
14 | theme: {
15 | extend: any;
16 | [key: string]: any;
17 | };
18 | variants: any;
19 | corePlugins: any;
20 | plugins: any;
21 | compositor: ICompositorConfig;
22 | };
23 |
24 | export interface iFontOpenType {
25 | key: string;
26 | file?: string;
27 | fallback: string;
28 | familyName: string;
29 | upm: number;
30 | xHeight: number;
31 | capHeight: number;
32 | lineGap: number;
33 | ascent: number;
34 | descent: number;
35 | weight: number;
36 | italic: boolean;
37 | }
38 |
39 | export type FontConfigFile = {
40 | file: string;
41 | key: string;
42 | familyName: string;
43 | fallback: string;
44 | weight?: number;
45 | italic?: boolean;
46 | upm: undefined;
47 | xHeight: undefined;
48 | capHeight: undefined;
49 | ascent: undefined;
50 | descent: undefined;
51 | };
52 |
53 | export type FontsConfig = Array;
54 |
55 | export interface UtilityOptions {
56 | useRem: boolean;
57 | snap: boolean;
58 | type: boolean;
59 | rhythm: boolean;
60 | measure: boolean;
61 | matrix: boolean;
62 | xray: boolean;
63 | }
64 |
65 | export interface ICompositorConfig {
66 | root: number;
67 | baseline: number;
68 | leading: number;
69 | matrix: number;
70 | type: NumberScale;
71 | measure: NumberScale;
72 | rhythm: NumberScale;
73 | fonts: FontsConfig;
74 | options: UtilityOptions;
75 | styles: iCompositorThemeStyles;
76 | }
77 |
78 | export interface iCompositorThemeStyles {
79 | ruler: {
80 | color: string;
81 | };
82 | }
83 |
84 | export interface Style extends CSS.Properties {
85 | [key: string]: any;
86 | }
87 |
88 | export interface TypeFamilyParams {
89 | font: iFontOpenType;
90 | }
91 |
92 | export interface StyleFamily {
93 | fontFamily: CSS.FontFamilyProperty;
94 | fontWeight: CSS.FontWeightProperty;
95 | fontStyle: CSS.FontStyleProperty;
96 | display: CSS.DisplayProperty;
97 | '&::before, &::after': {
98 | content: CSS.ContentProperty;
99 | height: CSS.HeightProperty;
100 | display: CSS.DisplayProperty;
101 | };
102 | }
103 |
104 | export interface TypeStyleRelParams {
105 | font: iFontOpenType;
106 | baseline: number;
107 | root: number;
108 | size: number;
109 | leading: number;
110 | useRem: boolean;
111 | }
112 |
113 | export interface TypeStyleParams {
114 | font: iFontOpenType;
115 | baseline: number;
116 | size: number;
117 | snap: boolean;
118 | leading: number;
119 | root?: number;
120 | useRem: boolean;
121 | }
122 |
123 | export interface StyleTypography {
124 | fontSize: CSS.FontSizeProperty;
125 | lineHeight: CSS.LineHeightProperty;
126 | paddingTop: CSS.PaddingTopProperty;
127 | paddingBottom: CSS.PaddingTopProperty;
128 | '&::before': {
129 | marginTop: CSS.MarginProperty;
130 | };
131 | '&::after': {
132 | marginBottom: CSS.MarginProperty;
133 | };
134 | }
135 |
--------------------------------------------------------------------------------
/plugin/src/utils/baseline-scale-to-px.ts:
--------------------------------------------------------------------------------
1 | import { is } from './is';
2 |
3 | export const baselineScaleToPx = baseline => scale => {
4 | const result = Object.keys(scale).reduce((res, key) => {
5 | const value = scale[key];
6 | return {
7 | [key]: is.num(value) ? `${value * baseline}px` : value,
8 | ...res,
9 | };
10 | }, {});
11 | return result;
12 | };
13 |
14 | export default baselineScaleToPx;
15 |
--------------------------------------------------------------------------------
/plugin/src/utils/baseline-scale-to-rem.ts:
--------------------------------------------------------------------------------
1 | import { is } from './is';
2 | import { pxToRem } from './px-to-rem';
3 |
4 | export const baselineScaleToRem = baseline => root => scale => {
5 | const result = Object.keys(scale).reduce((res, key) => {
6 | const toRootEm = pxToRem(root);
7 | const value = scale[key];
8 | return {
9 | [key]: is.num(value) ? `${toRootEm(value * baseline)}rem` : value,
10 | ...res,
11 | };
12 | }, {});
13 | return result;
14 | };
15 |
16 | export default baselineScaleToRem;
17 |
--------------------------------------------------------------------------------
/plugin/src/utils/get-rhythm.ts:
--------------------------------------------------------------------------------
1 | import { is } from './is';
2 | import { get } from './get';
3 | import { pxToRem } from './px-to-rem';
4 |
5 | //
6 | export const getRhythm = theme => key => {
7 | //
8 | const { useRem, root, baseline } = theme;
9 | const toRootEm = pxToRem(root);
10 |
11 | const valuePrevix = is.num(key) && key < 0 ? '-' : '';
12 | const scaleKey = is.num(key) ? Math.abs(key) : key;
13 | const scaleValue = get(theme.rhythm, scaleKey, scaleKey);
14 |
15 | // if it's just a number, transform to px or rem if useRem
16 | const styleValue = is.num(scaleValue)
17 | ? is.truthy(useRem)
18 | ? `${valuePrevix}${toRootEm(scaleValue * baseline)}rem`
19 | : `${valuePrevix}${scaleValue * baseline}px`
20 | : // else try to get a theme value
21 | get(theme, key, key);
22 |
23 | return styleValue;
24 | };
25 |
26 | export default getRhythm;
27 |
--------------------------------------------------------------------------------
/plugin/src/utils/get.ts:
--------------------------------------------------------------------------------
1 | // based on https://github.com/developit/dlv
2 | export const get = (obj: any, key, def, p: number = 0, undef?) => {
3 | key = key && key.split ? key.split('.') : [key];
4 | for (p = 0; p < key.length; p++) {
5 | obj = obj ? obj[key[p]] : undef;
6 | }
7 | return obj === undef ? def : obj;
8 | };
9 |
10 | export default get;
11 |
--------------------------------------------------------------------------------
/plugin/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './uuid';
2 | export * from './merge';
3 | export * from './get';
4 | export * from './is';
5 | export * from './mem';
6 | export * from './noop';
7 | export * from './strip-css';
8 | export * from './baseline-scale-to-rem';
9 | export * from './baseline-scale-to-px';
10 | export * from './px-scale-to-rem';
11 | export * from './px-to-rem';
12 | export * from './get-rhythm';
13 | export * from './scale-add-suffix';
14 |
--------------------------------------------------------------------------------
/plugin/src/utils/is.ts:
--------------------------------------------------------------------------------
1 | export const is = {
2 | truthy: n => n !== undefined && n !== null && n !== false,
3 | exists: n => n !== undefined && n !== null,
4 | undefined: n => n === undefined,
5 | array: n => Array.isArray(n),
6 | num: n => typeof n === 'number' && !Number.isNaN(n),
7 | func: f => typeof f === 'function',
8 | object: n => typeof n === 'object' && n !== null,
9 | emptyObject: obj =>
10 | Object.entries(obj).length === 0 && obj.constructor === Object,
11 | string: str => Object.prototype.toString.call(str) === '[object String]',
12 | cssunit: value =>
13 | [
14 | 'px',
15 | 'em',
16 | 'ex',
17 | 'ch',
18 | 'rem',
19 | 'vh',
20 | 'vw',
21 | 'vmin',
22 | 'vmax',
23 | 'inherit',
24 | ].some(u => value.includes(u)),
25 | };
26 |
27 | export default is;
28 |
--------------------------------------------------------------------------------
/plugin/src/utils/mem.ts:
--------------------------------------------------------------------------------
1 | export const mem = func => {
2 | const mem = {};
3 | return (...params) => {
4 | const key = String(params);
5 | if (!mem[key]) {
6 | mem[key] = func(...params);
7 | }
8 | return mem[key];
9 | };
10 | };
11 |
12 | export default mem;
13 |
--------------------------------------------------------------------------------
/plugin/src/utils/merge.ts:
--------------------------------------------------------------------------------
1 | export const merge = (a, b) => {
2 | let result = Object.assign({}, a, b);
3 | for (const key in a) {
4 | if (!a[key] || typeof b[key] !== 'object') continue;
5 | Object.assign(result, {
6 | [key]: Object.assign(a[key], b[key]),
7 | });
8 | }
9 | return result;
10 | };
11 |
12 | export default merge;
13 |
--------------------------------------------------------------------------------
/plugin/src/utils/noop.ts:
--------------------------------------------------------------------------------
1 | export const noop = n => n;
2 |
3 | export default noop;
4 |
--------------------------------------------------------------------------------
/plugin/src/utils/px-scale-to-rem.ts:
--------------------------------------------------------------------------------
1 | import { is } from './is';
2 | import { pxToRem } from './px-to-rem';
3 |
4 | export const pxScaleToRem = root => scale => {
5 | //
6 | const result = Object.keys(scale).reduce((res, key) => {
7 | const toRootEm = pxToRem(root);
8 | const value = scale[key];
9 | //
10 | return {
11 | [key]: is.num(value) ? `${toRootEm(value)}rem` : value,
12 | ...res,
13 | };
14 | }, {});
15 | return result;
16 | };
17 |
18 | export default pxScaleToRem;
19 |
--------------------------------------------------------------------------------
/plugin/src/utils/px-to-rem.ts:
--------------------------------------------------------------------------------
1 | export const pxToRem = (root: number) => (px: number) => px / root;
2 |
3 | export default pxToRem;
4 |
--------------------------------------------------------------------------------
/plugin/src/utils/scale-add-suffix.ts:
--------------------------------------------------------------------------------
1 | import { is } from './is';
2 | export const scaleAddSuffix = suffix => scale => {
3 | //
4 | const result = Object.keys(scale).reduce((res, key) => {
5 | const value = scale[key];
6 | //
7 | return {
8 | [key]: is.num(value) ? `${value}${suffix}` : value,
9 | ...res,
10 | };
11 | }, {});
12 | return result;
13 | };
14 |
15 | export default scaleAddSuffix;
16 |
--------------------------------------------------------------------------------
/plugin/src/utils/strip-css.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/benface/jest-matcher-css/blob/master/index.js
2 | export const stripcss = function (str) {
3 | return str.replace(/[;\s]/g, '');
4 | };
5 |
6 | export default stripcss;
7 |
--------------------------------------------------------------------------------
/plugin/src/utils/uuid.ts:
--------------------------------------------------------------------------------
1 | export const uuid = prefix =>
2 | `${prefix}-${
3 | Math.random().toString(36).substring(2) + Date.now().toString(36)
4 | }`;
5 |
6 | export default uuid;
7 |
--------------------------------------------------------------------------------
/plugin/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.settings.json",
3 | "compilerOptions": {
4 | "outDir": "./dist",
5 | "baseUrl": "./"
6 | },
7 | "include": ["src/**/*", "jest.config.ts"]
8 | }
9 |
--------------------------------------------------------------------------------
/plugin/types.d.ts:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tol-is/tailwind-compositor/c7e422cb8141521b6c03dcbbb3c69eb522a44128/plugin/types.d.ts
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Tailwind Compositor
2 |
3 | Compositor is a system of constraints designed to produce aesthetically pleasing, typographic compositions, based on objective, constant dimensions of space.
4 |
5 | A baseline-grid typography system for [tailwindcss](https://tailwindcss.com/).
6 |
7 | Algorithm Demo: [Styled Baseline](https://styled-baseline.netlify.app/)
8 |
9 | ---
10 |
11 | ## Installation
12 |
13 | You will need fontkit, postcss and tailwindcss installed along with the plugin
14 |
15 | ```
16 | npm install postcss fontkit tailwindcss tailwind-compositor
17 | ```
18 |
19 | #### - postcss.config.js
20 |
21 | In your `postcss.config.js` you will need to import your standard `tailwind.config.js`, but also your `compositor.config.js`.
22 |
23 | The `{ compositor }` will receive both, merge with your tailwind config, and return a standard tailwind configuration.
24 |
25 | ```
26 | const tailwindcss = require('tailwindcss');
27 | const { compositor } = require('tailwind-compositor');
28 |
29 | // import both configurations
30 | const compositorConfig = require('./compositor.config.js');
31 | const tailwindConfig = require('./tailwind.config.js');
32 |
33 | // compose config
34 | const tailwindConfigComposed = compositor(compositorConfig)(tailwindConfig);
35 |
36 | // use with tailwind
37 | module.exports = {
38 | plugins: [
39 | tailwindcss(tailwindConfigComposed),
40 | ],
41 | };
42 | ```
43 |
44 | ---
45 |
46 | ## Configuration
47 |
48 | #### - compositor.config.js
49 |
50 | ```
51 | module.exports = {
52 | // root unit
53 | root: 16,
54 |
55 | // baseline grid height in px units
56 | baseline: 8,
57 |
58 | // maximum leading
59 | leading: 4,
60 |
61 | // matrix max columns
62 | matrix: 4,
63 |
64 | // type scale in px units
65 | type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56, 60, 72],
66 |
67 | // spacing scale in baseline units
68 | rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12],
69 |
70 | // line width in ch units
71 | measure: [10, 15, 20, 30, 35, 50, 55, 60, 65],
72 |
73 | // webfonts and vertical metrics
74 | fonts: [
75 | {
76 | key: "sans-400",
77 | familyName: "Inter",
78 | fallback: "sans-serif",
79 | weight: 400,
80 | italic: false,
81 | upm: 2816,
82 | xHeight: 1536,
83 | capHeight: 2048,
84 | ascent: 2728,
85 | descent: -680
86 | },
87 | {
88 | key: 'sans-600',
89 | familyName: "Inter",
90 | fallback: 'sans-serif',
91 | file: path.resolve('./fonts/inter/Inter-Semibold.woff2'),
92 | },
93 | ],
94 |
95 | // compositor options
96 | options: {
97 | useRem: true,
98 | snap: true,
99 | type: true,
100 | rhythm: true,
101 | measure: true,
102 | matrix: true,
103 | xray: true,
104 | },
105 | }
106 | ```
107 |
108 | ---
109 |
110 | #### 1/9 - root: integer
111 |
112 | The root font size, in `px` units.
113 |
114 | ---
115 |
116 | #### 2/9 - baseline: integer
117 |
118 | The baseline grid row height, in `px` units.
119 |
120 | ---
121 |
122 | #### 3/9 - leading: integer
123 |
124 | The maximum leading value in baseline units.
125 |
126 | ---
127 |
128 | #### 4/9 - matrix: integer
129 |
130 | The maximum columns on the matrix utility
131 |
132 | ---
133 |
134 | #### 5/9 - type : array[integer]
135 |
136 | ```
137 | type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56, 60, 72]
138 | ```
139 |
140 | The system's typographic scale, in `px` units.
141 |
142 | ---
143 |
144 | #### 6/9 - rhythm : array[integer]
145 |
146 | ```
147 | rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12]
148 | ```
149 |
150 | The system's size and spacing scale, in `baseline` units, used for `rhythm`, `margin`, `padding`, `width/min/max`, `height/min/max` and `grid-gap` utilities
151 |
152 | ---
153 |
154 | #### 7/9 - measure : array[integer]
155 |
156 | ```
157 | measure: [10, 15, 20, 30, 35, 50, 55, 60, 65]
158 | ```
159 |
160 | Separate scale used for `measure` (line-width) utilities, configured in `ch` units.
161 |
162 | ---
163 |
164 | #### 8/9 - fonts : array[opentype]
165 |
166 | The font scale provides all the information needed to render text styles. Each entry describes a font/weight/style set, and only those that are part of the system will be enabled.
167 |
168 | The `file` property, is used to extract the vertical metrics dynamically from the font-file. If you want to configure the metrics manually, you can omit the `file` prop.
169 |
170 | The `key` property is used to name the utility classes. The configuration bellow will produce four font styles. The recommended convention is `${family}-${weight}${style}`.
171 |
172 | 1. `font-sans-400` : Inter Regular
173 | 2. `font-sans-400i` : Inter Regular Italic
174 | 3. `font-sans-600i` : Inter Semibold
175 | 4. `font-sans-600i` : Inter Semibold Italic
176 |
177 | ```
178 | {
179 | key: "sans-400",
180 | familyName: "Inter",
181 | fallback: "sans-serif",
182 | weight: 400,
183 | italic: false,
184 | upm: 2816,
185 | xHeight: 1536,
186 | capHeight: 2048,
187 | lineGap: 0,
188 | ascent: 2728,
189 | descent: -680
190 | },
191 | {
192 | key: 'sans-400i',
193 | familyName: "Inter",
194 | fallback: 'sans-serif',
195 | file: path.resolve('./fonts/inter/Inter-Italic.woff2'),
196 | },
197 | {
198 | key: 'sans-600',
199 | familyName: "Inter",
200 | fallback: 'sans-serif',
201 | file: path.resolve('./fonts/inter/Inter-Semibold.woff2'),
202 | },
203 | {
204 | key: 'sans-600i',
205 | familyName: "Inter",
206 | fallback: 'sans-serif',
207 | file: path.resolve('./fonts/inter/Inter-SemiboldItalic.woff2'),
208 | },
209 | ```
210 |
211 | ---
212 |
213 | #### 9/9 - Options : object
214 |
215 | Options properties, are used to enable/disable individual compositor utilities.
216 |
217 | If `useRem` is set to true, compositor will use the root unit value, to transform all spacing and font-size utilities, to relative units. Line-height will be transformed to unitless ratios.
218 |
219 | If `snap` is true, compositor will align each line text to the nearest baseline grid row, otherwise will trim the line-height above the capHeight and below the baseline, and apply a constant lineGap between lines of text.
220 |
221 | - `useRem: boolean` transform to relative units
222 | - `snap: boolean` Align text styles to a baseline grid
223 | `type: boolean` Enable typographic utilities
224 | - `rhythm: boolean` Enable rhythm utilities
225 | - `measure: boolean` Enable measure utilities
226 | - `matrix: boolean` Enable matrix utilities
227 | - `xray: boolean` Enable debug utilities
228 |
229 | ```
230 | options: {
231 | useRem: true,
232 | snap: true,
233 | type: true,
234 | rhythm: true,
235 | measure: true,
236 | matrix: true,
237 | xray: true,
238 | }
239 | ```
240 |
241 | ---
242 |
243 | ## Tailwind Utility Classes
244 |
245 | #### 1/7 - Typography
246 |
247 | ##### Font & Font Style
248 |
249 | - font: `font-{font-key}`
250 |
251 | ```
252 |
253 | // fonts: [
254 | // { key: "sans-400", ... },
255 | // { key: 'sans-400i', ... },
256 | // { key: 'sans-600', ... },
257 | // { key: 'sans-600i', ... },
258 | // ],
259 |
260 | // sans semibold italic
261 |
262 |
263 | // sans regular
264 |
265 |
266 | // sans regular italic
267 |
268 | ```
269 |
270 | ##### Text Style
271 |
272 | - Text Style : `text-{type_scale_index}/{leading_baseline_units}`
273 |
274 | ```
275 |
276 | // type: [16, 18, 20, 22, 24, 28, 30, 32, 40, 48, 56]
277 |
278 | // sans semibold italic - 56px / leading 3
279 |
280 |
281 | // sans regular - 20px / leading 3
282 |
283 |
284 | // sans regular italic - 18px / leading 2
285 |
286 | ```
287 |
288 |
289 | ---
290 |
291 | #### 2/7 - Line Width
292 |
293 | - `measure-{measure_scale_index}`
294 |
295 | ```
296 | // measure: [10, 15, 20, 30, 35, 50, 55, 60, 65]
297 |
298 | // 10ch
299 | Ad proident quis enim duis commodo.
300 |
301 | // 15ch
302 | Ad proident quis enim duis commodo.
303 |
304 | // 20ch
305 | Ad proident quis enim duis commodo.
306 |
307 | // 30ch
308 | Ad proident quis enim duis commodo.
309 | ```
310 |
311 | ---
312 |
313 | #### 3/7 - Spacing
314 |
315 | When the tailwind theme is composed, the rhythm scale is transformed to tailwindcss spacing scale and can be used for all spacing utilities, margin, padding and grid-gap.
316 |
317 | - Margin: `m-{rhythm_scale_index}`
318 | - Margin Left: `ml-{rhythm_scale_index}`
319 | - Padding: `p-{rhythm_scale_index}`
320 | - ...etc
321 |
322 | ```
323 |
324 | // rhythm: [0, 1, 2, 3, 4, 5, 6, 8, 10, 12]
325 |
326 |
331 | ```
332 |
333 | ---
334 |
335 | #### 4/7 - Size
336 |
337 | Compositor also applies the spacing scale to tailwind sizing scales, width, min/max width and also height min/max.
338 |
339 | - Height: `h-{rhythm_scale_index}`
340 | - Min Height: `min-h-{rhythm_scale_index}`
341 | - Max Height: `max-h-{rhythm_scale_index}`
342 | - ...etc
343 | -
344 |
345 | ```
346 |
349 | ```
350 |
351 | ---
352 |
353 | #### 5/7 - Lobotomized Owls
354 |
355 | - Vertical rhythm (alias): `rhythm-{rhythm_scale_index}`
356 | - Vertical rhythm: `rhythm-y-{rhythm_scale_index}`
357 | - Horizontal Rhythm: `rhythm-x-{rhythm_scale_index}`
358 |
359 | ```
360 |
361 |
362 |
363 |
364 |
365 | // render horizontally
366 |
367 |
368 |
369 |
370 |
371 | ```
372 |
373 | ---
374 |
375 | #### 6/7 - Matrix Utils
376 |
377 | ##### Matrix
378 | - Matrix: `matrix-{columns_length}`
379 | - Matrix Gap: `matrix-gap-{rhythm_scale_index}`
380 | - Matrix Gap X: `matrix-gap-x-{rhythm_scale_index}`
381 | - Matrix Gap Y: `matrix-gap-y-{rhythm_scale_index}`
382 |
383 | ##### Cells
384 | By default every child of the matrix, will be placed in the next available column and will span for 1 column. In many cases you might not need any cell utilities or only the `cell-span-x` utility.
385 |
386 | - Cell Start X: `cell-start-x-{columns_index}`
387 | - Cell Span X: `cell-span-x-{columns_index}`
388 |
389 | ---
390 |
391 | #### 7/7 - Dev Utils
392 |
393 | - Background grid lines: `bg-baseline`
394 |
395 | ```
396 |
397 | ```
398 |
--------------------------------------------------------------------------------
/scripts/rollup.base.js:
--------------------------------------------------------------------------------
1 | import typescript from 'rollup-plugin-typescript2';
2 |
3 | export const createRollupConfig = pkg => ({
4 | input: ['src/index.ts'],
5 | //
6 | output: [
7 | {
8 | file: pkg.main,
9 | format: 'cjs',
10 | exports: 'named',
11 | },
12 | {
13 | file: pkg.module,
14 | format: 'es',
15 | exports: 'named',
16 | },
17 | ],
18 | //
19 | external: [...Object.keys(pkg.peerDependencies || {})],
20 | plugins: [
21 | typescript({
22 | clean: true,
23 | typescript: require('typescript'),
24 | }),
25 | ],
26 | });
27 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.settings.json",
3 | "files": [] // do not remove!
4 | }
5 |
--------------------------------------------------------------------------------
/tsconfig.settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "strict": false,
4 | "noImplicitAny": false,
5 | "allowSyntheticDefaultImports": true,
6 | "declaration": true,
7 | "esModuleInterop": true,
8 | "forceConsistentCasingInFileNames": true,
9 | "module": "esnext",
10 | "moduleResolution": "node",
11 | "noEmit": true,
12 | "outDir": "./dist",
13 | "resolveJsonModule": true,
14 | "skipLibCheck": true,
15 | "sourceMap": true,
16 | "target": "es5",
17 | "baseUrl": "./",
18 | "noErrorTruncation": true,
19 | "lib": ["es6", "dom"]
20 | },
21 | "module": "commonjs",
22 | "exclude": ["node_modules"]
23 | }
24 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["tslint:latest"],
3 | "rules": {
4 | "quotemark": [true, "single"],
5 | "no-submodule-imports": false,
6 | "object-literal-sort-keys": false
7 | }
8 | }
9 |
--------------------------------------------------------------------------------