Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
allow arrays in visitor definition #112
  • Loading branch information
tbela99 committed Sep 16, 2025
commit 11c8deabb030d6c0eb62c4f8c487c4ff26e4fcc3
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

- [x] make streaming optional #109
- [x] patch at-rule syntax for @font-feature-value #110
- [x] support percentage in transform() and scale() #111
- [x] allow arrays in visitor definition #112

## v1.3.3

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# css-parser

CSS parser and minifier for node and the browser
CSS parser, minifier and validator for node and the browser

## Installation

Expand Down Expand Up @@ -101,7 +101,7 @@ Javascript module from cdn

<script type="module">

import {transform} from 'https://esm.sh/@tbela99/css-parser@1.3.3/web';
import {transform} from 'https://esm.sh/@tbela99/css-parser@1.3.4/web';

const css = `
.s {
Expand All @@ -126,7 +126,7 @@ Javascript umd module from cdn

```html

<script src="https://unpkg.com/@tbela99/css-parser@1.3.2/dist/index-umd-web.js"></script>
<script src="https://unpkg.com/@tbela99/css-parser@1.3.4/dist/index-umd-web.js"></script>
<script>

(async () => {
Expand Down
325 changes: 203 additions & 122 deletions dist/index-umd-web.js

Large diffs are not rendered by default.

325 changes: 203 additions & 122 deletions dist/index.cjs

Large diffs are not rendered by default.

41 changes: 23 additions & 18 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ declare enum WalkerOptionEnum {
/**
* event types for the walkValues function
*/
declare enum WalkerValueEvent {
declare enum WalkerEvent {
/**
* enter node
*/
Expand Down Expand Up @@ -777,7 +777,7 @@ declare function walk(node: AstNode$1, filter?: WalkerFilter | null, reverse?: b
*
*/
declare function walkValues(values: Token$1[], root?: AstNode$1 | Token$1 | null, filter?: WalkerValueFilter | null | {
event?: WalkerValueEvent;
event?: WalkerEvent;
fn?: WalkerValueFilter;
type?: EnumToken$1 | EnumToken$1[] | ((token: Token$1) => boolean);
}, reverse?: boolean): Generator<WalkAttributesResult>;
Expand Down Expand Up @@ -2182,13 +2182,12 @@ export declare type AstNode$1 =
| AstInvalidRule
| AstInvalidDeclaration;

export declare type VisitorEventType = 'Enter' | 'Leave' ;
export declare type GenericVisitorResult<T> = T | T[] | Promise<T> | Promise<T[]> | null | Promise<null>;
export declare type GenericVisitorHandler<T> = ((node: T, parent?: AstNode | Token, root?: AstNode | Token) => GenericVisitorResult<T>);
export declare type GenericVisitorAstNodeHandlerMap<T> =
Record<string, GenericVisitorHandler<T>>
| GenericVisitorHandler<T>
| { type: VisitorEventType, handler: Record<string, GenericVisitorHandler<T>> | GenericVisitorHandler<T> };
| { type: WalkerEvent, handler: Record<string, GenericVisitorHandler<T>> };

export declare type ValueVisitorHandler = GenericVisitorHandler<Token>;

Expand Down Expand Up @@ -2254,7 +2253,7 @@ export declare interface VisitorNodeMap {
* // @media tv,screen{.foo{height:calc(40px/3)}}
* ```
*/
AtRule?: GenericVisitorAstNodeHandlerMap<AstAtRule>;
AtRule?: GenericVisitorAstNodeHandlerMap<AstAtRule> | Array<GenericVisitorAstNodeHandlerMap<AstAtRule>>;
/**
* declaration visitor
*
Expand Down Expand Up @@ -2356,7 +2355,7 @@ export declare interface VisitorNodeMap {
* // .foo{width:calc(40px/3);padding:10px}.selector{padding:20px}
* ```
*/
Declaration?: GenericVisitorAstNodeHandlerMap<AstDeclaration>;
Declaration?: GenericVisitorAstNodeHandlerMap<AstDeclaration> | Array<GenericVisitorAstNodeHandlerMap<AstDeclaration>>;

/**
* rule visitor
Expand Down Expand Up @@ -2398,19 +2397,22 @@ export declare interface VisitorNodeMap {
* // .foo{width:3px;.foo{width:3px}}
* ```
*/
Rule?: GenericVisitorAstNodeHandlerMap<AstRule>;
Rule?: GenericVisitorAstNodeHandlerMap<AstRule> | Array<GenericVisitorAstNodeHandlerMap<AstRule>>;

KeyframesRule?: GenericVisitorAstNodeHandlerMap<AstKeyframesRule>;
KeyframesRule?: GenericVisitorAstNodeHandlerMap<AstKeyframesRule> | Array<GenericVisitorAstNodeHandlerMap<AstKeyframesRule>>;

KeyframesAtRule?: GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule> | Record<string, GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule>>;
KeyframesAtRule?: GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule> | Record<string, GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule>> | Array<GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule> | Record<string, GenericVisitorAstNodeHandlerMap<AstKeyframesAtRule>>>;

/**
* value visitor
*/
Value?: GenericVisitorHandler<Token> | Record<keyof EnumToken, GenericVisitorHandler<Token>> | {
type: VisitorEventType,
type: WalkerEvent,
handler: GenericVisitorHandler<Token> | Record<keyof EnumToken, GenericVisitorHandler<Token>>
};
} | Array<GenericVisitorHandler<Token> | Record<keyof EnumToken, GenericVisitorHandler<Token>> | {
type: WalkerEvent,
handler: GenericVisitorHandler<Token> | Record<keyof EnumToken, GenericVisitorHandler<Token>>
}>;

/**
* generic token visitor. the key name is of type keyof EnumToken.
Expand Down Expand Up @@ -2460,9 +2462,12 @@ export declare interface VisitorNodeMap {
* ```
*/
[key: keyof EnumToken]: GenericVisitorHandler<Token> | {
type: VisitorEventType,
type: WalkerEvent,
handler: GenericVisitorHandler<Token>
};
} | Array<GenericVisitorHandler<Token> | {
type: WalkerEvent,
handler: GenericVisitorHandler<Token>
}>;
}

export declare interface PropertyListOptions {
Expand Down Expand Up @@ -3019,7 +3024,7 @@ export declare type WalkerFilter = (node: AstNode$1) => WalkerOption;
/**
* filter nod
*/
export declare type WalkerValueFilter = (node: AstNode$1 | Token$1, parent?: AstNode$1 | Token$1 | null, event?: WalkerValueEvent) => WalkerOption | null;
export declare type WalkerValueFilter = (node: AstNode$1 | Token$1, parent?: AstNode$1 | Token$1 | null, event?: WalkerEvent) => WalkerOption | null;

export declare interface WalkResult {
node: AstNode$1;
Expand Down Expand Up @@ -3275,9 +3280,9 @@ export declare interface ParserOptions extends MinifyOptions, MinifyFeatureOptio

/**
* node visitor
* {@link VisitorNodeMap}
* {@link VisitorNodeMap | VisitorNodeMap[]}
*/
visitor?: VisitorNodeMap;
visitor?: VisitorNodeMap | VisitorNodeMap[];
/**
* abort signal
*
Expand Down Expand Up @@ -3900,5 +3905,5 @@ declare function transformFile(file: string, options?: TransformOptions, asStrea
*/
declare function transform(css: string | ReadableStream<Uint8Array>, options?: TransformOptions): Promise<TransformResult>;

export { ColorType, EnumToken$1 as EnumToken, FeatureWalkMode, SourceMap, ValidationLevel, WalkerOptionEnum, WalkerValueEvent, convertColor, dirname, expand, isOkLabClose, load, mathFuncs, minify, okLabDistance, parse, parseDeclarations, parseFile, parseString, parseTokens, render, renderToken, resolve, transform, transformFile, transformFunctions, walk, walkValues };
export type { AddToken, AngleToken, AstAtRule, AstComment, AstDeclaration, AstInvalidAtRule, AstInvalidDeclaration, AstInvalidRule, AstKeyFrameRule, AstKeyframesAtRule, AstKeyframesRule, AstNode$1 as AstNode, AstRule, AstRuleList, AstStyleSheet, AtRuleToken, AtRuleVisitorHandler, AttrEndToken, AttrStartToken, AttrToken, Background, BackgroundAttachmentMapping, BackgroundPosition, BackgroundPositionClass, BackgroundPositionConstraints, BackgroundPositionMapping, BackgroundProperties, BackgroundRepeat, BackgroundRepeatMapping, BackgroundSize, BackgroundSizeMapping, BadCDOCommentToken, BadCommentToken, BadStringToken, BadUrlToken, BaseToken, BinaryExpressionNode, BinaryExpressionToken, BlockEndToken, BlockStartToken, Border, BorderColor, BorderColorClass, BorderProperties, BorderRadius, CDOCommentToken, ChildCombinatorToken, ClassSelectorToken, ColonToken, ColorToken, ColumnCombinatorToken, CommaToken, CommentToken, ConstraintsMapping, ContainMatchToken, Context, DashMatchToken, DashedIdentToken, DeclarationVisitorHandler, DelimToken, DescendantCombinatorToken, DimensionToken, DivToken, EOFToken, EndMatchToken, EqualMatchToken, ErrorDescription, FlexToken, Font, FontFamily, FontProperties, FontWeight, FontWeightConstraints, FontWeightMapping, FractionToken, FrequencyToken, FunctionImageToken, FunctionToken, FunctionURLToken, GenericVisitorAstNodeHandlerMap, GenericVisitorHandler, GenericVisitorResult, GreaterThanOrEqualToken, GreaterThanToken, GridTemplateFuncToken, HashToken, IdentListToken, IdentToken, ImportantToken, IncludeMatchToken, InvalidAttrToken, InvalidClassSelectorToken, LengthToken, LessThanOrEqualToken, LessThanToken, LineHeight, ListToken, LiteralToken, LoadResult, Location, Map$1 as Map, MatchExpressionToken, MatchedSelector, MediaFeatureAndToken, MediaFeatureNotToken, MediaFeatureOnlyToken, MediaFeatureOrToken, MediaFeatureToken, MediaQueryConditionToken, MinifyFeature, MinifyFeatureOptions, MinifyOptions, MulToken, NameSpaceAttributeToken, NestingSelectorToken, NextSiblingCombinatorToken, NumberToken, OptimizedSelector, OptimizedSelectorToken, Outline, OutlineProperties, ParensEndToken, ParensStartToken, ParensToken, ParseInfo, ParseResult, ParseResultStats, ParseTokenOptions, ParserOptions, PercentageToken, Position, Prefix, PropertiesConfig, PropertiesConfigProperties, PropertyListOptions, PropertyMapType, PropertySetType, PropertyType, PseudoClassFunctionToken, PseudoClassToken, PseudoElementToken, PseudoPageToken, PurpleBackgroundAttachment, RawSelectorTokens, RenderOptions, RenderResult, ResolutionToken, ResolvedPath, RuleVisitorHandler, SemiColonToken, Separator, ShorthandDef, ShorthandMapType, ShorthandProperties, ShorthandPropertyType, ShorthandType, SourceMapObject, StartMatchToken, StringToken, SubToken, SubsequentCombinatorToken, TimeToken, TimelineFunctionToken, TimingFunctionToken, Token$1 as Token, TokenizeResult, TransformOptions, TransformResult, UnaryExpression, UnaryExpressionNode, UnclosedStringToken, UniversalSelectorToken, UrlToken, ValidationConfiguration, ValidationOptions, ValidationResult, ValidationSelectorOptions, ValidationSyntaxNode, ValidationSyntaxResult, Value, ValueVisitorHandler, VariableScopeInfo, VisitorEventType, VisitorNodeMap, WalkAttributesResult, WalkResult, WalkerFilter, WalkerOption, WalkerValueFilter, WhitespaceToken };
export { ColorType, EnumToken$1 as EnumToken, FeatureWalkMode, SourceMap, ValidationLevel, WalkerEvent, WalkerOptionEnum, convertColor, dirname, expand, isOkLabClose, load, mathFuncs, minify, okLabDistance, parse, parseDeclarations, parseFile, parseString, parseTokens, render, renderToken, resolve, transform, transformFile, transformFunctions, walk, walkValues };
export type { AddToken, AngleToken, AstAtRule, AstComment, AstDeclaration, AstInvalidAtRule, AstInvalidDeclaration, AstInvalidRule, AstKeyFrameRule, AstKeyframesAtRule, AstKeyframesRule, AstNode$1 as AstNode, AstRule, AstRuleList, AstStyleSheet, AtRuleToken, AtRuleVisitorHandler, AttrEndToken, AttrStartToken, AttrToken, Background, BackgroundAttachmentMapping, BackgroundPosition, BackgroundPositionClass, BackgroundPositionConstraints, BackgroundPositionMapping, BackgroundProperties, BackgroundRepeat, BackgroundRepeatMapping, BackgroundSize, BackgroundSizeMapping, BadCDOCommentToken, BadCommentToken, BadStringToken, BadUrlToken, BaseToken, BinaryExpressionNode, BinaryExpressionToken, BlockEndToken, BlockStartToken, Border, BorderColor, BorderColorClass, BorderProperties, BorderRadius, CDOCommentToken, ChildCombinatorToken, ClassSelectorToken, ColonToken, ColorToken, ColumnCombinatorToken, CommaToken, CommentToken, ConstraintsMapping, ContainMatchToken, Context, DashMatchToken, DashedIdentToken, DeclarationVisitorHandler, DelimToken, DescendantCombinatorToken, DimensionToken, DivToken, EOFToken, EndMatchToken, EqualMatchToken, ErrorDescription, FlexToken, Font, FontFamily, FontProperties, FontWeight, FontWeightConstraints, FontWeightMapping, FractionToken, FrequencyToken, FunctionImageToken, FunctionToken, FunctionURLToken, GenericVisitorAstNodeHandlerMap, GenericVisitorHandler, GenericVisitorResult, GreaterThanOrEqualToken, GreaterThanToken, GridTemplateFuncToken, HashToken, IdentListToken, IdentToken, ImportantToken, IncludeMatchToken, InvalidAttrToken, InvalidClassSelectorToken, LengthToken, LessThanOrEqualToken, LessThanToken, LineHeight, ListToken, LiteralToken, LoadResult, Location, Map$1 as Map, MatchExpressionToken, MatchedSelector, MediaFeatureAndToken, MediaFeatureNotToken, MediaFeatureOnlyToken, MediaFeatureOrToken, MediaFeatureToken, MediaQueryConditionToken, MinifyFeature, MinifyFeatureOptions, MinifyOptions, MulToken, NameSpaceAttributeToken, NestingSelectorToken, NextSiblingCombinatorToken, NumberToken, OptimizedSelector, OptimizedSelectorToken, Outline, OutlineProperties, ParensEndToken, ParensStartToken, ParensToken, ParseInfo, ParseResult, ParseResultStats, ParseTokenOptions, ParserOptions, PercentageToken, Position, Prefix, PropertiesConfig, PropertiesConfigProperties, PropertyListOptions, PropertyMapType, PropertySetType, PropertyType, PseudoClassFunctionToken, PseudoClassToken, PseudoElementToken, PseudoPageToken, PurpleBackgroundAttachment, RawSelectorTokens, RenderOptions, RenderResult, ResolutionToken, ResolvedPath, RuleVisitorHandler, SemiColonToken, Separator, ShorthandDef, ShorthandMapType, ShorthandProperties, ShorthandPropertyType, ShorthandType, SourceMapObject, StartMatchToken, StringToken, SubToken, SubsequentCombinatorToken, TimeToken, TimelineFunctionToken, TimingFunctionToken, Token$1 as Token, TokenizeResult, TransformOptions, TransformResult, UnaryExpression, UnaryExpressionNode, UnclosedStringToken, UniversalSelectorToken, UrlToken, ValidationConfiguration, ValidationOptions, ValidationResult, ValidationSelectorOptions, ValidationSyntaxNode, ValidationSyntaxResult, Value, ValueVisitorHandler, VariableScopeInfo, VisitorNodeMap, WalkAttributesResult, WalkResult, WalkerFilter, WalkerOption, WalkerValueFilter, WhitespaceToken };
4 changes: 2 additions & 2 deletions dist/lib/ast/features/calc.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EnumToken } from '../types.js';
import { walkValues, WalkerValueEvent, WalkerOptionEnum } from '../walk.js';
import { walkValues, WalkerEvent, WalkerOptionEnum } from '../walk.js';
import { evaluate } from '../math/expression.js';
import { renderToken } from '../../renderer/render.js';
import '../../renderer/sourcemap/lib/encode.js';
Expand Down Expand Up @@ -34,7 +34,7 @@ class ComputeCalcExpressionFeature {
}
const set = new Set;
for (const { value, parent } of walkValues(node.val, node, {
event: WalkerValueEvent.Enter,
event: WalkerEvent.Enter,
// @ts-ignore
fn(node, parent) {
if (parent != null &&
Expand Down
7 changes: 4 additions & 3 deletions dist/lib/ast/features/inlinecssvariables.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,10 @@ class InlineCssVariablesFeature {
}
}
run(ast, options = {}, parent, context) {
if (!('chi' in ast)) {
return null;
}
// if (!('chi' in ast)) {
//
// return null;
// }
if (!('variableScope' in context)) {
context.variableScope = new Map;
}
Expand Down
40 changes: 20 additions & 20 deletions dist/lib/ast/transform/matrix.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,27 +30,27 @@ function parseMatrix(mat) {
function matrix(values) {
const matrix = identity();
if (values.length === 6) {
matrix[0 * 4 + 0] = values[0];
matrix[0 * 4 + 1] = values[1];
matrix[1 * 4 + 0] = values[2];
matrix[1 * 4 + 1] = values[3];
matrix[3 * 4 + 0] = values[4];
matrix[0] = values[0];
matrix[1] = values[1];
matrix[4] = values[2];
matrix[4 + 1] = values[3];
matrix[3 * 4] = values[4];
matrix[3 * 4 + 1] = values[5];
}
else if (values.length === 16) {
matrix[0 * 4 + 0] = values[0];
matrix[0 * 4 + 1] = values[1];
matrix[0 * 4 + 2] = values[2];
matrix[0 * 4 + 3] = values[3];
matrix[1 * 4 + 0] = values[4];
matrix[1 * 4 + 1] = values[5];
matrix[1 * 4 + 2] = values[6];
matrix[1 * 4 + 3] = values[7];
matrix[2 * 4 + 0] = values[8];
matrix[0] = values[0];
matrix[1] = values[1];
matrix[2] = values[2];
matrix[3] = values[3];
matrix[4] = values[4];
matrix[4 + 1] = values[5];
matrix[4 + 2] = values[6];
matrix[4 + 3] = values[7];
matrix[2 * 4] = values[8];
matrix[2 * 4 + 1] = values[9];
matrix[2 * 4 + 2] = values[10];
matrix[2 * 4 + 3] = values[11];
matrix[3 * 4 + 0] = values[12];
matrix[3 * 4] = values[12];
matrix[3 * 4 + 1] = values[13];
matrix[3 * 4 + 2] = values[14];
matrix[3 * 4 + 3] = values[15];
Expand All @@ -75,11 +75,11 @@ function serialize(matrix) {
typ: EnumToken.FunctionTokenType,
val: 'matrix',
chi: [
matrix[0 * 4 + 0],
matrix[0 * 4 + 1],
matrix[1 * 4 + 0],
matrix[1 * 4 + 1],
matrix[3 * 4 + 0],
matrix[0],
matrix[1],
matrix[4],
matrix[4 + 1],
matrix[3 * 4],
matrix[3 * 4 + 1]
].reduce((acc, t) => {
if (acc.length > 0) {
Expand Down
22 changes: 11 additions & 11 deletions dist/lib/ast/transform/rotate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ function rotate3D(angle, x, y, z, from) {
x *= unit;
y *= unit;
z *= unit;
matrix[0 * 4 + 0] = 1 - 2 * (y * y + z * z) * sq;
matrix[0 * 4 + 1] = 2 * (x * y * sq + z * sc);
matrix[0 * 4 + 2] = 2 * (x * z * sq - y * sc);
matrix[1 * 4 + 0] = 2 * (x * y * sq - z * sc);
matrix[1 * 4 + 1] = 1 - 2 * (x * x + z * z) * sq;
matrix[1 * 4 + 2] = 2 * (y * z * sq + x * sc);
matrix[2 * 4 + 0] = 2 * (x * z * sq + y * sc);
matrix[0] = 1 - 2 * (y * y + z * z) * sq;
matrix[1] = 2 * (x * y * sq + z * sc);
matrix[2] = 2 * (x * z * sq - y * sc);
matrix[4] = 2 * (x * y * sq - z * sc);
matrix[4 + 1] = 1 - 2 * (x * x + z * z) * sq;
matrix[4 + 2] = 2 * (y * z * sq + x * sc);
matrix[2 * 4] = 2 * (x * z * sq + y * sc);
matrix[2 * 4 + 1] = 2 * (y * z * sq - x * sc);
matrix[2 * 4 + 2] = 1 - 2 * (x * x + y * y) * sq;
return multiply(from, matrix);
}
function rotate(angle, from) {
const matrix = identity();
matrix[0 * 4 + 0] = Math.cos(angle);
matrix[0 * 4 + 1] = Math.sin(angle);
matrix[1 * 4 + 0] = -Math.sin(angle);
matrix[1 * 4 + 1] = Math.cos(angle);
matrix[0] = Math.cos(angle);
matrix[1] = Math.sin(angle);
matrix[4] = -Math.sin(angle);
matrix[4 + 1] = Math.cos(angle);
return multiply(from, matrix);
}

Expand Down
12 changes: 6 additions & 6 deletions dist/lib/ast/transform/scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { identity, multiply } from './utils.js';

function scaleX(x, from) {
const matrix = identity();
matrix[0 * 4 + 0] = x;
matrix[0] = x;
return multiply(from, matrix);
}
function scaleY(y, from) {
const matrix = identity();
matrix[1 * 4 + 1] = y;
matrix[4 + 1] = y;
return multiply(from, matrix);
}
function scaleZ(z, from) {
Expand All @@ -17,14 +17,14 @@ function scaleZ(z, from) {
}
function scale(x, y, from) {
const matrix = identity();
matrix[0 * 4 + 0] = x;
matrix[1 * 4 + 1] = y;
matrix[0] = x;
matrix[4 + 1] = y;
return multiply(from, matrix);
}
function scale3d(x, y, z, from) {
const matrix = identity();
matrix[0 * 4 + 0] = x;
matrix[1 * 4 + 1] = y;
matrix[0] = x;
matrix[4 + 1] = y;
matrix[2 * 4 + 2] = z;
return multiply(from, matrix);
}
Expand Down
8 changes: 4 additions & 4 deletions dist/lib/ast/transform/skew.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ import { identity, multiply } from './utils.js';

function skewX(x, from) {
const matrix = identity();
matrix[1 * 4 + 0] = Math.tan(x);
matrix[4] = Math.tan(x);
return multiply(from, matrix);
}
function skewY(y, from) {
const matrix = identity();
matrix[0 * 4 + 1] = Math.tan(y);
matrix[1] = Math.tan(y);
return multiply(from, matrix);
}
// convert angle to radian
function skew(values, from) {
const matrix = identity();
matrix[1 * 4 + 0] = Math.tan(values[0]);
matrix[4] = Math.tan(values[0]);
if (values.length > 1) {
matrix[0 * 4 + 1] = Math.tan(values[1]);
matrix[1] = Math.tan(values[1]);
}
return multiply(from, matrix);
}
Expand Down
Loading
Loading