ts-astroturf-tools
v0.16.0
Published
TypeScript tools that enhance astroturf.
Downloads
26
Maintainers
Readme
ts-astroturf-tools [beta! 🚧]
This package improves DX for astroturf users.
Compatible with astroturf@>=1.0.0-beta
, typescript@>=4
and webpack@>=5
! For compatibility with astroturf@>=0.9 <= 1
, use ts-astroturf-tools@<=0.14.3
.
Installation
yarn add -D ts-astroturf-tools
npm i --save-dev ts-astroturf-tools
Overview
Features are divided in three major categories:
- linaria-like functionality
- diagnostic messages
- autocomplete for identifiers
linaria
-like functionality
Use variables declared in other modules inside your CSS:
// * before // impossible :( // * after // colors.tsx export const RED = 'red'; // index.tsx import { css } from 'astroturf'; import { RED } from './colors'; const btn = css` color: ${RED}; `; // works for 'stylesheet' and ... import { stylesheet } from 'astroturf'; const { a } = stylesheet` .a { color: ${RED}; } `; // .. styled components too! import styled from 'astroturf/react'; const Button = styled.button` color: ${RED}; `;
Diagnostic messages
These messages are available if you use plain stylesheet
tag from astroturf
.
There are two types of diagnostic messages:
warnings in case there is unused CSS
Available via:
- webpack loader
- babel plugin
- TS Language Service Plugin (VS Code)
import { stylesheet } from 'astroturf'; const { btn } = stylesheet` .btn { color: red; } .active { color: green; } `;
The warning will look like this:
In VS Code the warning will become a suggestion:
errors in case there is missing CSS
Available via:
- webpack loader
- babel plugin
- TS Language Service Plugin (VS Code)
import { stylesheet } from 'astroturf'; const { btn, active } = stylesheet` .btn { color: red; } `;
The error will look like this:
In VS Code:
Autocomplete for identifiers
Available via:
- TS Language Service Plugin (VS Code)
Quick summary of tools and their respective features
| Tool | Diagnostic messages | Autocomplete for identifiers | linaria
-like functionality |
| -------------------------- | ------------------- | ---------------------------- | ---------------------------- |
| TS Language Service Plugin | ✅ | ✅ | N/A
|
| webpack loader | ✅ | N/A
| ✅ optional |
| babel plugin | ✅ | N/A
| ❌ |
| TS transformer | ❌ | N/A
| ✅ |
N/A
- not applicable
Configuration
TS Language Service Plugin
Add
ts-astroturf-tools
as a plugin to yourtsconfig.json
:{ "compilerOptions": { "plugins": [ { "name": "ts-astroturf-tools" } ] }, "files": ["src/index.tsx"], "exclude": ["node_modules"] }
Don't forget to switch to workspace typescript instance:
TS transformer:
raw TypeScript
You should use ttypescript as a compiler.
Add
ts-astroturf-tools/transformer
as a transformer to yourtsconfig.json
:{ "compilerOptions": { "plugins": [ { "transform": "ts-astroturf-tools/transformer" } ] }, "files": ["src/index.tsx"], "exclude": ["node_modules"] }
webpack / ts-loader
const transformer = require('ts-astroturf-tools/transformer'); module.exports = { // ... module: { // ... rules: [ { test: /\.tsx$/, use: { loader: 'ts-loader', options: { // ... getCustomTransformers: () => ({ before: [transformer()], }), }, }, }, ], }, };
webpack loader
Add
ts-astroturf-tools/loader
as a first loader for ts-files:module.exports = { // ... module: { rules: [ // ... { test: /\.tsx?$/, use: [ // works with any typescript loader 'ts-loader', 'astroturf/loader', 'ts-astroturf-tools/loader', ], }, ], }, };
Available options:
| Option name | Type | Description | | ----------- | --------- | ------------------------------------- | |
linaria
|boolean
| Enableslinaria
-like functionality. |Defaults:
module.exports = { // ... module: { rules: [ // ... { test: /\.tsx?$/, use: [ // works with any typescript loader 'awesome-typescript-loader', 'astroturf/loader', { loader: 'ts-astroturf-tools/loader', options: { linaria: false, }, }, ], }, ], }, };
Babel plugin
Add
ts-astroturf-tools/babel-plugin
to your babel plugins:module.exports = { presets: ['@babel/env', '@babel/preset-react'], plugins: ['ts-astroturf-tools/babel-plugin'], };
Known limitations
Regex-based parser is used to extract CSS class names.
Limited support for imports
Supported extensions:
.tsx
,.ts
,.js
.Files must not contain side-effects, import other heavy modules and / or libraries and code that must be transpiled.
This is ok:
// a.js export const redColor = 'red'; // b.js export const greenColor = 'green'; export { redColor } from './a.js'; // index.js import { greenColor, redColor } from './a.js'; import styled from 'astroturf/react'; const Button = styled.button` color: ${redColor}; background: ${greenColor}; `;
This is not ok and will most likely result in an error:
// a.js import * as React from 'react'; import image from './someImage.png'; export const redColor = 'red'; export const Something = () => ( <div style={{ background: `url(${image});` }}>Hello!</div> ); // b.js export const greenColor = 'green'; export { redColor } from './a.js'; // index.js import { greenColor, redColor } from './a.js'; import styled from 'astroturf/react'; const Button = styled.button` color: ${redColor}; background: ${greenColor}; `;
Performance issues with imports (this issue is in progress of being fixed)
As of now, files are parsed and executed for each encountered import.
For example:
// a.js export const RED = 'red'; // b.js export { RED } from './a'; export const GREEN = 'green'; // ComponentA.js import styled from 'astroturf/react'; import { GREEN } from './b'; export const ComponentA = styled.div` color: ${GREEN}; `; // ComponentB.js import styled from 'astroturf/react'; import { RED } from './b'; export const ComponentB = styled.div` color: ${RED}; `;
In this case both
a.js
andb.js
will be parsed and executed twice (first forComponentA.js
and then forComponentB.js
). Keep this in mind and try to avoid creating large dependency trees.Limited support for interpolations
const WIDTH = '500px'; // ok const { a } = stylesheet` .a { width: ${WIDTH}; } `;
const NAME = 'someClass'; // error // vvvvvvvvv const { someClass } = stylesheet` .${NAME} { color: red; } `;
Only plain CSS is supported.
Basic features of SASS/LESS/etc. may work:
// simple nesting is ok const { someClass, anotherClass } = stylesheet` .someClass { color: red; &.anotherClass { border: 1px solid black; } } `;
Advanced features will most probably not work:
// error! // vvvvvvvvvvvv const { someClass, anotherClass } = stylesheet` @name: anotherClass; .someClass { color: red; &.@{name} { color: black; } } `;
It is not possible to show errors in case destructuring is not used:
const classes = stylesheet` .a { color: red; } `; console.log(a.b); // <- no error
This is not hugely important because you should always use
css
in the first place.