diff --git a/.github/ISSUE_TEMPLATE/css-issue.yml b/.github/ISSUE_TEMPLATE/css-issue.yml index 9fb785fc99..9adf1f34b6 100644 --- a/.github/ISSUE_TEMPLATE/css-issue.yml +++ b/.github/ISSUE_TEMPLATE/css-issue.yml @@ -82,6 +82,7 @@ body: - PostCSS Container Rule Prelude List - PostCSS Content Alt Text - PostCSS Contrast Color Functions + - PostCSS Custom Functions - PostCSS Custom Media Queries - PostCSS Custom Properties - PostCSS Custom Selectors diff --git a/.github/ISSUE_TEMPLATE/plugin-issue.yml b/.github/ISSUE_TEMPLATE/plugin-issue.yml index 78c46d0d44..81e8da72e6 100644 --- a/.github/ISSUE_TEMPLATE/plugin-issue.yml +++ b/.github/ISSUE_TEMPLATE/plugin-issue.yml @@ -79,6 +79,7 @@ body: - PostCSS Container Rule Prelude List - PostCSS Content Alt Text - PostCSS Contrast Color Functions + - PostCSS Custom Functions - PostCSS Custom Media Queries - PostCSS Custom Properties - PostCSS Custom Selectors diff --git a/.github/labeler.yml b/.github/labeler.yml index 7aa485ef57..845385eb4f 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -161,6 +161,12 @@ - plugins/postcss-contrast-color-function/** - experimental/postcss-contrast-color-function/** +"plugins/postcss-custom-functions": + - changed-files: + - any-glob-to-any-file: + - plugins/postcss-custom-functions/** + - experimental/postcss-custom-functions/** + "plugins/postcss-custom-media": - changed-files: - any-glob-to-any-file: diff --git a/package-lock.json b/package-lock.json index eb4a4df7ad..597aaebf59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -858,6 +858,10 @@ "resolved": "cli/csstools-cli", "link": true }, + "node_modules/@csstools/custom-function-parser": { + "resolved": "packages/custom-function-parser", + "link": true + }, "node_modules/@csstools/generate-test-cases": { "resolved": "packages/generate-test-cases", "link": true @@ -918,6 +922,10 @@ "resolved": "plugins/postcss-contrast-color-function", "link": true }, + "node_modules/@csstools/postcss-custom-functions": { + "resolved": "plugins/postcss-custom-functions", + "link": true + }, "node_modules/@csstools/postcss-debug-logger": { "resolved": "plugins/postcss-debug-logger", "link": true @@ -8310,6 +8318,28 @@ "node": ">=20.19.0" } }, + "packages/custom-function-parser": { + "name": "@csstools/custom-function-parser", + "version": "0.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.1", + "@csstools/css-tokenizer": "^4.0.2" + } + }, "packages/generate-test-cases": { "name": "@csstools/generate-test-cases", "version": "1.0.0", @@ -9256,6 +9286,37 @@ "postcss": "^8.4" } }, + "plugins/postcss-custom-functions": { + "name": "@csstools/postcss-custom-functions", + "version": "0.0.0", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/cascade-layer-name-parser": "^3.0.1", + "@csstools/css-parser-algorithms": "^4.0.1", + "@csstools/css-tokenizer": "^4.0.2", + "@csstools/custom-function-parser": "^0.0.0" + }, + "devDependencies": { + "@csstools/postcss-tape": "*", + "puppeteer": "^25.11.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, "plugins/postcss-custom-media": { "version": "12.0.2", "funding": [ diff --git a/packages/custom-function-parser/.gitignore b/packages/custom-function-parser/.gitignore new file mode 100644 index 0000000000..8b84de0347 --- /dev/null +++ b/packages/custom-function-parser/.gitignore @@ -0,0 +1,6 @@ +node_modules +package-lock.json +yarn.lock +*.result.css +*.result.css.map +*.result.json diff --git a/packages/custom-function-parser/.nvmrc b/packages/custom-function-parser/.nvmrc new file mode 100644 index 0000000000..b807a943cb --- /dev/null +++ b/packages/custom-function-parser/.nvmrc @@ -0,0 +1 @@ +v26.1.0 diff --git a/packages/custom-function-parser/CHANGELOG.md b/packages/custom-function-parser/CHANGELOG.md new file mode 100644 index 0000000000..1230a0570c --- /dev/null +++ b/packages/custom-function-parser/CHANGELOG.md @@ -0,0 +1,5 @@ +# Changes to Custom Function Parser + +### Unreleased (major) + +- Initial version diff --git a/packages/custom-function-parser/LICENSE.md b/packages/custom-function-parser/LICENSE.md new file mode 100644 index 0000000000..af5411fa24 --- /dev/null +++ b/packages/custom-function-parser/LICENSE.md @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright 2022 Romain Menke, Antonio Laguna + +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, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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/packages/custom-function-parser/README.md b/packages/custom-function-parser/README.md new file mode 100644 index 0000000000..8c4ea70429 --- /dev/null +++ b/packages/custom-function-parser/README.md @@ -0,0 +1,28 @@ +# Custom Function Parser for CSS + +[npm version][npm-url] +[Build Status][cli-url] +[Discord][discord] + +Implemented from : https://www.w3.org/TR/mediaqueries-5/ + +## Usage + +Add [Custom Function Parser] to your project: + +```bash +npm install @csstools/custom-function-parser @csstools/css-parser-algorithms @csstools/css-tokenizer --save-dev +``` + +[Custom Function Parser] depends on our CSS tokenizer and parser algorithms. +It must be used together with `@csstools/css-tokenizer` and `@csstools/css-parser-algorithms`. + +```ts +// TODO +``` + +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test +[discord]: https://discord.gg/bUadyRwkJS +[npm-url]: https://www.npmjs.com/package/@csstools/custom-function-parser + +[Custom Function Parser]: https://github.com/csstools/postcss-plugins/tree/main/packages/custom-function-parser diff --git a/packages/custom-function-parser/api-extractor.json b/packages/custom-function-parser/api-extractor.json new file mode 100644 index 0000000000..ccef9beeb0 --- /dev/null +++ b/packages/custom-function-parser/api-extractor.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../api-extractor.json", + "docModel": { + "enabled": true + } +} diff --git a/packages/custom-function-parser/dist/index.d.ts b/packages/custom-function-parser/dist/index.d.ts new file mode 100644 index 0000000000..bc0198b30b --- /dev/null +++ b/packages/custom-function-parser/dist/index.d.ts @@ -0,0 +1,72 @@ +import type { CSSToken } from '@csstools/css-tokenizer'; +import { FunctionNode } from '@csstools/css-parser-algorithms'; +import type { ParseError } from '@csstools/css-tokenizer'; +import type { TokenColon } from '@csstools/css-tokenizer'; +import type { TokenIdent } from '@csstools/css-tokenizer'; + +export declare class CustomFunction { + type: NodeType; + function: FunctionNode; + parameters: Array; + returnsKeyword: Array; + returnType: Array; + before: Array; + after: Array; + constructor(fn: FunctionNode, parameters: Array, returnsKeyword: Array, returnType: Array, before?: Array, after?: Array); + getName(): string; + getReturnType(): string; + tokens(): Array; + toString(): string; + /** + * @internal + */ + toJSON(): Record; + /** + * @internal + */ + isCustomFunction(): this is CustomFunction; + static isCustomFunction(x: unknown): x is CustomFunction; +} + +export declare class FunctionParameter { + type: NodeType; + name: TokenIdent; + argumentType: Array; + colon: TokenColon | null; + defaultValue: Array; + before: Array; + after: Array; + constructor(name: TokenIdent, argumentType: Array, colon: TokenColon | null, defaultValue: Array, before?: Array, after?: Array); + getName(): string; + getNameToken(): TokenIdent | null; + getArgumentType(): string; + getDefaultValue(): string; + /** + * @internal + */ + toJSON(): Record; + /** + * @internal + */ + isFunctionParameter(): this is FunctionParameter; + static isFunctionParameter(x: unknown): x is FunctionParameter; +} + +export declare function isCustomFunction(x: unknown): x is CustomFunction; + +export declare function isFunctionParameter(x: unknown): x is FunctionParameter; + +export declare enum NodeType { + CustomFunction = "custom-function", + FunctionParameter = "function-parameter" +} + +export declare function parse(source: string, options?: { + onParseError?: (error: ParseError) => void; +}): CustomFunction | false; + +export declare function parseFromTokens(tokens: Array, options?: { + onParseError?: (error: ParseError) => void; +}): CustomFunction | false; + +export { } diff --git a/packages/custom-function-parser/dist/index.mjs b/packages/custom-function-parser/dist/index.mjs new file mode 100644 index 0000000000..4a0221b0bb --- /dev/null +++ b/packages/custom-function-parser/dist/index.mjs @@ -0,0 +1 @@ +import{parseListOfComponentValues as t,isWhiteSpaceOrCommentNode as e,isFunctionNode as r,isTokenNode as n,isWhitespaceNode as s,isSimpleBlockNode as o}from"@csstools/css-parser-algorithms";import{stringify as a,isTokenComment as i,isTokenIdent as u,isTokenComma as l,isTokenDelim as c,isTokenColon as f,isTokenOpenCurly as m,tokenize as h}from"@csstools/css-tokenizer";var p;!function(t){t.CustomFunction="custom-function",t.FunctionParameter="function-parameter"}(p||(p={}));class CustomFunction{type=p.CustomFunction;function;parameters;returnsKeyword;returnType;before;after;constructor(t,e,r,n,s=[],o=[]){this.function=t,this.parameters=e,this.returnsKeyword=r,this.returnType=n,this.before=s,this.after=o}getName(){return this.function.getName()}getReturnType(){const n=t(this.returnType).filter(t=>!e(t));return 1===n.length&&r(n[0])&&"type"===n[0].getName().toLowerCase()?a(...n[0].value.flatMap(t=>t.tokens()).filter(t=>!i(t))).trim():a(...this.returnType.filter(t=>!i(t))).trim()}tokens(){return[...this.before,...this.function.tokens(),...this.returnsKeyword,...this.returnType,...this.after]}toString(){return a(...this.before)+a(...this.function.tokens())+a(...this.returnsKeyword)+a(...this.returnType)+a(...this.after)}toJSON(){return{type:this.type,name:this.getName(),string:this.toString(),tokens:this.tokens(),parameters:this.parameters.map(t=>t.toJSON()),returnsKeyword:this.returnsKeyword,returnType:this.returnType,before:this.before,after:this.after}}isCustomFunction(){return CustomFunction.isCustomFunction(this)}static isCustomFunction(t){return!!t&&(t instanceof CustomFunction&&t.type===p.CustomFunction)}}class FunctionParameter{type=p.FunctionParameter;name;argumentType;colon;defaultValue;before;after;constructor(t,e,r,n,s=[],o=[]){this.name=t,this.argumentType=e,this.colon=r,this.defaultValue=n,this.before=s,this.after=o}getName(){return this.name[4].value}getNameToken(){return this.name}getArgumentType(){return a(...this.argumentType.filter(t=>!i(t))).trim()}getDefaultValue(){return a(...this.defaultValue).trim()}toJSON(){return{type:this.type,name:this.getName(),argumentType:this.argumentType,colon:this.colon,defaultValue:this.defaultValue,before:this.before,after:this.after}}isFunctionParameter(){return FunctionParameter.isFunctionParameter(this)}static isFunctionParameter(t){return!!t&&(t instanceof FunctionParameter&&t.type===p.FunctionParameter)}}function parseCustomFunction(t){let s=null,o=-1,a=-1,i=-1,l=t.length;for(let l=0;li;r--){const n=t[r];if(!e(n))break;l=r}const c=parseFunctionParameters(s.value);return!!c&&new CustomFunction(s,c,-1===i?[]:t.slice(o+1,i).flatMap(t=>t.tokens()),-1===i?[]:t.slice(i,l).flatMap(t=>t.tokens()),t.slice(0,o).flatMap(t=>t.tokens()),t.slice(l).flatMap(t=>t.tokens()))}function parseFunctionParameters(t){if(!t.some(t=>!e(t)))return[];const r=[],n=new Set;for(let e=0;e0&&n(r)&&c(r.value)&&">"===r.value[4].value)a--;else if(-1===p&&0===a&&n(r)&&f(r.value))p=y,F=r.value;else if(-1===p){if(-1!==p)return!1}else g=y}}if(!h)return!1;if(-1!==p&&-1===g)return!1;const k=-1!==p?p-1:y-1;for(let e=t.length-1;e>Math.max(k,g);e--){const r=t[e];if(!s(r))break;v=e}let P;{const n=t.slice(i+1,k+1),s=n.filter(t=>!e(t));P=1===s.length&&r(s[0])&&"type"===s[0].getName().toLowerCase()?s[0].value.flatMap(t=>t.tokens()):n.flatMap(t=>t.tokens())}let T=[];if(-1!==g){const r=t.slice(p+1,v);if(hasTopLevelImportant(r))return!1;const n=r.filter(t=>!e(t));T=1===n.length&&o(n[0])&&m(n[0].startToken)?n[0].value.flatMap(t=>t.tokens()):r.flatMap(t=>t.tokens())}return{advance:y,node:new FunctionParameter(h,P,F,T,t.slice(0,i).flatMap(t=>t.tokens()),t.slice(v,y+1).flatMap(t=>t.tokens()))}}function hasTopLevelImportant(t){for(let r=0;r{n=!0,r?.onParseError?.(t)}});return!n&&parseCustomFunction(s)}function parse(t,e){return parseFromTokens(h({css:t},{onParseError:e?.onParseError}),e)}function isCustomFunction(t){return CustomFunction.isCustomFunction(t)}function isFunctionParameter(t){return FunctionParameter.isFunctionParameter(t)}export{CustomFunction,FunctionParameter,p as NodeType,isCustomFunction,isFunctionParameter,parse,parseFromTokens}; diff --git a/packages/custom-function-parser/docs/custom-function-parser.api.json b/packages/custom-function-parser/docs/custom-function-parser.api.json new file mode 100644 index 0000000000..f8cbd831d0 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.api.json @@ -0,0 +1,1859 @@ +{ + "metadata": { + "toolPackage": "@microsoft/api-extractor", + "schemaVersion": 1011, + "oldestForwardsCompatibleVersion": 1001, + "tsdocConfig": { + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": true, + "tagDefinitions": [ + { + "tagName": "@alpha", + "syntaxKind": "modifier" + }, + { + "tagName": "@beta", + "syntaxKind": "modifier" + }, + { + "tagName": "@defaultValue", + "syntaxKind": "block" + }, + { + "tagName": "@decorator", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@deprecated", + "syntaxKind": "block" + }, + { + "tagName": "@eventProperty", + "syntaxKind": "modifier" + }, + { + "tagName": "@example", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@experimental", + "syntaxKind": "modifier" + }, + { + "tagName": "@inheritDoc", + "syntaxKind": "inline" + }, + { + "tagName": "@internal", + "syntaxKind": "modifier" + }, + { + "tagName": "@label", + "syntaxKind": "inline" + }, + { + "tagName": "@link", + "syntaxKind": "inline", + "allowMultiple": true + }, + { + "tagName": "@override", + "syntaxKind": "modifier" + }, + { + "tagName": "@packageDocumentation", + "syntaxKind": "modifier" + }, + { + "tagName": "@param", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@privateRemarks", + "syntaxKind": "block" + }, + { + "tagName": "@public", + "syntaxKind": "modifier" + }, + { + "tagName": "@readonly", + "syntaxKind": "modifier" + }, + { + "tagName": "@remarks", + "syntaxKind": "block" + }, + { + "tagName": "@returns", + "syntaxKind": "block" + }, + { + "tagName": "@sealed", + "syntaxKind": "modifier" + }, + { + "tagName": "@see", + "syntaxKind": "block" + }, + { + "tagName": "@throws", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@typeParam", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@virtual", + "syntaxKind": "modifier" + }, + { + "tagName": "@jsx", + "syntaxKind": "block" + }, + { + "tagName": "@jsxRuntime", + "syntaxKind": "block" + }, + { + "tagName": "@jsxFrag", + "syntaxKind": "block" + }, + { + "tagName": "@jsxImportSource", + "syntaxKind": "block" + }, + { + "tagName": "@betaDocumentation", + "syntaxKind": "modifier" + }, + { + "tagName": "@internalRemarks", + "syntaxKind": "block" + }, + { + "tagName": "@preapproved", + "syntaxKind": "modifier" + } + ], + "supportForTags": { + "@alpha": true, + "@beta": true, + "@defaultValue": true, + "@decorator": true, + "@deprecated": true, + "@eventProperty": true, + "@example": true, + "@experimental": true, + "@inheritDoc": true, + "@internal": true, + "@label": true, + "@link": true, + "@override": true, + "@packageDocumentation": true, + "@param": true, + "@privateRemarks": true, + "@public": true, + "@readonly": true, + "@remarks": true, + "@returns": true, + "@sealed": true, + "@see": true, + "@throws": true, + "@typeParam": true, + "@virtual": true, + "@betaDocumentation": true, + "@internalRemarks": true, + "@preapproved": true + }, + "reportUnsupportedHtmlElements": false + } + }, + "kind": "Package", + "canonicalReference": "@csstools/custom-function-parser!", + "docComment": "", + "name": "@csstools/custom-function-parser", + "preserveMemberOrder": false, + "members": [ + { + "kind": "EntryPoint", + "canonicalReference": "@csstools/custom-function-parser!", + "name": "", + "preserveMemberOrder": false, + "members": [ + { + "kind": "Class", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:class", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare class CustomFunction " + } + ], + "fileUrlPath": "dist/_types/nodes/custom-function.d.ts", + "releaseTag": "Public", + "isAbstract": false, + "name": "CustomFunction", + "preserveMemberOrder": false, + "members": [ + { + "kind": "Constructor", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:constructor(1)", + "docComment": "/**\n * Constructs a new instance of the `CustomFunction` class\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "constructor(fn: " + }, + { + "kind": "Reference", + "text": "FunctionNode", + "canonicalReference": "@csstools/css-parser-algorithms!FunctionNode:class" + }, + { + "kind": "Content", + "text": ", parameters: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "FunctionParameter", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:class" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", returnsKeyword: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", returnType: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", before?: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", after?: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ");" + } + ], + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "fn", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + }, + { + "parameterName": "parameters", + "parameterTypeTokenRange": { + "startIndex": 3, + "endIndex": 7 + }, + "isOptional": false + }, + { + "parameterName": "returnsKeyword", + "parameterTypeTokenRange": { + "startIndex": 8, + "endIndex": 12 + }, + "isOptional": false + }, + { + "parameterName": "returnType", + "parameterTypeTokenRange": { + "startIndex": 13, + "endIndex": 17 + }, + "isOptional": false + }, + { + "parameterName": "before", + "parameterTypeTokenRange": { + "startIndex": 18, + "endIndex": 22 + }, + "isOptional": true + }, + { + "parameterName": "after", + "parameterTypeTokenRange": { + "startIndex": 23, + "endIndex": 27 + }, + "isOptional": true + } + ] + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#after:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "after: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "after", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#before:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "before: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "before", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#function:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "function: " + }, + { + "kind": "Reference", + "text": "FunctionNode", + "canonicalReference": "@csstools/css-parser-algorithms!FunctionNode:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "function", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#getName:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getName(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getName" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#getReturnType:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getReturnType(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getReturnType" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction.isCustomFunction:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "static isCustomFunction(x: " + }, + { + "kind": "Content", + "text": "unknown" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "@csstools/custom-function-parser!~x" + }, + { + "kind": "Content", + "text": " is " + }, + { + "kind": "Reference", + "text": "CustomFunction", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "isOptional": false, + "isAbstract": false, + "name": "isCustomFunction" + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#parameters:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "parameters: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "FunctionParameter", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:class" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "parameters", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#returnsKeyword:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "returnsKeyword: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "returnsKeyword", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#returnType:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "returnType: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "returnType", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#tokens:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "tokens(): " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "tokens" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#toString:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "toString(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "toString" + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction#type:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "type: " + }, + { + "kind": "Reference", + "text": "NodeType", + "canonicalReference": "@csstools/custom-function-parser!NodeType:enum" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "type", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + } + ], + "implementsTokenRanges": [] + }, + { + "kind": "Class", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:class", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare class FunctionParameter " + } + ], + "fileUrlPath": "dist/_types/nodes/function-parameter.d.ts", + "releaseTag": "Public", + "isAbstract": false, + "name": "FunctionParameter", + "preserveMemberOrder": false, + "members": [ + { + "kind": "Constructor", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:constructor(1)", + "docComment": "/**\n * Constructs a new instance of the `FunctionParameter` class\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "constructor(name: " + }, + { + "kind": "Reference", + "text": "TokenIdent", + "canonicalReference": "@csstools/css-tokenizer!TokenIdent:interface" + }, + { + "kind": "Content", + "text": ", argumentType: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", colon: " + }, + { + "kind": "Reference", + "text": "TokenColon", + "canonicalReference": "@csstools/css-tokenizer!TokenColon:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ", defaultValue: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", before?: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", after?: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ");" + } + ], + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "name", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + }, + { + "parameterName": "argumentType", + "parameterTypeTokenRange": { + "startIndex": 3, + "endIndex": 7 + }, + "isOptional": false + }, + { + "parameterName": "colon", + "parameterTypeTokenRange": { + "startIndex": 8, + "endIndex": 10 + }, + "isOptional": false + }, + { + "parameterName": "defaultValue", + "parameterTypeTokenRange": { + "startIndex": 11, + "endIndex": 15 + }, + "isOptional": false + }, + { + "parameterName": "before", + "parameterTypeTokenRange": { + "startIndex": 16, + "endIndex": 20 + }, + "isOptional": true + }, + { + "parameterName": "after", + "parameterTypeTokenRange": { + "startIndex": 21, + "endIndex": 25 + }, + "isOptional": true + } + ] + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#after:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "after: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "after", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#argumentType:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "argumentType: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "argumentType", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#before:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "before: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "before", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#colon:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "colon: " + }, + { + "kind": "Reference", + "text": "TokenColon", + "canonicalReference": "@csstools/css-tokenizer!TokenColon:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "colon", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 3 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#defaultValue:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "defaultValue: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "defaultValue", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#getArgumentType:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getArgumentType(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getArgumentType" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#getDefaultValue:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getDefaultValue(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getDefaultValue" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#getName:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getName(): " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getName" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#getNameToken:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "getNameToken(): " + }, + { + "kind": "Reference", + "text": "TokenIdent", + "canonicalReference": "@csstools/css-tokenizer!TokenIdent:interface" + }, + { + "kind": "Content", + "text": " | null" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": false, + "returnTypeTokenRange": { + "startIndex": 1, + "endIndex": 3 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [], + "isOptional": false, + "isAbstract": false, + "name": "getNameToken" + }, + { + "kind": "Method", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter.isFunctionParameter:member(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "static isFunctionParameter(x: " + }, + { + "kind": "Content", + "text": "unknown" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "@csstools/custom-function-parser!~x" + }, + { + "kind": "Content", + "text": " is " + }, + { + "kind": "Reference", + "text": "FunctionParameter", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isStatic": true, + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, + "releaseTag": "Public", + "isProtected": false, + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "isOptional": false, + "isAbstract": false, + "name": "isFunctionParameter" + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#name:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "name: " + }, + { + "kind": "Reference", + "text": "TokenIdent", + "canonicalReference": "@csstools/css-tokenizer!TokenIdent:interface" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "name", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + }, + { + "kind": "Property", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter#type:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "type: " + }, + { + "kind": "Reference", + "text": "NodeType", + "canonicalReference": "@csstools/custom-function-parser!NodeType:enum" + }, + { + "kind": "Content", + "text": ";" + } + ], + "isReadonly": false, + "isOptional": false, + "releaseTag": "Public", + "name": "type", + "propertyTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isStatic": false, + "isProtected": false, + "isAbstract": false + } + ], + "implementsTokenRanges": [] + }, + { + "kind": "Function", + "canonicalReference": "@csstools/custom-function-parser!isCustomFunction:function(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function isCustomFunction(x: " + }, + { + "kind": "Content", + "text": "unknown" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "@csstools/custom-function-parser!~x" + }, + { + "kind": "Content", + "text": " is " + }, + { + "kind": "Reference", + "text": "CustomFunction", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "dist/_types/util/type-predicates.d.ts", + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "isCustomFunction" + }, + { + "kind": "Function", + "canonicalReference": "@csstools/custom-function-parser!isFunctionParameter:function(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function isFunctionParameter(x: " + }, + { + "kind": "Content", + "text": "unknown" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "x", + "canonicalReference": "@csstools/custom-function-parser!~x" + }, + { + "kind": "Content", + "text": " is " + }, + { + "kind": "Reference", + "text": "FunctionParameter", + "canonicalReference": "@csstools/custom-function-parser!FunctionParameter:class" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "dist/_types/util/type-predicates.d.ts", + "returnTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "x", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + } + ], + "name": "isFunctionParameter" + }, + { + "kind": "Enum", + "canonicalReference": "@csstools/custom-function-parser!NodeType:enum", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare enum NodeType " + } + ], + "fileUrlPath": "dist/_types/util/node-type.d.ts", + "releaseTag": "Public", + "name": "NodeType", + "preserveMemberOrder": false, + "members": [ + { + "kind": "EnumMember", + "canonicalReference": "@csstools/custom-function-parser!NodeType.CustomFunction:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "CustomFunction = " + }, + { + "kind": "Content", + "text": "\"custom-function\"" + } + ], + "initializerTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "name": "CustomFunction" + }, + { + "kind": "EnumMember", + "canonicalReference": "@csstools/custom-function-parser!NodeType.FunctionParameter:member", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "FunctionParameter = " + }, + { + "kind": "Content", + "text": "\"function-parameter\"" + } + ], + "initializerTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "releaseTag": "Public", + "name": "FunctionParameter" + } + ] + }, + { + "kind": "Function", + "canonicalReference": "@csstools/custom-function-parser!parse:function(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function parse(source: " + }, + { + "kind": "Content", + "text": "string" + }, + { + "kind": "Content", + "text": ", options?: " + }, + { + "kind": "Content", + "text": "{\n onParseError?: (error: " + }, + { + "kind": "Reference", + "text": "ParseError", + "canonicalReference": "@csstools/css-tokenizer!ParseError:class" + }, + { + "kind": "Content", + "text": ") => void;\n}" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "CustomFunction", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:class" + }, + { + "kind": "Content", + "text": " | false" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "dist/_types/parser/parse.d.ts", + "returnTypeTokenRange": { + "startIndex": 7, + "endIndex": 9 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "source", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 2 + }, + "isOptional": false + }, + { + "parameterName": "options", + "parameterTypeTokenRange": { + "startIndex": 3, + "endIndex": 6 + }, + "isOptional": true + } + ], + "name": "parse" + }, + { + "kind": "Function", + "canonicalReference": "@csstools/custom-function-parser!parseFromTokens:function(1)", + "docComment": "", + "excerptTokens": [ + { + "kind": "Content", + "text": "export declare function parseFromTokens(tokens: " + }, + { + "kind": "Reference", + "text": "Array", + "canonicalReference": "!Array:interface" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "CSSToken", + "canonicalReference": "@csstools/css-tokenizer!CSSToken:type" + }, + { + "kind": "Content", + "text": ">" + }, + { + "kind": "Content", + "text": ", options?: " + }, + { + "kind": "Content", + "text": "{\n onParseError?: (error: " + }, + { + "kind": "Reference", + "text": "ParseError", + "canonicalReference": "@csstools/css-tokenizer!ParseError:class" + }, + { + "kind": "Content", + "text": ") => void;\n}" + }, + { + "kind": "Content", + "text": "): " + }, + { + "kind": "Reference", + "text": "CustomFunction", + "canonicalReference": "@csstools/custom-function-parser!CustomFunction:class" + }, + { + "kind": "Content", + "text": " | false" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "dist/_types/parser/parse.d.ts", + "returnTypeTokenRange": { + "startIndex": 10, + "endIndex": 12 + }, + "releaseTag": "Public", + "overloadIndex": 1, + "parameters": [ + { + "parameterName": "tokens", + "parameterTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + }, + "isOptional": false + }, + { + "parameterName": "options", + "parameterTypeTokenRange": { + "startIndex": 6, + "endIndex": 9 + }, + "isOptional": true + } + ], + "name": "parseFromTokens" + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction._constructor_.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction._constructor_.md new file mode 100644 index 0000000000..8ebf12afe3 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction._constructor_.md @@ -0,0 +1,122 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [(constructor)](./custom-function-parser.customfunction._constructor_.md) + +## CustomFunction.(constructor) + +Constructs a new instance of the `CustomFunction` class + +**Signature:** + +```typescript +constructor(fn: FunctionNode, parameters: Array, returnsKeyword: Array, returnType: Array, before?: Array, after?: Array); +``` + +## Parameters + + + + + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +fn + + + + +FunctionNode + + + + + +
+ +parameters + + + + +Array<[FunctionParameter](./custom-function-parser.functionparameter.md)> + + + + + +
+ +returnsKeyword + + + + +Array<CSSToken> + + + + + +
+ +returnType + + + + +Array<CSSToken> + + + + + +
+ +before + + + + +Array<CSSToken> + + + + +_(Optional)_ + + +
+ +after + + + + +Array<CSSToken> + + + + +_(Optional)_ + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.after.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.after.md new file mode 100644 index 0000000000..b4a8560637 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.after.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [after](./custom-function-parser.customfunction.after.md) + +## CustomFunction.after property + +**Signature:** + +```typescript +after: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.before.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.before.md new file mode 100644 index 0000000000..6833cca8a9 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.before.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [before](./custom-function-parser.customfunction.before.md) + +## CustomFunction.before property + +**Signature:** + +```typescript +before: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.function.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.function.md new file mode 100644 index 0000000000..0f0d92f5d4 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.function.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [function](./custom-function-parser.customfunction.function.md) + +## CustomFunction.function property + +**Signature:** + +```typescript +function: FunctionNode; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.getname.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.getname.md new file mode 100644 index 0000000000..33eac18b13 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.getname.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [getName](./custom-function-parser.customfunction.getname.md) + +## CustomFunction.getName() method + +**Signature:** + +```typescript +getName(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.getreturntype.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.getreturntype.md new file mode 100644 index 0000000000..941629802b --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.getreturntype.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [getReturnType](./custom-function-parser.customfunction.getreturntype.md) + +## CustomFunction.getReturnType() method + +**Signature:** + +```typescript +getReturnType(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.iscustomfunction.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.iscustomfunction.md new file mode 100644 index 0000000000..83c83f3adc --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.iscustomfunction.md @@ -0,0 +1,50 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [isCustomFunction](./custom-function-parser.customfunction.iscustomfunction.md) + +## CustomFunction.isCustomFunction() method + +**Signature:** + +```typescript +static isCustomFunction(x: unknown): x is CustomFunction; +``` + +## Parameters + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +x + + + + +unknown + + + + + +
+ +**Returns:** + +x is [CustomFunction](./custom-function-parser.customfunction.md) + diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.md new file mode 100644 index 0000000000..fe94f0b56a --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.md @@ -0,0 +1,272 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) + +## CustomFunction class + +**Signature:** + +```typescript +export declare class CustomFunction +``` + +## Constructors + + + +
+ +Constructor + + + + +Modifiers + + + + +Description + + +
+ +[(constructor)(fn, parameters, returnsKeyword, returnType, before, after)](./custom-function-parser.customfunction._constructor_.md) + + + + + + + +Constructs a new instance of the `CustomFunction` class + + +
+ +## Properties + + + + + + + + + +
+ +Property + + + + +Modifiers + + + + +Type + + + + +Description + + +
+ +[after](./custom-function-parser.customfunction.after.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[before](./custom-function-parser.customfunction.before.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[function](./custom-function-parser.customfunction.function.md) + + + + + + + +FunctionNode + + + + + +
+ +[parameters](./custom-function-parser.customfunction.parameters.md) + + + + + + + +Array<[FunctionParameter](./custom-function-parser.functionparameter.md)> + + + + + +
+ +[returnsKeyword](./custom-function-parser.customfunction.returnskeyword.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[returnType](./custom-function-parser.customfunction.returntype.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[type](./custom-function-parser.customfunction.type.md) + + + + + + + +[NodeType](./custom-function-parser.nodetype.md) + + + + + +
+ +## Methods + + + + + + + +
+ +Method + + + + +Modifiers + + + + +Description + + +
+ +[getName()](./custom-function-parser.customfunction.getname.md) + + + + + + + + +
+ +[getReturnType()](./custom-function-parser.customfunction.getreturntype.md) + + + + + + + + +
+ +[isCustomFunction(x)](./custom-function-parser.customfunction.iscustomfunction.md) + + + + +`static` + + + + + +
+ +[tokens()](./custom-function-parser.customfunction.tokens.md) + + + + + + + + +
+ +[toString()](./custom-function-parser.customfunction.tostring.md) + + + + + + + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.parameters.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.parameters.md new file mode 100644 index 0000000000..0514a6bd4f --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.parameters.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [parameters](./custom-function-parser.customfunction.parameters.md) + +## CustomFunction.parameters property + +**Signature:** + +```typescript +parameters: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.returnskeyword.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.returnskeyword.md new file mode 100644 index 0000000000..ca45873c36 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.returnskeyword.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [returnsKeyword](./custom-function-parser.customfunction.returnskeyword.md) + +## CustomFunction.returnsKeyword property + +**Signature:** + +```typescript +returnsKeyword: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.returntype.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.returntype.md new file mode 100644 index 0000000000..d182ee4c09 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.returntype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [returnType](./custom-function-parser.customfunction.returntype.md) + +## CustomFunction.returnType property + +**Signature:** + +```typescript +returnType: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.tokens.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.tokens.md new file mode 100644 index 0000000000..f2724c1f23 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.tokens.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [tokens](./custom-function-parser.customfunction.tokens.md) + +## CustomFunction.tokens() method + +**Signature:** + +```typescript +tokens(): Array; +``` +**Returns:** + +Array<CSSToken> + diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.tostring.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.tostring.md new file mode 100644 index 0000000000..a55569c78f --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.tostring.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [toString](./custom-function-parser.customfunction.tostring.md) + +## CustomFunction.toString() method + +**Signature:** + +```typescript +toString(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.customfunction.type.md b/packages/custom-function-parser/docs/custom-function-parser.customfunction.type.md new file mode 100644 index 0000000000..0fec80e0a6 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.customfunction.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [CustomFunction](./custom-function-parser.customfunction.md) > [type](./custom-function-parser.customfunction.type.md) + +## CustomFunction.type property + +**Signature:** + +```typescript +type: NodeType; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter._constructor_.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter._constructor_.md new file mode 100644 index 0000000000..8cf69f0606 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter._constructor_.md @@ -0,0 +1,122 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [(constructor)](./custom-function-parser.functionparameter._constructor_.md) + +## FunctionParameter.(constructor) + +Constructs a new instance of the `FunctionParameter` class + +**Signature:** + +```typescript +constructor(name: TokenIdent, argumentType: Array, colon: TokenColon | null, defaultValue: Array, before?: Array, after?: Array); +``` + +## Parameters + + + + + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +name + + + + +TokenIdent + + + + + +
+ +argumentType + + + + +Array<CSSToken> + + + + + +
+ +colon + + + + +TokenColon \| null + + + + + +
+ +defaultValue + + + + +Array<CSSToken> + + + + + +
+ +before + + + + +Array<CSSToken> + + + + +_(Optional)_ + + +
+ +after + + + + +Array<CSSToken> + + + + +_(Optional)_ + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.after.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.after.md new file mode 100644 index 0000000000..cf92b817df --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.after.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [after](./custom-function-parser.functionparameter.after.md) + +## FunctionParameter.after property + +**Signature:** + +```typescript +after: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.argumenttype.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.argumenttype.md new file mode 100644 index 0000000000..f88fae04de --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.argumenttype.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [argumentType](./custom-function-parser.functionparameter.argumenttype.md) + +## FunctionParameter.argumentType property + +**Signature:** + +```typescript +argumentType: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.before.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.before.md new file mode 100644 index 0000000000..13491a768a --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.before.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [before](./custom-function-parser.functionparameter.before.md) + +## FunctionParameter.before property + +**Signature:** + +```typescript +before: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.colon.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.colon.md new file mode 100644 index 0000000000..36490c65b4 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.colon.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [colon](./custom-function-parser.functionparameter.colon.md) + +## FunctionParameter.colon property + +**Signature:** + +```typescript +colon: TokenColon | null; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.defaultvalue.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.defaultvalue.md new file mode 100644 index 0000000000..f0c780b6e1 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.defaultvalue.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [defaultValue](./custom-function-parser.functionparameter.defaultvalue.md) + +## FunctionParameter.defaultValue property + +**Signature:** + +```typescript +defaultValue: Array; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getargumenttype.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getargumenttype.md new file mode 100644 index 0000000000..9560ffed54 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getargumenttype.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [getArgumentType](./custom-function-parser.functionparameter.getargumenttype.md) + +## FunctionParameter.getArgumentType() method + +**Signature:** + +```typescript +getArgumentType(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getdefaultvalue.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getdefaultvalue.md new file mode 100644 index 0000000000..4e44b65697 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getdefaultvalue.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [getDefaultValue](./custom-function-parser.functionparameter.getdefaultvalue.md) + +## FunctionParameter.getDefaultValue() method + +**Signature:** + +```typescript +getDefaultValue(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getname.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getname.md new file mode 100644 index 0000000000..d14560841e --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getname.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [getName](./custom-function-parser.functionparameter.getname.md) + +## FunctionParameter.getName() method + +**Signature:** + +```typescript +getName(): string; +``` +**Returns:** + +string + diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getnametoken.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getnametoken.md new file mode 100644 index 0000000000..2d5d5bb350 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.getnametoken.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [getNameToken](./custom-function-parser.functionparameter.getnametoken.md) + +## FunctionParameter.getNameToken() method + +**Signature:** + +```typescript +getNameToken(): TokenIdent | null; +``` +**Returns:** + +TokenIdent \| null + diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.isfunctionparameter.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.isfunctionparameter.md new file mode 100644 index 0000000000..745342d235 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.isfunctionparameter.md @@ -0,0 +1,50 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [isFunctionParameter](./custom-function-parser.functionparameter.isfunctionparameter.md) + +## FunctionParameter.isFunctionParameter() method + +**Signature:** + +```typescript +static isFunctionParameter(x: unknown): x is FunctionParameter; +``` + +## Parameters + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +x + + + + +unknown + + + + + +
+ +**Returns:** + +x is [FunctionParameter](./custom-function-parser.functionparameter.md) + diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.md new file mode 100644 index 0000000000..6c48fff0e9 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.md @@ -0,0 +1,272 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) + +## FunctionParameter class + +**Signature:** + +```typescript +export declare class FunctionParameter +``` + +## Constructors + + + +
+ +Constructor + + + + +Modifiers + + + + +Description + + +
+ +[(constructor)(name, argumentType, colon, defaultValue, before, after)](./custom-function-parser.functionparameter._constructor_.md) + + + + + + + +Constructs a new instance of the `FunctionParameter` class + + +
+ +## Properties + + + + + + + + + +
+ +Property + + + + +Modifiers + + + + +Type + + + + +Description + + +
+ +[after](./custom-function-parser.functionparameter.after.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[argumentType](./custom-function-parser.functionparameter.argumenttype.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[before](./custom-function-parser.functionparameter.before.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[colon](./custom-function-parser.functionparameter.colon.md) + + + + + + + +TokenColon \| null + + + + + +
+ +[defaultValue](./custom-function-parser.functionparameter.defaultvalue.md) + + + + + + + +Array<CSSToken> + + + + + +
+ +[name](./custom-function-parser.functionparameter.name.md) + + + + + + + +TokenIdent + + + + + +
+ +[type](./custom-function-parser.functionparameter.type.md) + + + + + + + +[NodeType](./custom-function-parser.nodetype.md) + + + + + +
+ +## Methods + + + + + + + +
+ +Method + + + + +Modifiers + + + + +Description + + +
+ +[getArgumentType()](./custom-function-parser.functionparameter.getargumenttype.md) + + + + + + + + +
+ +[getDefaultValue()](./custom-function-parser.functionparameter.getdefaultvalue.md) + + + + + + + + +
+ +[getName()](./custom-function-parser.functionparameter.getname.md) + + + + + + + + +
+ +[getNameToken()](./custom-function-parser.functionparameter.getnametoken.md) + + + + + + + + +
+ +[isFunctionParameter(x)](./custom-function-parser.functionparameter.isfunctionparameter.md) + + + + +`static` + + + + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.name.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.name.md new file mode 100644 index 0000000000..3140600220 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.name.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [name](./custom-function-parser.functionparameter.name.md) + +## FunctionParameter.name property + +**Signature:** + +```typescript +name: TokenIdent; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.functionparameter.type.md b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.type.md new file mode 100644 index 0000000000..2cfb3d496a --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.functionparameter.type.md @@ -0,0 +1,11 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [FunctionParameter](./custom-function-parser.functionparameter.md) > [type](./custom-function-parser.functionparameter.type.md) + +## FunctionParameter.type property + +**Signature:** + +```typescript +type: NodeType; +``` diff --git a/packages/custom-function-parser/docs/custom-function-parser.iscustomfunction.md b/packages/custom-function-parser/docs/custom-function-parser.iscustomfunction.md new file mode 100644 index 0000000000..3885c62b7a --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.iscustomfunction.md @@ -0,0 +1,50 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [isCustomFunction](./custom-function-parser.iscustomfunction.md) + +## isCustomFunction() function + +**Signature:** + +```typescript +export declare function isCustomFunction(x: unknown): x is CustomFunction; +``` + +## Parameters + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +x + + + + +unknown + + + + + +
+ +**Returns:** + +x is [CustomFunction](./custom-function-parser.customfunction.md) + diff --git a/packages/custom-function-parser/docs/custom-function-parser.isfunctionparameter.md b/packages/custom-function-parser/docs/custom-function-parser.isfunctionparameter.md new file mode 100644 index 0000000000..5e7b2beab5 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.isfunctionparameter.md @@ -0,0 +1,50 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [isFunctionParameter](./custom-function-parser.isfunctionparameter.md) + +## isFunctionParameter() function + +**Signature:** + +```typescript +export declare function isFunctionParameter(x: unknown): x is FunctionParameter; +``` + +## Parameters + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +x + + + + +unknown + + + + + +
+ +**Returns:** + +x is [FunctionParameter](./custom-function-parser.functionparameter.md) + diff --git a/packages/custom-function-parser/docs/custom-function-parser.md b/packages/custom-function-parser/docs/custom-function-parser.md new file mode 100644 index 0000000000..1219811293 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.md @@ -0,0 +1,114 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) + +## custom-function-parser package + +## Classes + + + + +
+ +Class + + + + +Description + + +
+ +[CustomFunction](./custom-function-parser.customfunction.md) + + + + + +
+ +[FunctionParameter](./custom-function-parser.functionparameter.md) + + + + + +
+ +## Enumerations + + + +
+ +Enumeration + + + + +Description + + +
+ +[NodeType](./custom-function-parser.nodetype.md) + + + + + +
+ +## Functions + + + + + + +
+ +Function + + + + +Description + + +
+ +[isCustomFunction(x)](./custom-function-parser.iscustomfunction.md) + + + + + +
+ +[isFunctionParameter(x)](./custom-function-parser.isfunctionparameter.md) + + + + + +
+ +[parse(source, options)](./custom-function-parser.parse.md) + + + + + +
+ +[parseFromTokens(tokens, options)](./custom-function-parser.parsefromtokens.md) + + + + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.nodetype.md b/packages/custom-function-parser/docs/custom-function-parser.nodetype.md new file mode 100644 index 0000000000..e6ada40558 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.nodetype.md @@ -0,0 +1,60 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [NodeType](./custom-function-parser.nodetype.md) + +## NodeType enum + +**Signature:** + +```typescript +export declare enum NodeType +``` + +## Enumeration Members + + + + +
+ +Member + + + + +Value + + + + +Description + + +
+ +CustomFunction + + + + +`"custom-function"` + + + + + +
+ +FunctionParameter + + + + +`"function-parameter"` + + + + + +
+ diff --git a/packages/custom-function-parser/docs/custom-function-parser.parse.md b/packages/custom-function-parser/docs/custom-function-parser.parse.md new file mode 100644 index 0000000000..9fa52388a0 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.parse.md @@ -0,0 +1,68 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [parse](./custom-function-parser.parse.md) + +## parse() function + +**Signature:** + +```typescript +export declare function parse(source: string, options?: { + onParseError?: (error: ParseError) => void; +}): CustomFunction | false; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +source + + + + +string + + + + + +
+ +options + + + + +{ onParseError?: (error: ParseError) => void; } + + + + +_(Optional)_ + + +
+ +**Returns:** + +[CustomFunction](./custom-function-parser.customfunction.md) \| false + diff --git a/packages/custom-function-parser/docs/custom-function-parser.parsefromtokens.md b/packages/custom-function-parser/docs/custom-function-parser.parsefromtokens.md new file mode 100644 index 0000000000..f51e42ef37 --- /dev/null +++ b/packages/custom-function-parser/docs/custom-function-parser.parsefromtokens.md @@ -0,0 +1,68 @@ + + +[Home](./index.md) > [@csstools/custom-function-parser](./custom-function-parser.md) > [parseFromTokens](./custom-function-parser.parsefromtokens.md) + +## parseFromTokens() function + +**Signature:** + +```typescript +export declare function parseFromTokens(tokens: Array, options?: { + onParseError?: (error: ParseError) => void; +}): CustomFunction | false; +``` + +## Parameters + + + + +
+ +Parameter + + + + +Type + + + + +Description + + +
+ +tokens + + + + +Array<CSSToken> + + + + + +
+ +options + + + + +{ onParseError?: (error: ParseError) => void; } + + + + +_(Optional)_ + + +
+ +**Returns:** + +[CustomFunction](./custom-function-parser.customfunction.md) \| false + diff --git a/packages/custom-function-parser/docs/index.md b/packages/custom-function-parser/docs/index.md new file mode 100644 index 0000000000..28cbb9d646 --- /dev/null +++ b/packages/custom-function-parser/docs/index.md @@ -0,0 +1,30 @@ + + +[Home](./index.md) + +## API Reference + +## Packages + + + +
+ +Package + + + + +Description + + +
+ +[@csstools/custom-function-parser](./custom-function-parser.md) + + + + + +
+ diff --git a/packages/custom-function-parser/package.json b/packages/custom-function-parser/package.json new file mode 100644 index 0000000000..36aa089773 --- /dev/null +++ b/packages/custom-function-parser/package.json @@ -0,0 +1,71 @@ +{ + "name": "@csstools/custom-function-parser", + "description": "Parse CSS custom function params.", + "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", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "engines": { + "node": ">=20.19.0" + }, + "type": "module", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.mjs" + } + }, + "files": [ + "CHANGELOG.md", + "LICENSE.md", + "README.md", + "dist" + ], + "peerDependencies": { + "@csstools/css-parser-algorithms": "^4.0.1", + "@csstools/css-tokenizer": "^4.0.2" + }, + "scripts": { + "build": "rollup -c ../../rollup/default.mjs", + "docs": "node ../../.github/bin/generate-docs/api-documenter.mjs", + "lint": "node ../../.github/bin/format-package-json.mjs", + "prepublishOnly": "npm run build && npm run test", + "stryker": "stryker run --logLevel error", + "test": "node --test ./test/test.mjs ./test/_import.mjs ./test/_require.cjs", + "test:rewrite-expects": "REWRITE_EXPECTS=true node --test ./test/test.mjs" + }, + "homepage": "https://github.com/csstools/postcss-plugins/tree/main/packages/custom-function-parser#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/csstools/postcss-plugins.git", + "directory": "packages/custom-function-parser" + }, + "bugs": "https://github.com/csstools/postcss-plugins/issues", + "keywords": [ + "css", + "custom functions", + "parser" + ], + "volta": { + "extends": "../../package.json" + } +} diff --git a/packages/custom-function-parser/src/index.ts b/packages/custom-function-parser/src/index.ts new file mode 100644 index 0000000000..03072e2eab --- /dev/null +++ b/packages/custom-function-parser/src/index.ts @@ -0,0 +1,11 @@ +export { parse, parseFromTokens } from './parser/parse'; + +export { NodeType } from './util/node-type'; + +export { + isCustomFunction, + isFunctionParameter, +} from './util/type-predicates'; + +export { CustomFunction } from './nodes/custom-function'; +export { FunctionParameter } from './nodes/function-parameter'; diff --git a/packages/custom-function-parser/src/nodes/custom-function.ts b/packages/custom-function-parser/src/nodes/custom-function.ts new file mode 100644 index 0000000000..cf086c1ab0 --- /dev/null +++ b/packages/custom-function-parser/src/nodes/custom-function.ts @@ -0,0 +1,96 @@ +import type { CSSToken } from '@csstools/css-tokenizer'; +import { isTokenComment, stringify } from '@csstools/css-tokenizer'; +import { NodeType } from '../util/node-type'; +import type { FunctionParameter } from './function-parameter'; +import { isFunctionNode, isWhiteSpaceOrCommentNode, parseListOfComponentValues, type FunctionNode } from '@csstools/css-parser-algorithms'; + +export class CustomFunction { + type = NodeType.CustomFunction; + + function: FunctionNode; + parameters: Array; + returnsKeyword: Array; + returnType: Array; + before: Array; + after: Array; + + constructor(fn: FunctionNode, parameters: Array, returnsKeyword: Array, returnType: Array, before: Array = [], after: Array = []) { + this.function = fn; + this.parameters = parameters; + this.returnsKeyword = returnsKeyword; + this.returnType = returnType; + this.before = before; + this.after = after; + } + + getName(): string { + return this.function.getName(); + } + + getReturnType(): string { + const meaningfulComponentValues = parseListOfComponentValues(this.returnType).filter((x) => !isWhiteSpaceOrCommentNode(x)); + if ( + meaningfulComponentValues.length === 1 && + isFunctionNode(meaningfulComponentValues[0]) && + meaningfulComponentValues[0].getName().toLowerCase() === 'type' + ) { + return stringify( + ...meaningfulComponentValues[0].value + .flatMap((x) => x.tokens()) + .filter((x) => !isTokenComment(x)) + ).trim(); + } + + return stringify(...this.returnType.filter((x) => !isTokenComment(x))).trim(); + } + + tokens(): Array { + return [ + ...this.before, + ...this.function.tokens(), + ...this.returnsKeyword, + ...this.returnType, + ...this.after, + ]; + } + + toString(): string { + return stringify(...this.before) + stringify(...this.function.tokens()) + stringify(...this.returnsKeyword) + stringify(...this.returnType) + stringify(...this.after); + } + + /** + * @internal + */ + toJSON(): Record { + return { + type: this.type, + name: this.getName(), + string: this.toString(), + tokens: this.tokens(), + parameters: this.parameters.map((x) => x.toJSON()), + returnsKeyword: this.returnsKeyword, + returnType: this.returnType, + before: this.before, + after: this.after, + }; + } + + /** + * @internal + */ + isCustomFunction(): this is CustomFunction { + return CustomFunction.isCustomFunction(this); + } + + static isCustomFunction(x: unknown): x is CustomFunction { + if (!x) { + return false; + } + + if (!(x instanceof CustomFunction)) { + return false; + } + + return x.type === NodeType.CustomFunction; + } +} diff --git a/packages/custom-function-parser/src/nodes/function-parameter.ts b/packages/custom-function-parser/src/nodes/function-parameter.ts new file mode 100644 index 0000000000..8d97781797 --- /dev/null +++ b/packages/custom-function-parser/src/nodes/function-parameter.ts @@ -0,0 +1,73 @@ +import type { CSSToken, TokenColon, TokenIdent} from '@csstools/css-tokenizer'; +import { isTokenComment, stringify } from '@csstools/css-tokenizer'; +import { NodeType } from '../util/node-type'; + +export class FunctionParameter { + type = NodeType.FunctionParameter; + + name: TokenIdent; + argumentType: Array; + colon: TokenColon | null; + defaultValue: Array; + before: Array; + after: Array; + + constructor(name: TokenIdent, argumentType: Array, colon: TokenColon | null, defaultValue: Array, before: Array = [], after: Array = []) { + this.name = name; + this.argumentType = argumentType; + this.colon = colon; + this.defaultValue = defaultValue; + this.before = before; + this.after = after; + } + + getName(): string { + return this.name[4].value; + } + + getNameToken(): TokenIdent | null { + return this.name; + } + + getArgumentType(): string { + return stringify(...this.argumentType.filter((x) => !isTokenComment(x))).trim(); + } + + getDefaultValue(): string { + return stringify(...this.defaultValue).trim(); + } + + /** + * @internal + */ + toJSON(): Record { + return { + type: this.type, + name: this.getName(), + argumentType: this.argumentType, + colon: this.colon, + defaultValue: this.defaultValue, + before: this.before, + after: this.after, + }; + } + + /** + * @internal + */ + isFunctionParameter(): this is FunctionParameter { + return FunctionParameter.isFunctionParameter(this); + } + + static isFunctionParameter(x: unknown): x is FunctionParameter { + if (!x) { + return false; + } + + if (!(x instanceof FunctionParameter)) { + return false; + } + + return x.type === NodeType.FunctionParameter; + } +} diff --git a/packages/custom-function-parser/src/parser/parse-custom-function.ts b/packages/custom-function-parser/src/parser/parse-custom-function.ts new file mode 100644 index 0000000000..79419cb47a --- /dev/null +++ b/packages/custom-function-parser/src/parser/parse-custom-function.ts @@ -0,0 +1,324 @@ +import { isFunctionNode, isSimpleBlockNode, isTokenNode, isWhitespaceNode, isWhiteSpaceOrCommentNode } from '@csstools/css-parser-algorithms'; +import type { ComponentValue, FunctionNode } from '@csstools/css-parser-algorithms'; +import type { CSSToken, TokenColon, TokenIdent } from '@csstools/css-tokenizer'; +import { isTokenColon, isTokenComma, isTokenDelim, isTokenIdent, isTokenOpenCurly } from '@csstools/css-tokenizer'; +import { CustomFunction } from '../nodes/custom-function'; +import { FunctionParameter } from '../nodes/function-parameter'; + +export function parseCustomFunction(componentValues: Array): CustomFunction | false { + let fnNode: FunctionNode | null = null; + let fnIndex = -1; + let returnsKeywordIndex = -1; + let returnTypeIndex = -1; + let afterIndex = componentValues.length; + + for (let i = 0; i < componentValues.length; i++) { + const componentValue = componentValues[i]; + if (isWhiteSpaceOrCommentNode(componentValue)) { + continue; + } + + if (fnIndex === -1 && isFunctionNode(componentValue)) { + if (!componentValue.getName().startsWith('--')) { + return false; + } + + fnIndex = i; + fnNode = componentValue; + continue; + } + + if (fnIndex !== -1 && returnsKeywordIndex === -1 && isTokenNode(componentValue)) { + const token = componentValue.value; + if (!isTokenIdent(token)) { + return false; + } + + if (token[4].value.toLowerCase() !== 'returns') { + return false; + } + + returnsKeywordIndex = i; + continue; + } + + if (returnsKeywordIndex !== -1) { + returnTypeIndex = i; + break; + } + + return false; + } + + if (returnsKeywordIndex !== -1 && returnTypeIndex === -1) { + return false; + } + + if (!fnNode) { + return false; + } + + for (let i = (componentValues.length - 1); i > returnTypeIndex; i--) { + const componentValue = componentValues[i]; + if (isWhiteSpaceOrCommentNode(componentValue)) { + afterIndex = i; + continue; + } + + break; + } + + const parameters = parseFunctionParameters(fnNode.value); + if (!parameters) { + return false; + } + + return new CustomFunction( + fnNode, + parameters, + returnTypeIndex === -1 ? [] : componentValues.slice(fnIndex + 1, returnTypeIndex).flatMap((x) => { + return x.tokens(); + }), + returnTypeIndex === -1 ? [] : componentValues.slice(returnTypeIndex, afterIndex).flatMap((x) => { + return x.tokens(); + }), + componentValues.slice(0, fnIndex).flatMap((x) => { + return x.tokens(); + }), + componentValues.slice(afterIndex).flatMap((x) => { + return x.tokens(); + }) + ); +} + +function parseFunctionParameters(componentValues: Array): Array | false { + if (!componentValues.some(x => !isWhiteSpaceOrCommentNode(x))) { + return []; + } + + const parameters: Array = []; + const seenNames = new Set(); + + for (let i = 0; i < componentValues.length; i++) { + const result = parseFunctionParameter( + componentValues.slice(i) + ); + + if (!result) { + return false; + } + + const name = result.node.getName(); + if (seenNames.has(name)) { + // The same custom property name may not appear more than once. + return false; + } + + seenNames.add(name); + + i += result.advance; + parameters.push(result.node); + continue; + } + + return parameters; +} + +function parseFunctionParameter(componentValues: Array): { advance: number, node: FunctionParameter } | false { + let syntaxComponentDepth = 0; + + let nameIndex = -1; + let nameToken: TokenIdent | null = null; + + let colonIndex = -1; + let colonToken: TokenColon | null = null; + + let defaultValueIndex = -1; + + let afterIndex = componentValues.length; + + let i = 0; + for (; i < componentValues.length; i++) { + const componentValue = componentValues[i]; + if (isWhiteSpaceOrCommentNode(componentValue)) { + continue; + } + + if ( + syntaxComponentDepth === 0 && + isTokenNode(componentValue) && + isTokenComma(componentValue.value) + ) { + afterIndex = i; + break; + } + + if (nameIndex === -1) { + if ( + isTokenNode(componentValue) && + isTokenIdent(componentValue.value) && + componentValue.value[4].value.startsWith('--') + ) { + nameIndex = i; + nameToken = componentValue.value; + continue; + } + + return false; + } + + if ( + colonIndex === -1 && + isTokenNode(componentValue) && + isTokenDelim(componentValue.value) && + componentValue.value[4].value === '<' + ) { + syntaxComponentDepth++; + continue; + } + + if ( + colonIndex === -1 && + syntaxComponentDepth > 0 && + isTokenNode(componentValue) && + isTokenDelim(componentValue.value) && + componentValue.value[4].value === '>' + ) { + syntaxComponentDepth--; + continue; + } + + if ( + colonIndex === -1 && + syntaxComponentDepth === 0 && + isTokenNode(componentValue) && + isTokenColon(componentValue.value) + ) { + colonIndex = i; + colonToken = componentValue.value; + continue; + } + + if (colonIndex !== -1) { + defaultValueIndex = i; + continue; + } + + if (colonIndex === -1) { + continue; + } + + return false; + } + + if (!nameToken) { + return false; + } + + if (colonIndex !== -1 && defaultValueIndex === -1) { + return false; + } + + const typeEndIndex = colonIndex !== -1 ? (colonIndex - 1) : (i - 1); + + for (let j = (componentValues.length - 1); j > Math.max(typeEndIndex, defaultValueIndex); j--) { + const componentValue = componentValues[j]; + if (isWhitespaceNode(componentValue)) { + afterIndex = j; + continue; + } + + break; + } + + let argumentType: Array; + { + const argumentTypeComponentValues = componentValues.slice(nameIndex + 1, typeEndIndex + 1); + const meaningfulComponentValues = argumentTypeComponentValues.filter((x) => !isWhiteSpaceOrCommentNode(x)); + if ( + meaningfulComponentValues.length === 1 && + isFunctionNode(meaningfulComponentValues[0]) && + meaningfulComponentValues[0].getName().toLowerCase() === 'type' + ) { + argumentType = meaningfulComponentValues[0].value.flatMap((x) => { + return x.tokens(); + }); + } else { + argumentType = argumentTypeComponentValues.flatMap((x) => { + return x.tokens(); + }); + } + } + + let defaultValue: Array = []; + if (defaultValueIndex !== -1) { + const defaultValueComponentValues = componentValues.slice(colonIndex + 1, afterIndex); + if (hasTopLevelImportant(defaultValueComponentValues)) { + // `!important` is not part of a . + return false; + } + + const meaningfulComponentValues = defaultValueComponentValues.filter((x) => !isWhiteSpaceOrCommentNode(x)); + if ( + meaningfulComponentValues.length === 1 && + isSimpleBlockNode(meaningfulComponentValues[0]) && + isTokenOpenCurly(meaningfulComponentValues[0].startToken) + ) { + defaultValue = meaningfulComponentValues[0].value.flatMap((x) => { + return x.tokens(); + }); + } else { + defaultValue = defaultValueComponentValues.flatMap((x) => { + return x.tokens(); + }); + } + } + + return { + advance: i, + node: new FunctionParameter( + nameToken, + argumentType, + colonToken, + defaultValue, + componentValues.slice(0, nameIndex).flatMap((x) => { + return x.tokens(); + }), + componentValues.slice(afterIndex, i + 1).flatMap((x) => { + return x.tokens(); + }) + ) + }; +} + +function hasTopLevelImportant(componentValues: Array): boolean { + for (let i = 0; i < componentValues.length; i++) { + const componentValue = componentValues[i]; + if ( + !isTokenNode(componentValue) || + !isTokenDelim(componentValue.value) || + componentValue.value[4].value !== '!' + ) { + continue; + } + + for (let j = i + 1; j < componentValues.length; j++) { + const next = componentValues[j]; + if (isWhiteSpaceOrCommentNode(next)) { + continue; + } + + if ( + isTokenNode(next) && + isTokenIdent(next.value) && + next.value[4].value.toLowerCase() === 'important' + ) { + return true; + } + + break; + } + } + + return false; +} diff --git a/packages/custom-function-parser/src/parser/parse.ts b/packages/custom-function-parser/src/parser/parse.ts new file mode 100644 index 0000000000..d3c11fda29 --- /dev/null +++ b/packages/custom-function-parser/src/parser/parse.ts @@ -0,0 +1,38 @@ +import { parseListOfComponentValues } from '@csstools/css-parser-algorithms'; +import type { CSSToken, ParseError } from '@csstools/css-tokenizer'; +import { tokenize } from '@csstools/css-tokenizer'; +import { parseCustomFunction } from './parse-custom-function'; +import type { CustomFunction } from '../nodes/custom-function'; + +export function parseFromTokens( + tokens: Array, + options?: { + onParseError?: (error: ParseError) => void + }, +): CustomFunction | false { + let errored = false; + + const componentValues = parseListOfComponentValues(tokens, { + onParseError: (error) => { + errored = true; + options?.onParseError?.(error); + }, + }); + + if (errored) { + return false; + } + + return parseCustomFunction(componentValues); +} + +export function parse( + source: string, + options?: { + onParseError?: (error: ParseError) => void + }, +): CustomFunction | false { + return parseFromTokens(tokenize({ css: source }, { + onParseError: options?.onParseError, + }), options); +} diff --git a/packages/custom-function-parser/src/util/node-type.ts b/packages/custom-function-parser/src/util/node-type.ts new file mode 100644 index 0000000000..c835af765d --- /dev/null +++ b/packages/custom-function-parser/src/util/node-type.ts @@ -0,0 +1,4 @@ +export enum NodeType { + CustomFunction = 'custom-function', + FunctionParameter = 'function-parameter', +} diff --git a/packages/custom-function-parser/src/util/type-predicates.ts b/packages/custom-function-parser/src/util/type-predicates.ts new file mode 100644 index 0000000000..d6bb8663e7 --- /dev/null +++ b/packages/custom-function-parser/src/util/type-predicates.ts @@ -0,0 +1,10 @@ +import { CustomFunction } from '../nodes/custom-function'; +import { FunctionParameter } from '../nodes/function-parameter'; + +export function isCustomFunction(x: unknown): x is CustomFunction { + return CustomFunction.isCustomFunction(x); +} + +export function isFunctionParameter(x: unknown): x is FunctionParameter { + return FunctionParameter.isFunctionParameter(x); +} diff --git a/packages/custom-function-parser/stryker.conf.json b/packages/custom-function-parser/stryker.conf.json new file mode 100644 index 0000000000..0951af7f6c --- /dev/null +++ b/packages/custom-function-parser/stryker.conf.json @@ -0,0 +1,19 @@ +{ + "$schema": "../../node_modules/@stryker-mutator/core/schema/stryker-schema.json", + "mutate": [ + "src/**/*.ts" + ], + "buildCommand": "rollup -c ../../rollup/default.mjs", + "testRunner": "command", + "coverageAnalysis": "perTest", + "tempDirName": "../../.stryker-tmp", + "commandRunner": { + "command": "node ./test/test.mjs" + }, + "thresholds": { + "high": 100, + "low": 100, + "break": 100 + }, + "inPlace": true +} diff --git a/packages/custom-function-parser/test/_import.mjs b/packages/custom-function-parser/test/_import.mjs new file mode 100644 index 0000000000..643f950dfe --- /dev/null +++ b/packages/custom-function-parser/test/_import.mjs @@ -0,0 +1,3 @@ +import { parse } from '@csstools/custom-function-parser'; + +parse('--foo(--bar)'); diff --git a/packages/custom-function-parser/test/_require.cjs b/packages/custom-function-parser/test/_require.cjs new file mode 100644 index 0000000000..43b8ffa196 --- /dev/null +++ b/packages/custom-function-parser/test/_require.cjs @@ -0,0 +1,3 @@ +const { parse } = require('@csstools/custom-function-parser'); + +parse('--foo(--bar)'); diff --git a/packages/custom-function-parser/test/cases/custom-function/0001.expect.json b/packages/custom-function-parser/test/cases/custom-function/0001.expect.json new file mode 100644 index 0000000000..b395b0a334 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0001.expect.json @@ -0,0 +1,28 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo()", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + ")-token", + ")", + 6, + 6, + null + ] + ], + "parameters": [], + "returnsKeyword": [], + "returnType": [], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0001.mjs b/packages/custom-function-parser/test/cases/custom-function/0001.mjs new file mode 100644 index 0000000000..60136a0323 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0001.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo()', + 'custom-function/0001', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0002.expect.json b/packages/custom-function-parser/test/cases/custom-function/0002.expect.json new file mode 100644 index 0000000000..41e50ba567 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0002.expect.json @@ -0,0 +1,65 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": " --foo( ) ", + "tokens": [ + [ + "whitespace-token", + " ", + 0, + 0, + null + ], + [ + "function-token", + "--foo(", + 1, + 6, + { + "value": "--foo" + } + ], + [ + "whitespace-token", + " ", + 7, + 7, + null + ], + [ + ")-token", + ")", + 8, + 8, + null + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ] + ], + "parameters": [], + "returnsKeyword": [], + "returnType": [], + "before": [ + [ + "whitespace-token", + " ", + 0, + 0, + null + ] + ], + "after": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ] + ] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0002.mjs b/packages/custom-function-parser/test/cases/custom-function/0002.mjs new file mode 100644 index 0000000000..e6b1b6ed5d --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0002.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + ' --foo( ) ', + 'custom-function/0002', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0003.expect.json b/packages/custom-function-parser/test/cases/custom-function/0003.expect.json new file mode 100644 index 0000000000..dbd1fd8e39 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0003.expect.json @@ -0,0 +1,65 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "/* a comment */--foo( )/* a comment */", + "tokens": [ + [ + "comment", + "/* a comment */", + 0, + 14, + null + ], + [ + "function-token", + "--foo(", + 15, + 20, + { + "value": "--foo" + } + ], + [ + "whitespace-token", + " ", + 21, + 21, + null + ], + [ + ")-token", + ")", + 22, + 22, + null + ], + [ + "comment", + "/* a comment */", + 23, + 37, + null + ] + ], + "parameters": [], + "returnsKeyword": [], + "returnType": [], + "before": [ + [ + "comment", + "/* a comment */", + 0, + 14, + null + ] + ], + "after": [ + [ + "comment", + "/* a comment */", + 23, + 37, + null + ] + ] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0003.mjs b/packages/custom-function-parser/test/cases/custom-function/0003.mjs new file mode 100644 index 0000000000..0ce45d1f96 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0003.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '/* a comment */--foo( )/* a comment */', + 'custom-function/0003', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0004.expect.json b/packages/custom-function-parser/test/cases/custom-function/0004.expect.json new file mode 100644 index 0000000000..f23fcadcc3 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0004.expect.json @@ -0,0 +1,232 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo(--x ) returns ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + "ident-token", + "--x", + 6, + 8, + { + "value": "--x" + } + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "whitespace-token", + " ", + 17, + 17, + null + ], + [ + ")-token", + ")", + 18, + 18, + null + ], + [ + "whitespace-token", + " ", + 19, + 19, + null + ], + [ + "ident-token", + "returns", + 20, + 26, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 27, + 27, + null + ], + [ + "delim-token", + "<", + 28, + 28, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 29, + 34, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 35, + 35, + { + "value": ">" + } + ] + ], + "parameters": [ + { + "type": "function-parameter", + "name": "--x", + "argumentType": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "whitespace-token", + " ", + 17, + 17, + null + ] + ], + "colon": null, + "defaultValue": [], + "before": [], + "after": [] + } + ], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 19, + 19, + null + ], + [ + "ident-token", + "returns", + 20, + 26, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 27, + 27, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 28, + 28, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 29, + 34, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 35, + 35, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0004.mjs b/packages/custom-function-parser/test/cases/custom-function/0004.mjs new file mode 100644 index 0000000000..29cc1ab991 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0004.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo(--x ) returns ', + 'custom-function/0004', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0005.expect.json b/packages/custom-function-parser/test/cases/custom-function/0005.expect.json new file mode 100644 index 0000000000..02e4a84d62 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0005.expect.json @@ -0,0 +1 @@ +false \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0005.mjs b/packages/custom-function-parser/test/cases/custom-function/0005.mjs new file mode 100644 index 0000000000..99272aa0a2 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0005.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo() returns', + 'custom-function/0005', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0006.expect.json b/packages/custom-function-parser/test/cases/custom-function/0006.expect.json new file mode 100644 index 0000000000..02e4a84d62 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0006.expect.json @@ -0,0 +1 @@ +false \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0006.mjs b/packages/custom-function-parser/test/cases/custom-function/0006.mjs new file mode 100644 index 0000000000..62c3390757 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0006.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo() ', + 'custom-function/0006', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0007.expect.json b/packages/custom-function-parser/test/cases/custom-function/0007.expect.json new file mode 100644 index 0000000000..02e4a84d62 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0007.expect.json @@ -0,0 +1 @@ +false \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0007.mjs b/packages/custom-function-parser/test/cases/custom-function/0007.mjs new file mode 100644 index 0000000000..d4b5c7a3d7 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0007.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + 'returns --foo()', + 'custom-function/0007', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0008.expect.json b/packages/custom-function-parser/test/cases/custom-function/0008.expect.json new file mode 100644 index 0000000000..fcb2394f19 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0008.expect.json @@ -0,0 +1,229 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo() /* a comment */ returns /* a comment */ /* a comment */ ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + ")-token", + ")", + 6, + 6, + null + ], + [ + "whitespace-token", + " ", + 7, + 7, + null + ], + [ + "comment", + "/* a comment */", + 8, + 22, + null + ], + [ + "whitespace-token", + " ", + 23, + 23, + null + ], + [ + "ident-token", + "returns", + 24, + 30, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 31, + 31, + null + ], + [ + "comment", + "/* a comment */", + 32, + 46, + null + ], + [ + "whitespace-token", + " ", + 47, + 47, + null + ], + [ + "delim-token", + "<", + 48, + 48, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 49, + 54, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 55, + 55, + { + "value": ">" + } + ], + [ + "whitespace-token", + " ", + 56, + 56, + null + ], + [ + "comment", + "/* a comment */", + 57, + 71, + null + ], + [ + "whitespace-token", + " ", + 72, + 72, + null + ] + ], + "parameters": [], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 7, + 7, + null + ], + [ + "comment", + "/* a comment */", + 8, + 22, + null + ], + [ + "whitespace-token", + " ", + 23, + 23, + null + ], + [ + "ident-token", + "returns", + 24, + 30, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 31, + 31, + null + ], + [ + "comment", + "/* a comment */", + 32, + 46, + null + ], + [ + "whitespace-token", + " ", + 47, + 47, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 48, + 48, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 49, + 54, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 55, + 55, + { + "value": ">" + } + ] + ], + "before": [], + "after": [ + [ + "whitespace-token", + " ", + 56, + 56, + null + ], + [ + "comment", + "/* a comment */", + 57, + 71, + null + ], + [ + "whitespace-token", + " ", + 72, + 72, + null + ] + ] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0008.mjs b/packages/custom-function-parser/test/cases/custom-function/0008.mjs new file mode 100644 index 0000000000..26b9b6e243 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0008.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo() /* a comment */ returns /* a comment */ /* a comment */ ', + 'custom-function/0008', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0009.expect.json b/packages/custom-function-parser/test/cases/custom-function/0009.expect.json new file mode 100644 index 0000000000..02e4a84d62 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0009.expect.json @@ -0,0 +1 @@ +false \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0009.mjs b/packages/custom-function-parser/test/cases/custom-function/0009.mjs new file mode 100644 index 0000000000..b313901435 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0009.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo() --bar()', + 'custom-function/0009', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0010.expect.json b/packages/custom-function-parser/test/cases/custom-function/0010.expect.json new file mode 100644 index 0000000000..5084801020 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0010.expect.json @@ -0,0 +1,144 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo() returns <--bar()>", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + ")-token", + ")", + 6, + 6, + null + ], + [ + "whitespace-token", + " ", + 7, + 7, + null + ], + [ + "ident-token", + "returns", + 8, + 14, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 15, + 15, + null + ], + [ + "delim-token", + "<", + 16, + 16, + { + "value": "<" + } + ], + [ + "function-token", + "--bar(", + 17, + 22, + { + "value": "--bar" + } + ], + [ + ")-token", + ")", + 23, + 23, + null + ], + [ + "delim-token", + ">", + 24, + 24, + { + "value": ">" + } + ] + ], + "parameters": [], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 7, + 7, + null + ], + [ + "ident-token", + "returns", + 8, + 14, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 15, + 15, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 16, + 16, + { + "value": "<" + } + ], + [ + "function-token", + "--bar(", + 17, + 22, + { + "value": "--bar" + } + ], + [ + ")-token", + ")", + 23, + 23, + null + ], + [ + "delim-token", + ">", + 24, + 24, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0010.mjs b/packages/custom-function-parser/test/cases/custom-function/0010.mjs new file mode 100644 index 0000000000..2c8714a7a7 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0010.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo() returns <--bar()>', + 'custom-function/0010', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0011.expect.json b/packages/custom-function-parser/test/cases/custom-function/0011.expect.json new file mode 100644 index 0000000000..371322e160 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0011.expect.json @@ -0,0 +1,279 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo(--x : red ) returns ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + "ident-token", + "--x", + 6, + 8, + { + "value": "--x" + } + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "colon-token", + ":", + 17, + 17, + null + ], + [ + "whitespace-token", + " ", + 18, + 18, + null + ], + [ + "ident-token", + "red", + 19, + 21, + { + "value": "red" + } + ], + [ + "whitespace-token", + " ", + 22, + 22, + null + ], + [ + ")-token", + ")", + 23, + 23, + null + ], + [ + "whitespace-token", + " ", + 24, + 24, + null + ], + [ + "ident-token", + "returns", + 25, + 31, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 32, + 32, + null + ], + [ + "delim-token", + "<", + 33, + 33, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 34, + 39, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 40, + 40, + { + "value": ">" + } + ] + ], + "parameters": [ + { + "type": "function-parameter", + "name": "--x", + "argumentType": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ] + ], + "colon": [ + "colon-token", + ":", + 17, + 17, + null + ], + "defaultValue": [ + [ + "whitespace-token", + " ", + 18, + 18, + null + ], + [ + "ident-token", + "red", + 19, + 21, + { + "value": "red" + } + ] + ], + "before": [], + "after": [ + [ + "whitespace-token", + " ", + 22, + 22, + null + ] + ] + } + ], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 24, + 24, + null + ], + [ + "ident-token", + "returns", + 25, + 31, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 32, + 32, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 33, + 33, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 34, + 39, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 40, + 40, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0011.mjs b/packages/custom-function-parser/test/cases/custom-function/0011.mjs new file mode 100644 index 0000000000..2c67a7e9da --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0011.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo(--x : red ) returns ', + 'custom-function/0011', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0012.expect.json b/packages/custom-function-parser/test/cases/custom-function/0012.expect.json new file mode 100644 index 0000000000..429e7f146f --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0012.expect.json @@ -0,0 +1,293 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo(--x : red ) returns ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + "ident-token", + "--x", + 6, + 8, + { + "value": "--x" + } + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "whitespace-token", + " ", + 17, + 17, + null + ], + [ + "colon-token", + ":", + 18, + 18, + null + ], + [ + "whitespace-token", + " ", + 19, + 19, + null + ], + [ + "ident-token", + "red", + 20, + 22, + { + "value": "red" + } + ], + [ + "whitespace-token", + " ", + 23, + 23, + null + ], + [ + ")-token", + ")", + 24, + 24, + null + ], + [ + "whitespace-token", + " ", + 25, + 25, + null + ], + [ + "ident-token", + "returns", + 26, + 32, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 33, + 33, + null + ], + [ + "delim-token", + "<", + 34, + 34, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 35, + 40, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 41, + 41, + { + "value": ">" + } + ] + ], + "parameters": [ + { + "type": "function-parameter", + "name": "--x", + "argumentType": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "whitespace-token", + " ", + 17, + 17, + null + ] + ], + "colon": [ + "colon-token", + ":", + 18, + 18, + null + ], + "defaultValue": [ + [ + "whitespace-token", + " ", + 19, + 19, + null + ], + [ + "ident-token", + "red", + 20, + 22, + { + "value": "red" + } + ] + ], + "before": [], + "after": [ + [ + "whitespace-token", + " ", + 23, + 23, + null + ] + ] + } + ], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 25, + 25, + null + ], + [ + "ident-token", + "returns", + 26, + 32, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 33, + 33, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 34, + 34, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 35, + 40, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 41, + 41, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0012.mjs b/packages/custom-function-parser/test/cases/custom-function/0012.mjs new file mode 100644 index 0000000000..d4ec11efcc --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0012.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo(--x : red ) returns ', + 'custom-function/0012', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0013.expect.json b/packages/custom-function-parser/test/cases/custom-function/0013.expect.json new file mode 100644 index 0000000000..c33cd72351 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0013.expect.json @@ -0,0 +1,250 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo(--x :red) returns ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + "ident-token", + "--x", + 6, + 8, + { + "value": "--x" + } + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "colon-token", + ":", + 17, + 17, + null + ], + [ + "ident-token", + "red", + 18, + 20, + { + "value": "red" + } + ], + [ + ")-token", + ")", + 21, + 21, + null + ], + [ + "whitespace-token", + " ", + 22, + 22, + null + ], + [ + "ident-token", + "returns", + 23, + 29, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 30, + 30, + null + ], + [ + "delim-token", + "<", + 31, + 31, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 32, + 37, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 38, + 38, + { + "value": ">" + } + ] + ], + "parameters": [ + { + "type": "function-parameter", + "name": "--x", + "argumentType": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ] + ], + "colon": [ + "colon-token", + ":", + 17, + 17, + null + ], + "defaultValue": [ + [ + "ident-token", + "red", + 18, + 20, + { + "value": "red" + } + ] + ], + "before": [], + "after": [] + } + ], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 22, + 22, + null + ], + [ + "ident-token", + "returns", + 23, + 29, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 30, + 30, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 31, + 31, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 32, + 37, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 38, + 38, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0013.mjs b/packages/custom-function-parser/test/cases/custom-function/0013.mjs new file mode 100644 index 0000000000..bc97c32ff9 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0013.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo(--x :red) returns ', + 'custom-function/0013', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/cases/custom-function/0014.expect.json b/packages/custom-function-parser/test/cases/custom-function/0014.expect.json new file mode 100644 index 0000000000..f130f34fc1 --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0014.expect.json @@ -0,0 +1,429 @@ +{ + "type": "custom-function", + "name": "--foo", + "string": "--foo(--x : red, --y, --z ) returns ", + "tokens": [ + [ + "function-token", + "--foo(", + 0, + 5, + { + "value": "--foo" + } + ], + [ + "ident-token", + "--x", + 6, + 8, + { + "value": "--x" + } + ], + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ], + [ + "colon-token", + ":", + 17, + 17, + null + ], + [ + "whitespace-token", + " ", + 18, + 18, + null + ], + [ + "ident-token", + "red", + 19, + 21, + { + "value": "red" + } + ], + [ + "comma-token", + ",", + 22, + 22, + null + ], + [ + "whitespace-token", + " ", + 23, + 23, + null + ], + [ + "ident-token", + "--y", + 24, + 26, + { + "value": "--y" + } + ], + [ + "comma-token", + ",", + 27, + 27, + null + ], + [ + "whitespace-token", + " ", + 28, + 28, + null + ], + [ + "ident-token", + "--z", + 29, + 31, + { + "value": "--z" + } + ], + [ + "whitespace-token", + " ", + 32, + 32, + null + ], + [ + "delim-token", + "<", + 33, + 33, + { + "value": "<" + } + ], + [ + "ident-token", + "length", + 34, + 39, + { + "value": "length" + } + ], + [ + "delim-token", + ">", + 40, + 40, + { + "value": ">" + } + ], + [ + ")-token", + ")", + 41, + 41, + null + ], + [ + "whitespace-token", + " ", + 42, + 42, + null + ], + [ + "ident-token", + "returns", + 43, + 49, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 50, + 50, + null + ], + [ + "delim-token", + "<", + 51, + 51, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 52, + 57, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 58, + 58, + { + "value": ">" + } + ] + ], + "parameters": [ + { + "type": "function-parameter", + "name": "--x", + "argumentType": [ + [ + "whitespace-token", + " ", + 9, + 9, + null + ], + [ + "delim-token", + "<", + 10, + 10, + { + "value": "<" + } + ], + [ + "ident-token", + "color", + 11, + 15, + { + "value": "color" + } + ], + [ + "delim-token", + ">", + 16, + 16, + { + "value": ">" + } + ] + ], + "colon": [ + "colon-token", + ":", + 17, + 17, + null + ], + "defaultValue": [ + [ + "whitespace-token", + " ", + 18, + 18, + null + ], + [ + "ident-token", + "red", + 19, + 21, + { + "value": "red" + } + ] + ], + "before": [], + "after": [ + [ + "comma-token", + ",", + 22, + 22, + null + ] + ] + }, + { + "type": "function-parameter", + "name": "--y", + "argumentType": [], + "colon": null, + "defaultValue": [], + "before": [ + [ + "whitespace-token", + " ", + 23, + 23, + null + ] + ], + "after": [ + [ + "comma-token", + ",", + 27, + 27, + null + ] + ] + }, + { + "type": "function-parameter", + "name": "--z", + "argumentType": [ + [ + "whitespace-token", + " ", + 32, + 32, + null + ], + [ + "delim-token", + "<", + 33, + 33, + { + "value": "<" + } + ], + [ + "ident-token", + "length", + 34, + 39, + { + "value": "length" + } + ], + [ + "delim-token", + ">", + 40, + 40, + { + "value": ">" + } + ] + ], + "colon": null, + "defaultValue": [], + "before": [ + [ + "whitespace-token", + " ", + 28, + 28, + null + ] + ], + "after": [] + } + ], + "returnsKeyword": [ + [ + "whitespace-token", + " ", + 42, + 42, + null + ], + [ + "ident-token", + "returns", + 43, + 49, + { + "value": "returns" + } + ], + [ + "whitespace-token", + " ", + 50, + 50, + null + ] + ], + "returnType": [ + [ + "delim-token", + "<", + 51, + 51, + { + "value": "<" + } + ], + [ + "ident-token", + "string", + 52, + 57, + { + "value": "string" + } + ], + [ + "delim-token", + ">", + 58, + 58, + { + "value": ">" + } + ] + ], + "before": [], + "after": [] +} \ No newline at end of file diff --git a/packages/custom-function-parser/test/cases/custom-function/0014.mjs b/packages/custom-function-parser/test/cases/custom-function/0014.mjs new file mode 100644 index 0000000000..c2e1df664d --- /dev/null +++ b/packages/custom-function-parser/test/cases/custom-function/0014.mjs @@ -0,0 +1,13 @@ +import assert from 'node:assert'; +import { runTest } from '../../util/run-test.mjs'; + +runTest( + '--foo(--x : red, --y, --z ) returns ', + 'custom-function/0014', + (actual, expected) => { + assert.deepStrictEqual( + actual, + expected, + ); + }, +); diff --git a/packages/custom-function-parser/test/get-argument-type/0001.mjs b/packages/custom-function-parser/test/get-argument-type/0001.mjs new file mode 100644 index 0000000000..1fc6625a46 --- /dev/null +++ b/packages/custom-function-parser/test/get-argument-type/0001.mjs @@ -0,0 +1,67 @@ +import assert from 'node:assert'; +import { parse } from '@csstools/custom-function-parser'; + + +{ + const fn = parse('--foo(--bar, --baz : "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '', + ); + + assert.strictEqual( + fn.parameters[1].getArgumentType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar, --baz type(): "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '', + ); + + assert.strictEqual( + fn.parameters[1].getArgumentType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar /* a comment */ /* a comment */ : /* a comment */ "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar type(/* a comment */ /* a comment */) : /* a comment */ "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar [ /* a comment */ /* a comment */ | /* a comment */ /* a comment */ ] : /* a comment */ "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '[ | ]', + ); +} + +{ + const fn = parse('--foo(--bar type([ /* a comment */ /* a comment */ | /* a comment */ /* a comment */ ]) : /* a comment */ "foo")'); + + assert.strictEqual( + fn.parameters[0].getArgumentType(), + '[ | ]', + ); +} diff --git a/packages/custom-function-parser/test/get-default-value/0001.mjs b/packages/custom-function-parser/test/get-default-value/0001.mjs new file mode 100644 index 0000000000..0cbc7c615f --- /dev/null +++ b/packages/custom-function-parser/test/get-default-value/0001.mjs @@ -0,0 +1,78 @@ +import assert from 'node:assert'; +import { parse } from '@csstools/custom-function-parser'; + + +{ + const fn = parse('--foo(--bar, --baz : "foo")'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '', + ); + + assert.strictEqual( + fn.parameters[1].getDefaultValue(), + '"foo"', + ); +} + +{ + const fn = parse('--foo(--bar : /* a comment */ "foo" /* a comment */)'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '/* a comment */ "foo" /* a comment */', + ); +} + +{ + const fn = parse('--foo(--bar : /* a comment */ "foo" /* a comment */)'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '/* a comment */ "foo" /* a comment */', + ); +} + +{ + const fn = parse('--foo(--bar: { 1, 2 }, --baz: 1)'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '1, 2', + ); + + assert.strictEqual( + fn.parameters[1].getDefaultValue(), + '1', + ); +} + +{ + const fn = parse('--foo(--bar: { 1, 2 } "something", --baz: 1)'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '{ 1, 2 } "something"', + ); + + assert.strictEqual( + fn.parameters[1].getDefaultValue(), + '1', + ); +} + + +{ + const fn = parse('--foo(--bar: ( 1, 2 ), --baz: 1)'); + + assert.strictEqual( + fn.parameters[0].getDefaultValue(), + '( 1, 2 )', + ); + + assert.strictEqual( + fn.parameters[1].getDefaultValue(), + '1', + ); +} diff --git a/packages/custom-function-parser/test/get-name/0001.mjs b/packages/custom-function-parser/test/get-name/0001.mjs new file mode 100644 index 0000000000..25257035df --- /dev/null +++ b/packages/custom-function-parser/test/get-name/0001.mjs @@ -0,0 +1,34 @@ +import assert from 'node:assert'; +import { parse } from '@csstools/custom-function-parser'; + +{ + const fn = parse('--foo()'); + + assert.strictEqual( + fn.getName(), + '--foo', + ); +} + +{ + const fn = parse('--foo(--bar)'); + + assert.strictEqual( + fn.parameters[0].getName(), + '--bar', + ); +} + +{ + const fn = parse('--foo(--bar, --baz : "foo")'); + + assert.strictEqual( + fn.parameters[0].getName(), + '--bar', + ); + + assert.strictEqual( + fn.parameters[1].getName(), + '--baz', + ); +} diff --git a/packages/custom-function-parser/test/get-return-type/0001.mjs b/packages/custom-function-parser/test/get-return-type/0001.mjs new file mode 100644 index 0000000000..17b92a6223 --- /dev/null +++ b/packages/custom-function-parser/test/get-return-type/0001.mjs @@ -0,0 +1,66 @@ +import assert from 'node:assert'; +import { parse } from '@csstools/custom-function-parser'; + + +{ + const fn = parse('--foo()'); + + assert.strictEqual( + fn.getReturnType(), + '', + ); +} + +{ + const fn = parse('--foo() returns '); + + assert.strictEqual( + fn.getReturnType(), + '', + ); +} + +{ + const fn = parse('--foo() returns type()'); + + assert.strictEqual( + fn.getReturnType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar: /* a comment */ "foo") returns /* a comment */ /* a comment */'); + + assert.strictEqual( + fn.getReturnType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar: /* a comment */ "foo") returns type(/* a comment */ /* a comment */)'); + + assert.strictEqual( + fn.getReturnType(), + '', + ); +} + +{ + const fn = parse('--foo(--bar: /* a comment */ "foo") returns [ /* a comment */ /* a comment */ | /* a comment */ /* a comment */ ]'); + + assert.strictEqual( + fn.getReturnType(), + '[ | ]', + ); +} + +{ + const fn = parse('--foo(--bar: /* a comment */ "foo") returns type([ /* a comment */ /* a comment */ | /* a comment */ /* a comment */ ])'); + + assert.strictEqual( + fn.getReturnType(), + '[ | ]', + ); +} diff --git a/packages/custom-function-parser/test/parse-prelude/0001.mjs b/packages/custom-function-parser/test/parse-prelude/0001.mjs new file mode 100644 index 0000000000..2562066923 --- /dev/null +++ b/packages/custom-function-parser/test/parse-prelude/0001.mjs @@ -0,0 +1,104 @@ +import assert from 'node:assert'; +import { parse } from '@csstools/custom-function-parser'; + +// Cases derived from: +// https://github.com/web-platform-tests/wpt/blob/master/css/css-mixins/functions/at-function-parsing.html +// +// Only the cases that do not require full `` syntax validation are +// asserted here. Type validation is part of the typed parameters iteration. + +const valid = [ + '--foo()', + '--foo( )', + '--foo(--x)', + '--foo( --x )', + '--foo(--x auto)', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x )', + '--foo(--x