Skip to content

Commit

Permalink
Add typings (#1382)
Browse files Browse the repository at this point in the history
  • Loading branch information
Semigradsky committed Jan 6, 2021
1 parent 3803763 commit 70a122b
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 46 deletions.
95 changes: 95 additions & 0 deletions lib/autoprefixer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { Plugin } from 'postcss'
import { Stats } from 'browserslist'

declare function autoprefixer<T extends string[]> (
...args: [...T, autoprefixer.Options]
): Plugin & autoprefixer.ExportedAPI

declare function autoprefixer (
browsers: string[],
options?: autoprefixer.Options
): Plugin & autoprefixer.ExportedAPI

declare function autoprefixer (
options?: autoprefixer.Options
): Plugin & autoprefixer.ExportedAPI

declare namespace autoprefixer {
type GridValue = 'autoplace' | 'no-autoplace'

interface Options {
/** environment for `Browserslist` */
env?: string

/** should Autoprefixer use Visual Cascade, if CSS is uncompressed */
cascade?: boolean

/** should Autoprefixer add prefixes. */
add?: boolean

/** should Autoprefixer [remove outdated] prefixes */
remove?: boolean

/** should Autoprefixer add prefixes for @supports parameters. */
supports?: boolean

/** should Autoprefixer add prefixes for flexbox properties */
flexbox?: boolean | 'no-2009'

/** should Autoprefixer add IE 10-11 prefixes for Grid Layout properties */
grid?: boolean | GridValue

/** custom usage statistics for > 10% in my stats browsers query */
stats?: Stats

/**
* list of queries for target browsers.
* Try to not use it.
* The best practice is to use `.browserslistrc` config or `browserslist` key in `package.json`
* to share target browsers with Babel, ESLint and Stylelint
*/
overrideBrowserslist?: string | string[]

/** do not raise error on unknown browser version in `Browserslist` config. */
ignoreUnknownVersions?: boolean
}

interface ExportedAPI {
/** Autoprefixer data */
data: {
browsers: { [browser: string]: object | undefined }
prefixes: { [prefixName: string]: object | undefined }
}

/** Autoprefixer default browsers */
defaults: string[]

/** Inspect with default Autoprefixer */
info(options?: { from?: string }): string

options: Options

browsers: string | string[]
}

/** Autoprefixer data */
let data: ExportedAPI['data']

/** Autoprefixer default browsers */
let defaults: ExportedAPI['defaults']

/** Inspect with default Autoprefixer */
let info: ExportedAPI['info']

let postcss: true
}

declare global {
namespace NodeJS {
interface ProcessEnv {
AUTOPREFIXER_GRID?: autoprefixer.GridValue
}
}
}

export = autoprefixer
14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@
"postcss-plugin"
],
"scripts": {
"test": "jest --coverage && eslint . bin/* && size-limit"
"test": "jest --coverage && eslint . bin/* && check-dts && size-limit"
},
"main": "lib/autoprefixer.js",
"bin": "bin/autoprefixer",
"types": "lib/autoprefixer.d.ts",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
Expand All @@ -42,6 +43,10 @@
"devDependencies": {
"@logux/eslint-config": "^44.0.1",
"@size-limit/preset-small-lib": "4.9.1",
"@types/jest": "^26.0.19",
"@typescript-eslint/eslint-plugin": "^4.11.1",
"@typescript-eslint/parser": "^4.11.1",
"check-dts": "^0.4.1",
"clean-publish": "^1.1.8",
"eslint": "^7.17.0",
"eslint-config-standard": "^16.0.2",
Expand All @@ -58,7 +63,9 @@
"jest": "^26.6.3",
"lint-staged": "^10.5.3",
"postcss": "^8.2.2",
"size-limit": "^4.9.1"
"size-limit": "^4.9.1",
"ts-jest": "^26.4.4",
"typescript": "^4.1.3"
},
"lint-staged": {
"*.js": "eslint --fix"
Expand All @@ -74,7 +81,7 @@
}
],
"eslintConfig": {
"extends": "@logux/eslint-config",
"extends": "@logux/eslint-config/ts",
"rules": {
"security/detect-non-literal-regexp": "off",
"security/detect-unsafe-regex": "off",
Expand Down Expand Up @@ -102,6 +109,7 @@
]
},
"jest": {
"preset": "ts-jest",
"testEnvironment": "node",
"coverageThreshold": {
"global": {
Expand Down
58 changes: 35 additions & 23 deletions test/autoprefixer.test.js → test/autoprefixer.test.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
let postcss = require('postcss')
let path = require('path')
let fs = require('fs')
/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable @typescript-eslint/no-confusing-void-expression */
import postcss, { AtRule, ChildNode, Container, Rule } from 'postcss'
import path from 'path'
import fs from 'fs'

let autoprefixer = require('../lib/autoprefixer')
// eslint-disable-next-line import/extensions
import autoprefixer from '..'

let grider = autoprefixer({
overrideBrowserslist: ['Chrome 25', 'Edge 12', 'IE 10'],
Expand Down Expand Up @@ -82,7 +85,7 @@ let example = autoprefixer({
overrideBrowserslist: ['defaults']
})

function prefixer (name) {
function prefixer (name: string) {
if (
name === 'grid' ||
name === 'grid-gap' ||
Expand Down Expand Up @@ -160,16 +163,16 @@ function prefixer (name) {
}
}

function read (name) {
function read (name: string) {
let file = path.join(__dirname, '/cases/' + name + '.css')
return fs.readFileSync(file).toString()
}

function universalizer (string) {
function universalizer (string: string) {
return string.replace(/\r/g, '')
}

function check (from, instance = prefixer(from)) {
function check (from: string, instance = prefixer(from)) {
let input = read(from)
let output = read(from + '.out')
let result = postcss([instance]).process(input)
Expand Down Expand Up @@ -228,10 +231,12 @@ afterEach(() => {

it('throws on wrong options', () => {
expect(() => {
autoprefixer({ browser: ['chrome 25', 'opera 12'] })
autoprefixer({ browser: ['chrome 25', 'opera 12'] } as autoprefixer.Options)
}).toThrow(/overrideBrowserslist/)
expect(() => {
autoprefixer({ browserslist: ['chrome 25', 'opera 12'] })
autoprefixer({
browserslist: ['chrome 25', 'opera 12']
} as autoprefixer.Options)
}).toThrow(/overrideBrowserslist/)
})

Expand Down Expand Up @@ -266,11 +271,14 @@ it('has default browsers', () => {
})

it('shows warning on browsers option', () => {
jest.spyOn(console, 'warn').mockImplementation(() => true)
let instance = autoprefixer({ browsers: ['last 1 version'] })
let consoleWarn = jest.spyOn(console, 'warn')
consoleWarn.mockImplementation(() => true)
let instance = autoprefixer({
browsers: ['last 1 version']
} as autoprefixer.Options)
expect(instance.browsers).toEqual(['last 1 version'])
expect(console.warn).toHaveBeenCalledTimes(1)
expect(console.warn.mock.calls[0][0]).toContain('overrideBrowserslist')
expect(consoleWarn).toHaveBeenCalledTimes(1)
expect(consoleWarn.mock.calls[0][0]).toContain('overrideBrowserslist')
})

it('passes statistics to Browserslist', () => {
Expand Down Expand Up @@ -427,11 +435,15 @@ it('prevents doubling prefixes', () => {
}
})

const isContainerNode = (node: ChildNode): node is AtRule | Rule => {
return 'nodes' in node
}

it('does not broke AST', () => {
function checkParent (node) {
function checkParent (node: Container) {
node.walk(child => {
expect(child.parent).toBeDefined()
if (child.nodes) checkParent(child)
if (isContainerNode(child)) checkParent(child)
})
}
for (let type of COMMONS) {
Expand All @@ -449,13 +461,13 @@ it('parses difficult files', () => {

it('marks parsing errors', () => {
expect(() => {
postcss([cleaner]).process('a {').css
let css = postcss([cleaner]).process('a {').css
}).toThrow('<css input>:1:1: Unclosed block')
})

it('shows file name in parse error', () => {
expect(() => {
postcss([cleaner]).process('a {', { from: 'a.css' }).css
let css = postcss([cleaner]).process('a {', { from: 'a.css' }).css
}).toThrow(/a.css:1:1: /)
})

Expand All @@ -476,7 +488,7 @@ it('sets browserslist environment', () => {
})

it('takes values from other PostCSS plugins', () => {
function plugin (root) {
function plugin (root: Container) {
root.walkDecls(i => {
i.value = 'calc(0)'
})
Expand Down Expand Up @@ -504,7 +516,7 @@ it('has disabled grid options by default', () => {
})

it('has different outputs for different grid options', () => {
function ap (gridValue) {
function ap (gridValue: autoprefixer.Options['grid']) {
return autoprefixer({
overrideBrowserslist: ['Edge 12', 'IE 10'],
grid: gridValue
Expand All @@ -531,14 +543,13 @@ it('has different outputs for different grid options', () => {
})

it('has different outputs for different grid environment variables', () => {
function ap (gridValue) {
function ap (gridValue: autoprefixer.GridValue) {
process.env.AUTOPREFIXER_GRID = gridValue
return autoprefixer({ overrideBrowserslist: ['Edge 12', 'IE 10'] })
}
let input = read('grid-options')
let outputAutoplace = read('grid-options.autoplace.out')
let outputNoAutoplace = read('grid-options.no-autoplace.out')
let outputDisabled = read('grid-options.disabled.out')

let resultAutoplace = postcss([ap('autoplace')]).process(input).css
expect(resultAutoplace).toEqual(outputAutoplace)
Expand Down Expand Up @@ -597,7 +608,8 @@ it('ignores unknown versions on request', () => {
})

it('works with CSS Modules', () => {
postcss([autoprefixer()]).process(':export { selectors: _1q6ho_2 }').css
let css = postcss([autoprefixer()]).process(':export { selectors: _1q6ho_2 }')
.css
})

describe('hacks', () => {
Expand Down
10 changes: 10 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"allowJs": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true
}
}

0 comments on commit 70a122b

Please sign in to comment.