Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typings #1382

Merged
merged 1 commit into from
Jan 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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[]> (
ai marked this conversation as resolved.
Show resolved Hide resolved
...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
ai marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

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
}
}