@tokey/css-selector-parser
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -0,1 +1,2 @@ | ||
import type { Immutable } from "./types"; | ||
import type { Token } from "@tokey/core"; | ||
@@ -7,4 +8,5 @@ export interface Selector extends Omit<Token<"selector">, "value"> { | ||
} | ||
export declare type NthSelectorList = [Nth, ...SelectorList]; | ||
export interface PseudoClass extends Token<"pseudo_class"> { | ||
nodes?: Selector[] | [Nth, ...SelectorList]; | ||
nodes?: SelectorList | NthSelectorList; | ||
colonComments: Comment[]; | ||
@@ -35,7 +37,7 @@ } | ||
} | ||
export interface Element extends Token<"element"> { | ||
export interface Type extends Token<"type"> { | ||
namespace?: Namespace; | ||
nodes?: SelectorList; | ||
} | ||
export interface Star extends Token<"star"> { | ||
export interface Universal extends Token<"universal"> { | ||
namespace?: Namespace; | ||
@@ -74,7 +76,29 @@ nodes?: SelectorList; | ||
} | ||
export declare type NamespacedNodes = Element | Star; | ||
export declare type Containers = NamespacedNodes | Attribute | Id | Class | PseudoClass | PseudoElement | Nesting; | ||
export declare type SelectorNode = Containers | Selector | Combinator | Comment | Invalid | Nth | NthStep | NthDash | NthOffset | NthOf; | ||
export declare type NamespacedNode = Type | Universal; | ||
export declare type FunctionalSelector = NamespacedNode | Attribute | Id | Class | PseudoClass | PseudoElement | Nesting; | ||
export declare type SelectorNode = FunctionalSelector | Selector | Combinator | Comment | Invalid | Nth | NthStep | NthDash | NthOffset | NthOf; | ||
export declare type SelectorNodes = SelectorNode[]; | ||
export declare type SelectorList = Selector[]; | ||
export declare type ImmutableSelector = Immutable<Selector>; | ||
export declare type ImmutableSelectorList = Immutable<SelectorList>; | ||
export declare type ImmutableNthSelectorList = Immutable<NthSelectorList>; | ||
export declare type ImmutableSelectorNode = Immutable<SelectorNode>; | ||
export declare type ImmutableFunctionalSelector = Immutable<FunctionalSelector>; | ||
export declare type ImmutableNamespacedNode = Immutable<NamespacedNode>; | ||
export declare type ImmutableUniversal = Immutable<Universal>; | ||
export declare type ImmutableClass = Immutable<Class>; | ||
export declare type ImmutableId = Immutable<Id>; | ||
export declare type ImmutableType = Immutable<Type>; | ||
export declare type ImmutableCombinator = Immutable<Combinator>; | ||
export declare type ImmutableAttribute = Immutable<Attribute>; | ||
export declare type ImmutablePseudoClass = Immutable<PseudoClass>; | ||
export declare type ImmutablePseudoElement = Immutable<PseudoElement>; | ||
export declare type ImmutableComment = Immutable<Comment>; | ||
export declare type ImmutableNesting = Immutable<Nesting>; | ||
export declare type ImmutableInvalid = Immutable<Invalid>; | ||
export declare type ImmutableNth = Immutable<Nth>; | ||
export declare type ImmutableNthStep = Immutable<NthStep>; | ||
export declare type ImmutableNthDash = Immutable<NthDash>; | ||
export declare type ImmutableNthOffset = Immutable<NthOffset>; | ||
export declare type ImmutableNthOf = Immutable<NthOf>; | ||
//# sourceMappingURL=ast-types.d.ts.map |
import type { CSSSelectorToken } from "./tokenizer"; | ||
import type { Combinator, Comment, Selector, Nth, NamespacedNodes, SelectorList, SelectorNode } from "./ast-types"; | ||
import type { Combinator, Comment, Selector, Nth, NamespacedNode, SelectorList, SelectorNode } from "./ast-types"; | ||
import { Token } from "@tokey/core"; | ||
@@ -10,5 +10,5 @@ export declare function createEmptySelector(): Selector; | ||
export declare function isNamespacedToken(token: CSSSelectorToken): token is Token<"text" | "*">; | ||
export declare function isNamespacedAst(token: SelectorNode): token is NamespacedNodes; | ||
export declare function isNamespacedAst(token: SelectorNode): token is NamespacedNode; | ||
export declare function ensureSelector(selectors: SelectorList, startToken: CSSSelectorToken): Selector; | ||
export declare function trimCombinators(selector: Selector): void; | ||
//# sourceMappingURL=helpers.d.ts.map |
@@ -65,3 +65,3 @@ "use strict"; | ||
function isNamespacedAst(token) { | ||
return token.type === `star` || token.type === `element`; | ||
return token.type === `universal` || token.type === `type`; | ||
} | ||
@@ -68,0 +68,0 @@ exports.isNamespacedAst = isNamespacedAst; |
export { parseCssSelector } from "./selector-parser"; | ||
export type { ParseConfig } from "./selector-parser"; | ||
export * from "./ast-types"; | ||
@@ -3,0 +4,0 @@ export { stringifySelectorAst } from "./stringify"; |
import type { SelectorList } from "./ast-types"; | ||
export declare function parseCssSelector(source: string): SelectorList; | ||
export interface ParseConfig { | ||
offset: number; | ||
} | ||
export declare function parseCssSelector(source: string, options?: Partial<ParseConfig>): SelectorList; | ||
//# sourceMappingURL=selector-parser.d.ts.map |
@@ -8,4 +8,4 @@ "use strict"; | ||
const core_1 = require("@tokey/core"); | ||
function parseCssSelector(source) { | ||
return parseTokens(source, tokenizer_1.tokenizeSelector(source)); | ||
function parseCssSelector(source, options = {}) { | ||
return parseTokens(source, tokenizer_1.tokenizeSelector(source, options)); | ||
} | ||
@@ -180,3 +180,3 @@ exports.parseCssSelector = parseCssSelector; | ||
ast.push({ | ||
type: "element", | ||
type: "type", | ||
value: token.value, | ||
@@ -198,3 +198,3 @@ start: token.start, | ||
ast.push({ | ||
type: "star", | ||
type: "universal", | ||
value: "*", | ||
@@ -256,3 +256,3 @@ start: token.start, | ||
const validTarget = !!target; | ||
const type = (target === null || target === void 0 ? void 0 : target.type) === `*` ? `star` : `element`; | ||
const type = (target === null || target === void 0 ? void 0 : target.type) === `*` ? `universal` : `type`; | ||
let invalid = ``; | ||
@@ -336,3 +336,4 @@ // remove before/after pipe comments | ||
if (currentSelector) { | ||
currentSelector.end = (_b = (_a = core_1.last(currentSelector.nodes)) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : currentSelector.start; | ||
currentSelector.end = | ||
(_b = (_a = core_1.last(currentSelector.nodes)) === null || _a === void 0 ? void 0 : _a.end) !== null && _b !== void 0 ? _b : currentSelector.start; | ||
} | ||
@@ -404,3 +405,4 @@ return false; | ||
if (s.done()) { | ||
currentSelector.end = (_u = (_t = core_1.last(currentSelector.nodes)) === null || _t === void 0 ? void 0 : _t.end) !== null && _u !== void 0 ? _u : currentSelector.start; | ||
currentSelector.end = | ||
(_u = (_t = core_1.last(currentSelector.nodes)) === null || _t === void 0 ? void 0 : _t.end) !== null && _u !== void 0 ? _u : currentSelector.start; | ||
helpers_1.trimCombinators(currentSelector); | ||
@@ -407,0 +409,0 @@ } |
@@ -1,3 +0,3 @@ | ||
import type { Nth, SelectorList, SelectorNode } from "./ast-types"; | ||
export declare function stringifySelectorAst(value: SelectorNode | SelectorList | [Nth, ...SelectorList]): string; | ||
import type { ImmutableSelectorNode, ImmutableSelectorList, ImmutableNthSelectorList } from "./ast-types"; | ||
export declare function stringifySelectorAst(value: ImmutableSelectorNode | ImmutableSelectorList | ImmutableNthSelectorList): string; | ||
//# sourceMappingURL=stringify.d.ts.map |
@@ -6,5 +6,3 @@ "use strict"; | ||
function stringifySelectorAst(value) { | ||
return Array.isArray(value) | ||
? stringifySelectors(value) | ||
: stringifyNode(value); | ||
return "length" in value ? stringifySelectors(value) : stringifyNode(value); | ||
} | ||
@@ -15,3 +13,3 @@ exports.stringifySelectorAst = stringifySelectorAst; | ||
class: (node) => `.${node.dotComments.map(stringifyNode).join("")}${node.value}${stringifyNested(node)}`, | ||
element: (node) => `${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
type: (node) => `${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
combinator: (node) => `${node.before}${node.value}${node.after}`, | ||
@@ -24,3 +22,3 @@ attribute: (node) => `[${node.value}]${stringifyNested(node)}`, | ||
comment: ({ before, value, after }) => `${before}${value}${after}`, | ||
star: (node) => `${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
universal: (node) => `${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
nesting: (node) => `${node.value}${stringifyNested(node)}`, | ||
@@ -50,5 +48,10 @@ selector: (node) => `${node.before}${node.nodes.map(stringifyNode).join("")}${node.after}`, | ||
if ((_a = node.nodes) === null || _a === void 0 ? void 0 : _a.length) { | ||
const isNth = node.type === `pseudo_class` && nth_parser_1.NthParser.isNthPseudoClass(node.value); | ||
const nthExpr = isNth ? stringifyNode(node.nodes.shift()) : ``; | ||
return `(${nthExpr}${stringifySelectors(node.nodes)})`; | ||
if (node.type === `pseudo_class` && | ||
nth_parser_1.NthParser.isNthPseudoClass(node.value)) { | ||
const [nthNode, ...selectors] = node.nodes; | ||
return `(${stringifyNode(nthNode)}${stringifySelectors(selectors)})`; | ||
} | ||
else { | ||
return `(${stringifySelectors(node.nodes)})`; | ||
} | ||
} | ||
@@ -61,3 +64,3 @@ else { | ||
} | ||
function stringifyNamespace({ namespace }) { | ||
function stringifyNamespace({ namespace, }) { | ||
let ns = ``; | ||
@@ -64,0 +67,0 @@ if (namespace) { |
import type { Token, Descriptors } from "@tokey/core"; | ||
declare type Delimiters = "[" | "]" | "(" | ")" | "," | "*" | "|" | ":" | "." | "#" | ">" | "~" | "+" | "{" | "}" | "&"; | ||
export declare type CSSSelectorToken = Token<Descriptors | Delimiters>; | ||
export declare function tokenizeSelector(source: string): CSSSelectorToken[]; | ||
export declare function tokenizeSelector(source: string, options?: { | ||
offset?: number; | ||
}): CSSSelectorToken[]; | ||
export {}; | ||
//# sourceMappingURL=tokenizer.d.ts.map |
@@ -5,3 +5,3 @@ "use strict"; | ||
const core_1 = require("@tokey/core"); | ||
function tokenizeSelector(source) { | ||
function tokenizeSelector(source, options = {}) { | ||
const parseLineComments = false; // why would that be a choice? | ||
@@ -21,2 +21,3 @@ return core_1.tokenize(source, { | ||
getUnclosedComment: core_1.getUnclosedComment, | ||
offset: options.offset, | ||
}); | ||
@@ -39,4 +40,5 @@ } | ||
char === "+" || | ||
char === "{" || | ||
char === "}" || | ||
char === "&"); | ||
//# sourceMappingURL=tokenizer.js.map |
{ | ||
"name": "@tokey/css-selector-parser", | ||
"description": "selector parser for css", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"main": "dist/index.js", | ||
@@ -11,3 +11,3 @@ "types": "dist/index.d.ts", | ||
"dependencies": { | ||
"@tokey/core": "^1.1.0" | ||
"@tokey/core": "^1.2.0" | ||
}, | ||
@@ -31,3 +31,4 @@ "keywords": [ | ||
"repository": "https://github.com/wixplosives/tokey/packages/css-selector-parser", | ||
"prettier": {} | ||
"prettier": {}, | ||
"sideEffects": false | ||
} |
@@ -40,3 +40,3 @@ # @tokey/css-selector-parser | ||
`parseCssSelector` - accepts a selector list string and returns an AST representation of that | ||
`parseCssSelector` - accepts a selector list string and returns an AST representation of that. | ||
@@ -85,2 +85,10 @@ ```js | ||
#### parsing config | ||
`offset` - start AST offset from a given point, defaults to 0: | ||
```js | ||
parseCssSelector(`ul`, { offset: 105 }); | ||
``` | ||
### Stringify | ||
@@ -134,3 +142,3 @@ | ||
> | ||
> for example: `./*what?!*/a`. | ||
> For example: `./*what?!*/a`. | ||
@@ -159,3 +167,3 @@ #### control traversal | ||
`visitList/ignoreList` limit the types of AST calls to the visit function, but does not prevent traversal of nested nodes. | ||
`visitList/ignoreList` - limits the types of AST calls to the visit function, but does not prevent traversal of nested nodes. | ||
@@ -186,3 +194,3 @@ ```js | ||
The parser supports native `pseudo-classes/pseudo-elements` functional selectors, but also parses other selectors in the same way. So `type`/`id`/`class`/`attribute`/`nesting` selectors are all parsed with `nodes` in case they are followed by a pair of parentheses (e.g. `element(nodeA, nodeB)`). **This syntax is not valid CSS and should be handled before served to a CSS consumer** | ||
The parser supports native `pseudo-classes/pseudo-elements` functional selectors, but also parses other selectors in the same way. So `type`/`id`/`class`/`attribute`/`nesting` selectors are all parsed with `nodes` in case they are followed by a pair of parentheses (e.g. `element(nodeA, nodeB)`). **This syntax is not valid CSS and should be handled before served to a CSS consumer.** | ||
@@ -189,0 +197,0 @@ ### Nth selector |
@@ -0,1 +1,2 @@ | ||
import type { Immutable } from "./types"; | ||
import type { Token } from "@tokey/core"; | ||
@@ -9,4 +10,7 @@ | ||
export type NthSelectorList = [Nth, ...SelectorList]; | ||
// ToDo: try type NthSelectorList only for the specific set of types | ||
export interface PseudoClass extends Token<"pseudo_class"> { | ||
nodes?: Selector[] | [Nth, ...SelectorList]; | ||
nodes?: SelectorList | NthSelectorList; | ||
colonComments: Comment[]; | ||
@@ -44,3 +48,3 @@ } | ||
export interface Element extends Token<"element"> { | ||
export interface Type extends Token<"type"> { | ||
namespace?: Namespace; | ||
@@ -50,3 +54,3 @@ nodes?: SelectorList; | ||
export interface Star extends Token<"star"> { | ||
export interface Universal extends Token<"universal"> { | ||
namespace?: Namespace; | ||
@@ -91,6 +95,6 @@ nodes?: SelectorList; | ||
export type NamespacedNodes = Element | Star; | ||
export type NamespacedNode = Type | Universal; | ||
export type Containers = | ||
| NamespacedNodes | ||
export type FunctionalSelector = | ||
| NamespacedNode | ||
| Attribute | ||
@@ -104,3 +108,3 @@ | Id | ||
export type SelectorNode = | ||
| Containers | ||
| FunctionalSelector | ||
| Selector | ||
@@ -117,1 +121,28 @@ | Combinator | ||
export type SelectorList = Selector[]; | ||
// immutable ast | ||
export type ImmutableSelector = Immutable<Selector>; | ||
export type ImmutableSelectorList = Immutable<SelectorList>; | ||
export type ImmutableNthSelectorList = Immutable<NthSelectorList>; | ||
export type ImmutableSelectorNode = Immutable<SelectorNode>; | ||
export type ImmutableFunctionalSelector = Immutable<FunctionalSelector>; | ||
export type ImmutableNamespacedNode = Immutable<NamespacedNode>; | ||
export type ImmutableUniversal = Immutable<Universal>; | ||
export type ImmutableClass = Immutable<Class>; | ||
export type ImmutableId = Immutable<Id>; | ||
export type ImmutableType = Immutable<Type>; | ||
export type ImmutableCombinator = Immutable<Combinator>; | ||
export type ImmutableAttribute = Immutable<Attribute>; | ||
export type ImmutablePseudoClass = Immutable<PseudoClass>; | ||
export type ImmutablePseudoElement = Immutable<PseudoElement>; | ||
export type ImmutableComment = Immutable<Comment>; | ||
export type ImmutableNesting = Immutable<Nesting>; | ||
export type ImmutableInvalid = Immutable<Invalid>; | ||
export type ImmutableNth = Immutable<Nth>; | ||
export type ImmutableNthStep = Immutable<NthStep>; | ||
export type ImmutableNthDash = Immutable<NthDash>; | ||
export type ImmutableNthOffset = Immutable<NthOffset>; | ||
export type ImmutableNthOf = Immutable<NthOf>; |
@@ -1,2 +0,2 @@ | ||
import type { SelectorNode, SelectorList, Containers } from "./ast-types"; | ||
import type { SelectorNode, SelectorList, FunctionalSelector } from "./ast-types"; | ||
@@ -127,5 +127,5 @@ export interface WalkOptions { | ||
type ContainerWithNodes = Containers & { nodes: SelectorNode[] }; | ||
type ContainerWithNodes = FunctionalSelector & { nodes: SelectorNode[] }; | ||
function isWithNodes(node: any): node is ContainerWithNodes { | ||
return node && `nodes` in node; | ||
} |
@@ -7,3 +7,3 @@ import type { CSSSelectorToken } from "./tokenizer"; | ||
Nth, | ||
NamespacedNodes, | ||
NamespacedNode, | ||
SelectorList, | ||
@@ -89,4 +89,4 @@ SelectorNode, | ||
} | ||
export function isNamespacedAst(token: SelectorNode): token is NamespacedNodes { | ||
return token.type === `star` || token.type === `element`; | ||
export function isNamespacedAst(token: SelectorNode): token is NamespacedNode { | ||
return token.type === `universal` || token.type === `type`; | ||
} | ||
@@ -93,0 +93,0 @@ |
export { parseCssSelector } from "./selector-parser"; | ||
export type { ParseConfig } from "./selector-parser"; | ||
export * from "./ast-types"; | ||
@@ -3,0 +4,0 @@ export { stringifySelectorAst } from "./stringify"; |
@@ -7,3 +7,3 @@ import { tokenizeSelector, CSSSelectorToken } from "./tokenizer"; | ||
Comment, | ||
NamespacedNodes, | ||
NamespacedNode, | ||
Selector, | ||
@@ -26,6 +26,10 @@ SelectorList, | ||
export function parseCssSelector(source: string) { | ||
return parseTokens(source, tokenizeSelector(source)); | ||
export interface ParseConfig { | ||
offset: number; | ||
} | ||
export function parseCssSelector(source: string, options: Partial<ParseConfig> = {}) { | ||
return parseTokens(source, tokenizeSelector(source, options)); | ||
} | ||
function parseTokens(source: string, tokens: CSSSelectorToken[]): SelectorList { | ||
@@ -201,3 +205,3 @@ return new Seeker(tokens).run<SelectorList>(handleToken, [], source); | ||
ast.push({ | ||
type: "element", | ||
type: "type", | ||
value: token.value, | ||
@@ -217,3 +221,3 @@ start: token.start, | ||
ast.push({ | ||
type: "star", | ||
type: "universal", | ||
value: "*", | ||
@@ -225,3 +229,3 @@ start: token.start, | ||
// search backwards compatible namespace in ast | ||
let prevAst: NamespacedNodes | undefined; | ||
let prevAst: NamespacedNode | undefined; | ||
let prevInvalidAst: SelectorNode | undefined; | ||
@@ -272,3 +276,3 @@ const beforeComments: Comment[] = []; | ||
const validTarget = !!target; | ||
const type = target?.type === `*` ? `star` : `element`; | ||
const type = target?.type === `*` ? `universal` : `type`; | ||
let invalid: NonNullable<Namespace["invalid"]> = ``; | ||
@@ -288,3 +292,3 @@ // remove before/after pipe comments | ||
// create new ast or modify the prev | ||
const nsAst: NamespacedNodes = | ||
const nsAst: NamespacedNode = | ||
prevAst || | ||
@@ -296,3 +300,3 @@ ({ | ||
end: target?.end || token.end, | ||
} as NamespacedNodes); | ||
} as NamespacedNode); | ||
nsAst.type = type; | ||
@@ -299,0 +303,0 @@ nsAst.namespace = { |
import { NthParser } from "./nth-parser"; | ||
import type { | ||
Id, | ||
Attribute, | ||
Class, | ||
Combinator, | ||
Comment, | ||
Containers, | ||
Element, | ||
Invalid, | ||
NamespacedNodes, | ||
Nth, | ||
NthDash, | ||
NthOf, | ||
NthOffset, | ||
NthStep, | ||
PseudoClass, | ||
PseudoElement, | ||
Selector, | ||
SelectorList, | ||
SelectorNode, | ||
Star, | ||
Nesting, | ||
ImmutableId, | ||
ImmutableAttribute, | ||
ImmutableClass, | ||
ImmutableCombinator, | ||
ImmutableComment, | ||
ImmutableType, | ||
ImmutableInvalid, | ||
ImmutableNth, | ||
ImmutableNthDash, | ||
ImmutableNthOf, | ||
ImmutableNthOffset, | ||
ImmutableNthStep, | ||
ImmutablePseudoClass, | ||
ImmutablePseudoElement, | ||
ImmutableSelector, | ||
ImmutableUniversal, | ||
ImmutableNesting, | ||
ImmutableSelectorNode, | ||
ImmutableSelectorList, | ||
ImmutableNthSelectorList, | ||
ImmutableFunctionalSelector, | ||
ImmutableNamespacedNode, | ||
} from "./ast-types"; | ||
export function stringifySelectorAst( | ||
value: SelectorNode | SelectorList | [Nth, ...SelectorList] | ||
value: | ||
| ImmutableSelectorNode | ||
| ImmutableSelectorList | ||
| ImmutableNthSelectorList | ||
): string { | ||
return Array.isArray(value) | ||
? stringifySelectors(value) | ||
: stringifyNode(value); | ||
return "length" in value ? stringifySelectors(value) : stringifyNode(value); | ||
} | ||
type R = { [K in SelectorNode as K["type"]]: (node: K) => string }; | ||
type Printers = { | ||
[K in ImmutableSelectorNode as K["type"]]: (node: K) => string; | ||
}; | ||
const printers: R = { | ||
id: (node: Id) => `#${node.value}${stringifyNested(node)}`, | ||
class: (node: Class) => | ||
const printers: Printers = { | ||
id: (node: ImmutableId) => `#${node.value}${stringifyNested(node)}`, | ||
class: (node: ImmutableClass) => | ||
`.${node.dotComments.map(stringifyNode).join("")}${ | ||
node.value | ||
}${stringifyNested(node)}`, | ||
element: (node: Element) => | ||
type: (node: ImmutableType) => | ||
`${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
combinator: (node: Combinator) => `${node.before}${node.value}${node.after}`, | ||
attribute: (node: Attribute) => `[${node.value}]${stringifyNested(node)}`, | ||
pseudo_class: (node: PseudoClass) => | ||
combinator: (node: ImmutableCombinator) => | ||
`${node.before}${node.value}${node.after}`, | ||
attribute: (node: ImmutableAttribute) => | ||
`[${node.value}]${stringifyNested(node)}`, | ||
pseudo_class: (node: ImmutablePseudoClass) => | ||
`:${node.colonComments.map(stringifyNode).join("")}${ | ||
node.value | ||
}${stringifyNested(node)}`, | ||
pseudo_element: (node: PseudoElement) => | ||
pseudo_element: (node: ImmutablePseudoElement) => | ||
`:${node.colonComments.first | ||
@@ -56,23 +62,30 @@ .map(stringifyNode) | ||
}${stringifyNested(node)}`, | ||
comment: ({ before, value, after }: Comment) => `${before}${value}${after}`, | ||
star: (node: Star) => | ||
comment: ({ before, value, after }: ImmutableComment) => | ||
`${before}${value}${after}`, | ||
universal: (node: ImmutableUniversal) => | ||
`${stringifyNamespace(node)}${node.value}${stringifyNested(node)}`, | ||
nesting: (node: Nesting) => `${node.value}${stringifyNested(node)}`, | ||
selector: (node: Selector) => | ||
nesting: (node: ImmutableNesting) => | ||
`${node.value}${stringifyNested(node)}`, | ||
selector: (node: ImmutableSelector) => | ||
`${node.before}${node.nodes.map(stringifyNode).join("")}${node.after}`, | ||
invalid: (node: Invalid) => node.value, | ||
nth: (node: Nth) => | ||
invalid: (node: ImmutableInvalid) => node.value, | ||
nth: (node: ImmutableNth) => | ||
`${node.before}${node.nodes.map(stringifyNode).join("")}${node.after}`, | ||
nth_step: ({ before, value, after }: NthStep) => `${before}${value}${after}`, | ||
nth_dash: ({ before, value, after }: NthDash) => `${before}${value}${after}`, | ||
nth_offset: ({ before, value, after }: NthOffset) => | ||
nth_step: ({ before, value, after }: ImmutableNthStep) => | ||
`${before}${value}${after}`, | ||
nth_of: ({ before, value, after }: NthOf) => `${before}${value}${after}`, | ||
nth_dash: ({ before, value, after }: ImmutableNthDash) => | ||
`${before}${value}${after}`, | ||
nth_offset: ({ before, value, after }: ImmutableNthOffset) => | ||
`${before}${value}${after}`, | ||
nth_of: ({ before, value, after }: ImmutableNthOf) => | ||
`${before}${value}${after}`, | ||
}; | ||
function stringifyNode(node: SelectorNode): string { | ||
function stringifyNode(node: ImmutableSelectorNode): string { | ||
return printers[node.type]?.(node as never) ?? ""; | ||
} | ||
function stringifySelectors(selectors: SelectorList | [Nth, ...SelectorList]) { | ||
function stringifySelectors( | ||
selectors: ImmutableSelectorList | ImmutableNthSelectorList | ||
) { | ||
const result: string[] = []; | ||
@@ -85,9 +98,14 @@ for (const node of selectors) { | ||
function stringifyNested(node: Containers): string { | ||
function stringifyNested(node: ImmutableFunctionalSelector): string { | ||
if ("nodes" in node) { | ||
if (node.nodes?.length) { | ||
const isNth = | ||
node.type === `pseudo_class` && NthParser.isNthPseudoClass(node.value); | ||
const nthExpr = isNth ? stringifyNode(node.nodes.shift()!) : ``; | ||
return `(${nthExpr}${stringifySelectors(node.nodes)})`; | ||
if ( | ||
node.type === `pseudo_class` && | ||
NthParser.isNthPseudoClass(node.value) | ||
) { | ||
const [nthNode, ...selectors] = node.nodes; | ||
return `(${stringifyNode(nthNode)}${stringifySelectors(selectors)})`; | ||
} else { | ||
return `(${stringifySelectors(node.nodes)})`; | ||
} | ||
} else { | ||
@@ -99,3 +117,6 @@ return `()`; | ||
} | ||
function stringifyNamespace({ namespace }: NamespacedNodes): string { | ||
function stringifyNamespace({ | ||
namespace, | ||
}: ImmutableNamespacedNode): string { | ||
let ns = ``; | ||
@@ -102,0 +123,0 @@ if (namespace) { |
@@ -33,3 +33,6 @@ import { | ||
export function tokenizeSelector(source: string) { | ||
export function tokenizeSelector( | ||
source: string, | ||
options: { offset?: number } = {} | ||
) { | ||
const parseLineComments = false; // why would that be a choice? | ||
@@ -49,2 +52,3 @@ return tokenize<CSSSelectorToken>(source, { | ||
getUnclosedComment, | ||
offset: options.offset, | ||
}); | ||
@@ -68,3 +72,4 @@ } | ||
char === "+" || | ||
char === "{" || | ||
char === "}" || | ||
char === "&"); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
129756
47
2496
194
Updated@tokey/core@^1.2.0