diff --git a/package-lock.json b/package-lock.json index 4b3470d1c..3c441984f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2128,6 +2128,10 @@ "resolved": "plugins/postcss-stepped-value-functions", "link": true }, + "node_modules/@csstools/postcss-system-ui-font-family": { + "resolved": "plugins/postcss-system-ui-font-family", + "link": true + }, "node_modules/@csstools/postcss-tape": { "resolved": "packages/postcss-tape", "link": true @@ -12028,6 +12032,30 @@ "postcss": "^8.4" } }, + "plugins/postcss-system-ui-font-family": { + "name": "@csstools/postcss-system-ui-font-family", + "version": "0.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "devDependencies": { + "@csstools/postcss-tape": "*" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "plugins/postcss-text-decoration-shorthand": { "name": "@csstools/postcss-text-decoration-shorthand", "version": "4.0.3", diff --git a/plugins/postcss-system-ui-font-family/.gitignore b/plugins/postcss-system-ui-font-family/.gitignore new file mode 100644 index 000000000..e5b28db4a --- /dev/null +++ b/plugins/postcss-system-ui-font-family/.gitignore @@ -0,0 +1,6 @@ +node_modules +package-lock.json +yarn.lock +*.result.css +*.result.css.map +*.result.html diff --git a/plugins/postcss-system-ui-font-family/.nvmrc b/plugins/postcss-system-ui-font-family/.nvmrc new file mode 100644 index 000000000..28d6ff1c8 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/.nvmrc @@ -0,0 +1 @@ +v25.1.0 diff --git a/plugins/postcss-system-ui-font-family/CHANGELOG.md b/plugins/postcss-system-ui-font-family/CHANGELOG.md new file mode 100644 index 000000000..90950723c --- /dev/null +++ b/plugins/postcss-system-ui-font-family/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changes to PostCSS System UI Font Family + +### Unreleased (major) + +- Initial version diff --git a/plugins/postcss-system-ui-font-family/INSTALL.md b/plugins/postcss-system-ui-font-family/INSTALL.md new file mode 100644 index 000000000..0d30ea33f --- /dev/null +++ b/plugins/postcss-system-ui-font-family/INSTALL.md @@ -0,0 +1,235 @@ +# Installing PostCSS System UI Font Family + +[PostCSS System UI Font Family] runs in all Node environments, with special instructions for: + +- [Node](#node) +- [PostCSS CLI](#postcss-cli) +- [PostCSS Load Config](#postcss-load-config) +- [Webpack](#webpack) +- [Next.js](#nextjs) +- [Gulp](#gulp) +- [Grunt](#grunt) + + + +## Node + +Add [PostCSS System UI Font Family] to your project: + +```bash +npm install postcss @csstools/postcss-system-ui-font-family --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +// commonjs +const postcss = require('postcss'); +const postcssSystemUIFontFamily = require('@csstools/postcss-system-ui-font-family'); + +postcss([ + postcssSystemUIFontFamily(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +```js +// esm +import postcss from 'postcss'; +import postcssSystemUIFontFamily from '@csstools/postcss-system-ui-font-family'; + +postcss([ + postcssSystemUIFontFamily(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +## PostCSS CLI + +Add [PostCSS CLI] to your project: + +```bash +npm install postcss-cli @csstools/postcss-system-ui-font-family --save-dev +``` + +Use [PostCSS System UI Font Family] in your `postcss.config.js` configuration file: + +```js +const postcssSystemUIFontFamily = require('@csstools/postcss-system-ui-font-family'); + +module.exports = { + plugins: [ + postcssSystemUIFontFamily(/* pluginOptions */) + ] +} +``` + +## PostCSS Load Config + +If your framework/CLI supports [`postcss-load-config`](https://github.com/postcss/postcss-load-config). + +```bash +npm install @csstools/postcss-system-ui-font-family --save-dev +``` + +`package.json`: + +```json +{ + "postcss": { + "plugins": { + "@csstools/postcss-system-ui-font-family": {} + } + } +} +``` + +`.postcssrc.json`: + +```json +{ + "plugins": { + "@csstools/postcss-system-ui-font-family": {} + } +} +``` + +_See the [README of `postcss-load-config`](https://github.com/postcss/postcss-load-config#usage) for more usage options._ + +## Webpack + +_Webpack version 5_ + +Add [PostCSS Loader] to your project: + +```bash +npm install postcss-loader @csstools/postcss-system-ui-font-family --save-dev +``` + +Use [PostCSS System UI Font Family] in your Webpack configuration: + +```js +module.exports = { + module: { + rules: [ + { + test: /\.css$/i, + use: [ + "style-loader", + { + loader: "css-loader", + options: { importLoaders: 1 }, + }, + { + loader: "postcss-loader", + options: { + postcssOptions: { + plugins: [ + // Other plugins, + [ + "@csstools/postcss-system-ui-font-family", + { + // Options + }, + ], + ], + }, + }, + }, + ], + }, + ], + }, +}; +``` + +## Next.js + +Read the instructions on how to [customize the PostCSS configuration in Next.js](https://nextjs.org/docs/advanced-features/customizing-postcss-config) + +```bash +npm install @csstools/postcss-system-ui-font-family --save-dev +``` + +Use [PostCSS System UI Font Family] in your `postcss.config.json` file: + +```json +{ + "plugins": [ + "@csstools/postcss-system-ui-font-family" + ] +} +``` + +```json5 +{ + "plugins": [ + [ + "@csstools/postcss-system-ui-font-family", + { + // Optionally add plugin options + } + ] + ] +} +``` + +## Gulp + +Add [Gulp PostCSS] to your project: + +```bash +npm install gulp-postcss @csstools/postcss-system-ui-font-family --save-dev +``` + +Use [PostCSS System UI Font Family] in your Gulpfile: + +```js +const postcss = require('gulp-postcss'); +const postcssSystemUIFontFamily = require('@csstools/postcss-system-ui-font-family'); + +gulp.task('css', function () { + var plugins = [ + postcssSystemUIFontFamily(/* pluginOptions */) + ]; + + return gulp.src('./src/*.css') + .pipe(postcss(plugins)) + .pipe(gulp.dest('.')); +}); +``` + +## Grunt + +Add [Grunt PostCSS] to your project: + +```bash +npm install grunt-postcss @csstools/postcss-system-ui-font-family --save-dev +``` + +Use [PostCSS System UI Font Family] in your Gruntfile: + +```js +const postcssSystemUIFontFamily = require('@csstools/postcss-system-ui-font-family'); + +grunt.loadNpmTasks('grunt-postcss'); + +grunt.initConfig({ + postcss: { + options: { + processors: [ + postcssSystemUIFontFamily(/* pluginOptions */) + ] + }, + dist: { + src: '*.css' + } + } +}); +``` + +[Gulp PostCSS]: https://github.com/postcss/gulp-postcss +[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss +[PostCSS]: https://github.com/postcss/postcss +[PostCSS CLI]: https://github.com/postcss/postcss-cli +[PostCSS Loader]: https://github.com/postcss/postcss-loader +[PostCSS System UI Font Family]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-system-ui-font-family +[Next.js]: https://nextjs.org diff --git a/plugins/postcss-system-ui-font-family/LICENSE.md b/plugins/postcss-system-ui-font-family/LICENSE.md new file mode 100644 index 000000000..e8ae93b9f --- /dev/null +++ b/plugins/postcss-system-ui-font-family/LICENSE.md @@ -0,0 +1,18 @@ +MIT No Attribution (MIT-0) + +Copyright © CSSTools Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the “Software”), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/postcss-system-ui-font-family/README.md b/plugins/postcss-system-ui-font-family/README.md new file mode 100644 index 000000000..c51f26dd4 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/README.md @@ -0,0 +1,91 @@ +# PostCSS System UI Font Family [PostCSS Logo][PostCSS] + +[npm version][npm-url] [Build Status][cli-url] [Discord][discord]

[Baseline Status][css-url] [CSS Standard Status][css-url] + +```bash +npm install @csstools/postcss-system-ui-font-family --save-dev +``` + +[PostCSS System UI Font Family] lets you use the `system-ui` keyword following the [CSS Fonts 4 Specification]. + +```css +.foo { + font: italic bold 12px/30px system-ui; + font-family: system-ui; + --font-family: system-ui; +} + +/* becomes */ + +.foo { + font: italic bold 12px/30px system-ui; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + --font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; +} +``` + +## Usage + +Add [PostCSS System UI Font Family] to your project: + +```bash +npm install postcss @csstools/postcss-system-ui-font-family --save-dev +``` + +Use it as a [PostCSS] plugin: + +```js +const postcss = require('postcss'); +const postcssSystemUIFontFamily = require('@csstools/postcss-system-ui-font-family'); + +postcss([ + postcssSystemUIFontFamily(/* pluginOptions */) +]).process(YOUR_CSS /*, processOptions */); +``` + +[PostCSS System UI Font Family] runs in all Node environments, with special +instructions for: + +- [Node](INSTALL.md#node) +- [PostCSS CLI](INSTALL.md#postcss-cli) +- [PostCSS Load Config](INSTALL.md#postcss-load-config) +- [Webpack](INSTALL.md#webpack) +- [Next.js](INSTALL.md#nextjs) +- [Gulp](INSTALL.md#gulp) +- [Grunt](INSTALL.md#grunt) + +## Options + +### preserve + +The `preserve` option determines whether the original notation +is preserved. By default, it is preserved. + +```js +postcssSystemUIFontFamily({ preserve: false }) +``` + +```css +.foo { + font: italic bold 12px/30px system-ui; + font-family: system-ui; + --font-family: system-ui; +} + +/* becomes */ + +.foo { + font: italic bold 12px/30px system-ui; + font-family: -apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + --font-family: -apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; +} +``` + +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test +[css-url]: https://cssdb.org/#system-ui-font-family +[discord]: https://discord.gg/bUadyRwkJS +[npm-url]: https://www.npmjs.com/package/@csstools/postcss-system-ui-font-family + +[PostCSS]: https://github.com/postcss/postcss +[PostCSS System UI Font Family]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-system-ui-font-family +[CSS Fonts 4 Specification]: https://drafts.csswg.org/css-fonts-4/#system-ui-def diff --git a/plugins/postcss-system-ui-font-family/api-extractor.json b/plugins/postcss-system-ui-font-family/api-extractor.json new file mode 100644 index 000000000..42058be51 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/api-extractor.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../api-extractor.json" +} diff --git a/plugins/postcss-system-ui-font-family/dist/index.cjs b/plugins/postcss-system-ui-font-family/dist/index.cjs new file mode 100644 index 000000000..090961a2a --- /dev/null +++ b/plugins/postcss-system-ui-font-family/dist/index.cjs @@ -0,0 +1 @@ +"use strict";var e=require("@csstools/css-parser-algorithms"),s=require("@csstools/css-tokenizer");const t=/^font(?:-family)?$/i,o=["system-ui","-apple-system","Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans","sans-serif"];const n=o.join(","),creator=r=>{const i=Object.assign({preserve:!0},r);return{postcssPlugin:"postcss-system-ui-font-family",Declaration(r){if(!r.variable&&!t.test(r.prop))return;if(r.value.includes(n))return;const a=r.value,l=s.tokenize({css:a}),u=e.parseCommaSeparatedListOfComponentValues(l),c=new Map;let p=-1;e:for(let t=0;t!("system-ui"!==e||!v)||!m.has(e)).map(t=>[new e.TokenNode([s.TokenType.Ident,t,-1,-1,{value:t}])]));var m,v;if(0===f.length)return;u.splice(p,1,...f);const d=e.stringify(u);d!==a&&(r.cloneBefore({prop:r.prop,value:d}),r.remove())}}};creator.postcss=!0,module.exports=creator; diff --git a/plugins/postcss-system-ui-font-family/dist/index.d.ts b/plugins/postcss-system-ui-font-family/dist/index.d.ts new file mode 100644 index 000000000..03cfbc7b1 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/dist/index.d.ts @@ -0,0 +1,12 @@ +import type { PluginCreator } from 'postcss'; + +declare const creator: PluginCreator; +export default creator; + +/** postcss-system-ui-font-family plugin options */ +export declare type pluginOptions = { + /** Preserve the original notation. default: true */ + preserve?: boolean; +}; + +export { } diff --git a/plugins/postcss-system-ui-font-family/dist/index.mjs b/plugins/postcss-system-ui-font-family/dist/index.mjs new file mode 100644 index 000000000..aaab436a7 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/dist/index.mjs @@ -0,0 +1 @@ +import{parseCommaSeparatedListOfComponentValues as e,isWhiteSpaceOrCommentNode as s,isTokenNode as t,stringify as o,TokenNode as n}from"@csstools/css-parser-algorithms";import{tokenize as r,isTokenIdent as i,TokenType as l}from"@csstools/css-tokenizer";const a=/^font(?:-family)?$/i,c=["system-ui","-apple-system","Segoe UI","Roboto","Ubuntu","Cantarell","Noto Sans","sans-serif"];const u=c.join(","),creator=p=>{const f=Object.assign({preserve:!0},p);return{postcssPlugin:"postcss-system-ui-font-family",Declaration(p){if(!p.variable&&!a.test(p.prop))return;if(p.value.includes(u))return;const m=p.value,v=r({css:m}),g=e(v),y=new Map;let h=-1;e:for(let e=0;e!("system-ui"!==e||!j)||!d.has(e)).map(e=>[new n([l.Ident,e,-1,-1,{value:e}])]));var d,j;if(0===b.length)return;g.splice(h,1,...b);const w=o(g);w!==m&&(p.cloneBefore({prop:p.prop,value:w}),p.remove())}}};creator.postcss=!0;export{creator as default}; diff --git a/plugins/postcss-system-ui-font-family/docs/README.md b/plugins/postcss-system-ui-font-family/docs/README.md new file mode 100644 index 000000000..846d3048b --- /dev/null +++ b/plugins/postcss-system-ui-font-family/docs/README.md @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + +
+ +[] lets you use the `system-ui` keyword following the [CSS Fonts 4 Specification]. + +```css + + +/* becomes */ + + +``` + + + + + +## Options + +### preserve + +The `preserve` option determines whether the original notation +is preserved. By default, it is preserved. + +```js +({ preserve: false }) +``` + +```css + + +/* becomes */ + + +``` + + +[CSS Fonts 4 Specification]: diff --git a/plugins/postcss-system-ui-font-family/package.json b/plugins/postcss-system-ui-font-family/package.json new file mode 100644 index 000000000..0db0a13a7 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/package.json @@ -0,0 +1,87 @@ +{ + "name": "@csstools/postcss-system-ui-font-family", + "description": "Use the `system-ui` keyword", + "version": "0.0.0", + "contributors": [ + { + "name": "Antonio Laguna", + "email": "antonio@laguna.es", + "url": "https://antonio.laguna.es" + }, + { + "name": "Romain Menke", + "email": "romainmenke@gmail.com" + } + ], + "license": "MIT-0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=18" + }, + "type": "module", + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.mjs" + }, + "require": { + "default": "./dist/index.cjs" + } + } + }, + "files": [ + "CHANGELOG.md", + "LICENSE.md", + "README.md", + "dist" + ], + "dependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + }, + "peerDependencies": { + "postcss": "^8.4" + }, + "devDependencies": { + "@csstools/postcss-tape": "*" + }, + "scripts": { + "build": "rollup -c ../../rollup/default.mjs", + "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs", + "lint": "node ../../.github/bin/format-package-json.mjs", + "prepublishOnly": "npm run build && npm run test", + "test": "node --test", + "test:rewrite-expects": "REWRITE_EXPECTS=true node --test" + }, + "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-system-ui-font-family#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/csstools/postcss-plugins.git", + "directory": "plugins/postcss-system-ui-font-family" + }, + "bugs": "https://github.com/csstools/postcss-plugins/issues", + "keywords": [ + "postcss-plugin" + ], + "csstools": { + "cssdbId": "system-ui-font-family", + "exportName": "postcssSystemUIFontFamily", + "humanReadableName": "PostCSS System UI Font Family", + "specUrl": "https://drafts.csswg.org/css-fonts-4/#system-ui-def" + }, + "volta": { + "extends": "../../package.json" + } +} diff --git a/plugins/postcss-system-ui-font-family/src/index.ts b/plugins/postcss-system-ui-font-family/src/index.ts new file mode 100644 index 000000000..976bcbe63 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/src/index.ts @@ -0,0 +1,130 @@ +import type { ComponentValue} from '@csstools/css-parser-algorithms'; +import { isTokenNode, isWhiteSpaceOrCommentNode, parseCommaSeparatedListOfComponentValues, stringify, TokenNode } from '@csstools/css-parser-algorithms'; +import { isTokenIdent, tokenize, TokenType } from '@csstools/css-tokenizer'; +import type { PluginCreator } from 'postcss'; + +/** postcss-system-ui-font-family plugin options */ +export type pluginOptions = { + /** Preserve the original notation. default: true */ + preserve?: boolean, +}; + +const PROPERTY_REGEX = /^font(?:-family)?$/i; + +const systemUiFamilies = [ + 'system-ui', + /* macOS 10.11-10.12 */ '-apple-system', + /* Windows 6+ */ 'Segoe UI', + /* Android 4+ */ 'Roboto', + /* Ubuntu 10.10+ */ 'Ubuntu', + /* Gnome 3+ */ 'Cantarell', + /* KDE Plasma 5+ */ 'Noto Sans', + /* fallback */ 'sans-serif', +]; + +function systemUIFamiliesAsComponentValues(existingSet: Map, preserve: boolean): Array> { + return systemUiFamilies.filter((family) => { + if (family === 'system-ui' && preserve) { + return true; + } + + return !existingSet.has(family) + }).map((family) => { + return [ + new TokenNode([TokenType.Ident, family, -1, -1, { value: family }]), + ] + }); +} + +const systemUIFamiliesList = systemUiFamilies.join(','); + +const creator: PluginCreator = (opts?: pluginOptions) => { + const options: pluginOptions = Object.assign( + { + preserve: true, + }, + opts, + ); + + return { + postcssPlugin: 'postcss-system-ui-font-family', + Declaration(decl): void { + if (!decl.variable && !PROPERTY_REGEX.test(decl.prop)) { + return; + } + + if (decl.value.includes(systemUIFamiliesList)) { + return; + } + + const originalValue = decl.value; + + const tokens = tokenize({ css: originalValue }); + const componentValuesList = parseCommaSeparatedListOfComponentValues(tokens) + + const foundFamilies = new Map() + let symstemUI_Index = -1; + + TOP_LEVEL: + for (let i = 0; i < componentValuesList.length; i++) { + const componentValues = componentValuesList[i]; + + const fontFamilyParts = []; + + for (let j = 0; j < componentValues.length; j++) { + const componentValue = componentValues[j]; + if (isWhiteSpaceOrCommentNode(componentValue)) { + continue; + } + + if (!isTokenNode(componentValue)) { + continue TOP_LEVEL; + } + + const token = componentValue.value; + if (!isTokenIdent(token)) { + continue TOP_LEVEL; + } + + if (token[4].value.toLowerCase() === 'system-ui') { + symstemUI_Index = i; + } + + fontFamilyParts.push(token[4].value); + } + + const fontFamily = fontFamilyParts.join(' '); + if (systemUiFamilies.includes(fontFamily)) { + foundFamilies.set(fontFamily, i) + } + } + + if (symstemUI_Index === -1) { + return; + } + + const replacements = systemUIFamiliesAsComponentValues(foundFamilies, !!options.preserve); + if (replacements.length === 0) { + return; + } + + componentValuesList.splice(symstemUI_Index, 1, ...replacements); + + const modified = stringify(componentValuesList); + if (modified === originalValue) { + return; + } + + decl.cloneBefore({ + prop: decl.prop, + value: modified, + }); + + decl.remove(); + }, + }; +}; + +creator.postcss = true; + +export default creator; diff --git a/plugins/postcss-system-ui-font-family/test/_import.mjs b/plugins/postcss-system-ui-font-family/test/_import.mjs new file mode 100644 index 000000000..2dba7d5ec --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/_import.mjs @@ -0,0 +1,10 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import plugin from '@csstools/postcss-system-ui-font-family'; + +test('import', () => { + plugin(); + assert.ok(plugin.postcss, 'should have "postcss flag"'); + assert.equal(typeof plugin, 'function', 'should return a function'); +}); + diff --git a/plugins/postcss-system-ui-font-family/test/_require.cjs b/plugins/postcss-system-ui-font-family/test/_require.cjs new file mode 100644 index 000000000..6ac2f679c --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/_require.cjs @@ -0,0 +1,9 @@ +const assert = require('node:assert/strict'); +const test = require('node:test'); +const plugin = require('@csstools/postcss-system-ui-font-family'); + +test('require', () => { + plugin(); + assert.ok(plugin.postcss, 'should have "postcss flag"'); + assert.equal(typeof plugin, 'function', 'should return a function'); +}); diff --git a/plugins/postcss-system-ui-font-family/test/_tape.mjs b/plugins/postcss-system-ui-font-family/test/_tape.mjs new file mode 100644 index 000000000..5b56ff664 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/_tape.mjs @@ -0,0 +1,17 @@ +import { postcssTape } from '@csstools/postcss-tape'; +import plugin from '@csstools/postcss-system-ui-font-family'; + +postcssTape(plugin)({ + basic: { + message: 'supports basic usage', + }, + 'examples/example': { + message: 'minimal example', + }, + 'examples/example:preserve-false': { + message: 'minimal example', + options: { + preserve: false, + }, + }, +}); diff --git a/plugins/postcss-system-ui-font-family/test/basic.css b/plugins/postcss-system-ui-font-family/test/basic.css new file mode 100644 index 000000000..e1aabc468 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/basic.css @@ -0,0 +1,27 @@ +.foo { + font: italic bold 12px/30px system-ui, Helvetica Neue, sans-serif; + font: italic bold 12px/30px system-ui, sans-serif; + font: italic bold 12px/30px sans-serif; + font-family: system-ui, Helvetica Neue, sans-serif; + font-family: system-ui, sans-serif; + font-family: system-ui; + font-family: "Droid Sans", system-ui, sans-serif; + --font-family: system-ui; +} + +.ignore { + font-family: sans-serif; +} + +.ignore { + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; +} + +.tab-between-idents { + font-family: system-ui, Segoe UI; +} + +.comment-between-idents { + font-family: system-ui, Segoe /* foo */UI; +} diff --git a/plugins/postcss-system-ui-font-family/test/basic.expect.css b/plugins/postcss-system-ui-font-family/test/basic.expect.css new file mode 100644 index 000000000..f04ac87b5 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/basic.expect.css @@ -0,0 +1,27 @@ +.foo { + font: italic bold 12px/30px system-ui, Helvetica Neue, sans-serif; + font: italic bold 12px/30px system-ui, sans-serif; + font: italic bold 12px/30px sans-serif; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans, Helvetica Neue, sans-serif; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans, sans-serif; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + font-family: "Droid Sans",system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans, sans-serif; + --font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; +} + +.ignore { + font-family: sans-serif; +} + +.ignore { + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + font-family: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif; +} + +.tab-between-idents { + font-family: system-ui,-apple-system,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif, Segoe UI; +} + +.comment-between-idents { + font-family: system-ui,-apple-system,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif, Segoe UI; +} diff --git a/plugins/postcss-system-ui-font-family/test/examples/example.css b/plugins/postcss-system-ui-font-family/test/examples/example.css new file mode 100644 index 000000000..6bea38d75 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/examples/example.css @@ -0,0 +1,5 @@ +.foo { + font: italic bold 12px/30px system-ui; + font-family: system-ui; + --font-family: system-ui; +} diff --git a/plugins/postcss-system-ui-font-family/test/examples/example.expect.css b/plugins/postcss-system-ui-font-family/test/examples/example.expect.css new file mode 100644 index 000000000..3d70d1092 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/examples/example.expect.css @@ -0,0 +1,5 @@ +.foo { + font: italic bold 12px/30px system-ui; + font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + --font-family: system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; +} diff --git a/plugins/postcss-system-ui-font-family/test/examples/example.preserve-false.expect.css b/plugins/postcss-system-ui-font-family/test/examples/example.preserve-false.expect.css new file mode 100644 index 000000000..f4a483f7a --- /dev/null +++ b/plugins/postcss-system-ui-font-family/test/examples/example.preserve-false.expect.css @@ -0,0 +1,5 @@ +.foo { + font: italic bold 12px/30px system-ui; + font-family: -apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; + --font-family: -apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif; +} diff --git a/plugins/postcss-system-ui-font-family/tsconfig.json b/plugins/postcss-system-ui-font-family/tsconfig.json new file mode 100644 index 000000000..500af6d26 --- /dev/null +++ b/plugins/postcss-system-ui-font-family/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": ".", + "strict": true + }, + "include": ["./src/**/*"], + "exclude": ["dist"] +} diff --git a/rollup/configs/externals.mjs b/rollup/configs/externals.mjs index 03066bdc5..352c46f99 100644 --- a/rollup/configs/externals.mjs +++ b/rollup/configs/externals.mjs @@ -61,6 +61,7 @@ export const externalsForCLI = [ '@csstools/postcss-scope-pseudo-class', '@csstools/postcss-sign-functions', '@csstools/postcss-stepped-value-functions', + '@csstools/postcss-system-ui-font-family', '@csstools/postcss-text-decoration-shorthand', '@csstools/postcss-trigonometric-functions', '@csstools/postcss-unset-value', @@ -169,6 +170,7 @@ export const externalsForPlugin = [ '@csstools/postcss-scope-pseudo-class', '@csstools/postcss-sign-functions', '@csstools/postcss-stepped-value-functions', + '@csstools/postcss-system-ui-font-family', '@csstools/postcss-text-decoration-shorthand', '@csstools/postcss-trigonometric-functions', '@csstools/postcss-unset-value',