Skip to content

Commit

Permalink
Merge pull request #1924 from postcss/refactor/types
Browse files Browse the repository at this point in the history
Reducint `node.parent.nodes!`
  • Loading branch information
ai committed Feb 7, 2024
2 parents 477b3bb + 5e7449f commit 612f360
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 32 deletions.
7 changes: 5 additions & 2 deletions lib/at-rule.d.ts
@@ -1,4 +1,7 @@
import Container, { ContainerProps } from './container.js'
import Container, {
ContainerProps,
ContainerWithChildren
} from './container.js'

declare namespace AtRule {
export interface AtRuleRaws extends Record<string, unknown> {
Expand Down Expand Up @@ -116,7 +119,7 @@ declare class AtRule_ extends Container {
* ```
*/
params: string
parent: Container | undefined
parent: ContainerWithChildren | undefined

raws: AtRule.AtRuleRaws

Expand Down
48 changes: 43 additions & 5 deletions lib/container.d.ts
Expand Up @@ -5,6 +5,12 @@ import Node, { ChildNode, ChildProps, NodeProps } from './node.js'
import Rule from './rule.js'

declare namespace Container {
export class ContainerWithChildren<
Child extends Node = ChildNode
> extends Container_<Child> {
nodes: Child[]
}

export interface ValueOptions {
/**
* String that’s used to narrow down values and speed up the regexp search.
Expand Down Expand Up @@ -66,7 +72,15 @@ declare abstract class Container_<Child extends Node = ChildNode> extends Node {
* @return This node for methods chain.
*/
append(
...nodes: (ChildProps | ChildProps[] | Node | Node[] | string | string[])[]
...nodes: (
| ChildProps
| ChildProps[]
| Node
| Node[]
| string
| string[]
| undefined
)[]
): this

assign(overrides: Container.ContainerProps | object): this
Expand Down Expand Up @@ -146,7 +160,14 @@ declare abstract class Container_<Child extends Node = ChildNode> extends Node {
*/
insertAfter(
oldNode: Child | number,
newNode: Child | Child[] | ChildProps | ChildProps[] | string | string[]
newNode:
| Child
| Child[]
| ChildProps
| ChildProps[]
| string
| string[]
| undefined
): this
/**
* Insert new node before old node within the container.
Expand All @@ -161,7 +182,14 @@ declare abstract class Container_<Child extends Node = ChildNode> extends Node {
*/
insertBefore(
oldNode: Child | number,
newNode: Child | Child[] | ChildProps | ChildProps[] | string | string[]
newNode:
| Child
| Child[]
| ChildProps
| ChildProps[]
| string
| string[]
| undefined
): this

/**
Expand Down Expand Up @@ -202,7 +230,15 @@ declare abstract class Container_<Child extends Node = ChildNode> extends Node {
* @return This node for methods chain.
*/
prepend(
...nodes: (ChildProps | ChildProps[] | Node | Node[] | string | string[])[]
...nodes: (
| ChildProps
| ChildProps[]
| Node
| Node[]
| string
| string[]
| undefined
)[]
): this
/**
* Add child to the end of the node.
Expand Down Expand Up @@ -447,6 +483,8 @@ declare abstract class Container_<Child extends Node = ChildNode> extends Node {
get last(): Child | undefined
}

declare class Container<Child extends Node = ChildNode> extends Container_<Child> {}
declare class Container<
Child extends Node = ChildNode
> extends Container_<Child> {}

export = Container
2 changes: 2 additions & 0 deletions lib/container.js
Expand Up @@ -173,6 +173,8 @@ class Container extends Node {
normalize(nodes, sample) {
if (typeof nodes === 'string') {
nodes = cleanSource(parse(nodes).nodes)
} else if (typeof nodes === 'undefined') {
nodes = []
} else if (Array.isArray(nodes)) {
nodes = nodes.slice(0)
for (let i of nodes) {
Expand Down
4 changes: 2 additions & 2 deletions lib/declaration.d.ts
@@ -1,4 +1,4 @@
import Container from './container.js'
import { ContainerWithChildren } from './container.js'
import Node from './node.js'

declare namespace Declaration {
Expand Down Expand Up @@ -79,7 +79,7 @@ declare class Declaration_ extends Node {
*/
important: boolean

parent: Container | undefined
parent: ContainerWithChildren | undefined

/**
* The property name for a CSS declaration.
Expand Down
6 changes: 3 additions & 3 deletions lib/node.d.ts
Expand Up @@ -246,7 +246,7 @@ declare abstract class Node_ {
* @param newNode New node.
* @return This node for methods chain.
*/
after(newNode: Node | Node.ChildProps | Node[] | string): this
after(newNode: Node | Node.ChildProps | Node[] | string | undefined): this

/**
* It assigns properties to an existing node instance.
Expand All @@ -273,7 +273,7 @@ declare abstract class Node_ {
* @param newNode New node.
* @return This node for methods chain.
*/
before(newNode: Node | Node.ChildProps | Node[] | string): this
before(newNode: Node | Node.ChildProps | Node[] | string | undefined): this

/**
* Clear the code style properties for the node and its children.
Expand Down Expand Up @@ -531,6 +531,6 @@ declare abstract class Node_ {
warn(result: Result, message: string, options?: WarningOptions): Warning
}

declare class Node extends Node_ { }
declare class Node extends Node_ {}

export = Node
7 changes: 5 additions & 2 deletions lib/rule.d.ts
@@ -1,4 +1,7 @@
import Container, { ContainerProps } from './container.js'
import Container, {
ContainerProps,
ContainerWithChildren
} from './container.js'

declare namespace Rule {
export interface RuleRaws extends Record<string, unknown> {
Expand Down Expand Up @@ -70,7 +73,7 @@ declare namespace Rule {
*/
declare class Rule_ extends Container {
nodes: NonNullable<Container['nodes']>
parent: Container | undefined
parent: ContainerWithChildren | undefined
raws: Rule.RuleRaws
/**
* The rule’s full selector represented as a string.
Expand Down
45 changes: 28 additions & 17 deletions test/container.test.ts
Expand Up @@ -638,18 +638,18 @@ test('insertBefore() receives array', () => {

test('insertBefore() receives pre-existing child node - a', () => {
let a = parse('a{ align-items: start; color: red; z-index: 1 }')
let declA = (a.first as Rule).nodes[0];
let declC = (a.first as Rule).nodes[2];
declC.before(declA);
let declA = (a.first as Rule).nodes[0]
let declC = (a.first as Rule).nodes[2]
declC.before(declA)

is(a.toString(), 'a{ color: red; align-items: start; z-index: 1 }')
})

test('insertBefore() receives pre-existing child node - b', () => {
let a = parse('a{ align-items: start; color: red; z-index: 1 }')
let declA = (a.first as Rule).nodes[0];
let declC = (a.first as Rule).nodes[2];
declA.before(declC);
let declA = (a.first as Rule).nodes[0]
let declC = (a.first as Rule).nodes[2]
declA.before(declC)

is(a.toString(), 'a{ z-index: 1; align-items: start; color: red }')
})
Expand Down Expand Up @@ -708,18 +708,18 @@ test('insertAfter() receives array', () => {

test('insertAfter() receives pre-existing child node - a', () => {
let a = parse('a{ align-items: start; color: red; z-index: 1 }')
let declA = (a.first as Rule).nodes[0];
let declC = (a.first as Rule).nodes[2];
declC.after(declA);
let declA = (a.first as Rule).nodes[0]
let declC = (a.first as Rule).nodes[2]
declC.after(declA)

is(a.toString(), 'a{ color: red; z-index: 1; align-items: start }')
})

test('insertAfter() receives pre-existing child node - b', () => {
let a = parse('a{ align-items: start; color: red; z-index: 1 }')
let declA = (a.first as Rule).nodes[0];
let declC = (a.first as Rule).nodes[2];
declA.after(declC);
let declA = (a.first as Rule).nodes[0]
let declC = (a.first as Rule).nodes[2]
declA.after(declC)

is(a.toString(), 'a{ align-items: start; z-index: 1; color: red }')
})
Expand Down Expand Up @@ -874,7 +874,7 @@ test('allows to clone nodes', () => {

test('container.nodes can be sorted', () => {
let root = parse('@b; @c; @a;')
let b = root.nodes[0];
let b = root.nodes[0]

root.nodes.sort((x, y) => {
return (x as AtRule).name.localeCompare((y as AtRule).name)
Expand All @@ -884,19 +884,30 @@ test('container.nodes can be sorted', () => {
is(root.toString(), ' @a;@b; @c;')

// Sorted nodes are reflected in "walk".
let result: string[] = [];
root.walkAtRules((atRule) => {
let result: string[] = []
root.walkAtRules(atRule => {
result.push(atRule.name.trim())
});
})

is(result.join(' '), 'a b c')

// Sorted nodes have the corect "index".
is(root.index(b), 1)

// Inserting after a sorted node results in the correct order.
b.after('@d;');
b.after('@d;')
is(root.toString(), ' @a;@b;@d; @c;')
})

test('ignores undefined on adding', () => {
let rule = parse('a { a: 1; b: 2 }').first as Rule
rule.append({ prop: 'c', value: '3' }, undefined)
rule.prepend(undefined)
rule.insertAfter(0, undefined)
rule.insertBefore(0, undefined)
rule.after(undefined)
rule.before(undefined)
is(rule.parent!.toString(), 'a { a: 1; b: 2; c: 3 }')
})

test.run()
2 changes: 1 addition & 1 deletion test/types.ts
Expand Up @@ -4,7 +4,7 @@ const plugin: PluginCreator<string> = prop => {
return {
Declaration: (decl, { Comment, result }) => {
if (decl.prop === prop) {
decl.warn(result, `${decl.prop} found`)
decl.warn(result, `${decl.prop} found in ${decl.parent?.nodes.length}`)
decl.replaceWith(new Comment({ text: `${decl.prop} removed` }))
}
},
Expand Down

0 comments on commit 612f360

Please sign in to comment.