aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/parser.ts39
-rw-r--r--tests/parser.spec.ts83
2 files changed, 94 insertions, 28 deletions
diff --git a/src/parser.ts b/src/parser.ts
index a6c3928..732e32a 100644
--- a/src/parser.ts
+++ b/src/parser.ts
@@ -3,6 +3,12 @@ import * as P from './utils/parser-comb'
export type CSSUnit = '' | 's' | 'ms'
+export interface Selector {
+ tag: string | undefined
+ id: string
+ selectors: Array<SelectorComp>
+}
+
export type SelectorComp = Enum<{
ClassName: string
Attr: readonly [string, string]
@@ -17,11 +23,7 @@ export type Expr = Enum<{
LiteralNumber: { value: number; unit: CSSUnit }
Pair: { key: string; value: Expr }
- Selector: {
- tag: string | undefined
- id: string
- selectors: Array<SelectorComp>
- }
+ Selector: Selector
}>
export const Expr = constructors<Expr>()
@@ -100,16 +102,35 @@ const exprParser: P.Parser<Expr> = P.or([
stringLiteralExprParser,
numberExprParser,
callExprParser,
- selectorExprParser,
- identifierExprParser,
pairExprParser,
varIdentifierExprParser,
+ selectorExprParser,
+ identifierExprParser,
])
-const multiExprParser = P.many1(exprParser)
+const declarationParser = P.or([callExprParser, selectorExprParser])
+
+const multiDeclarationParser = P.sepBy(declarationParser, whitespace)
+
+export const parseDeclarations = (input: string) =>
+ match<Array<Expr>, P.ParseResult<Array<Expr>>>(
+ multiDeclarationParser(input),
+ {
+ Ok: ({ value, input }) => {
+ if (input) {
+ console.error(`Declaration stopped parsing at: "${input}"`)
+ }
+ return value
+ },
+ Err: ({ error }) => {
+ console.error(error)
+ return []
+ },
+ },
+ )
export const parse = (input: string): Array<Expr> => {
- const res = multiExprParser(input.trim())
+ const res = P.many1(exprParser)(input.trim())
return match(res, {
Ok: ({ value, input }) => {
if (input) {
diff --git a/tests/parser.spec.ts b/tests/parser.spec.ts
index b03e073..825200e 100644
--- a/tests/parser.spec.ts
+++ b/tests/parser.spec.ts
@@ -1,4 +1,4 @@
-import { Expr, SelectorComp, parse } from '../src/parser'
+import { Expr, SelectorComp, parse, parseDeclarations } from '../src/parser'
describe('parser', () => {
it('should parse function call', () => {
@@ -155,24 +155,69 @@ describe('parser', () => {
])
})
- it('should parse complex selectors', () => {
- expect(parse(`button#something.my-class[hello=world]`)).toEqual([
- Expr.Selector({
- tag: 'button',
- id: 'something',
- selectors: [
- SelectorComp.ClassName('my-class'),
- SelectorComp.Attr(['hello', 'world']),
- ],
- }),
- ])
+ describe('parseDeclarations', () => {
+ it('should parse complex selectors', () => {
+ expect(
+ parseDeclarations(`button#something.my-class[hello=world]`),
+ ).toEqual([
+ Expr.Selector({
+ tag: 'button',
+ id: 'something',
+ selectors: [
+ SelectorComp.ClassName('my-class'),
+ SelectorComp.Attr(['hello', 'world']),
+ ],
+ }),
+ ])
- expect(parse(`#something[data-testid="hello world"]`)).toEqual([
- Expr.Selector({
- tag: undefined,
- id: 'something',
- selectors: [SelectorComp.Attr(['data-testid', 'hello world'])],
- }),
- ])
+ expect(
+ parseDeclarations(
+ `#something[data-testid="hello world"].wow input#password[type=password][placeholder="Password: ***"]`,
+ ),
+ ).toEqual([
+ Expr.Selector({
+ tag: undefined,
+ id: 'something',
+ selectors: [
+ SelectorComp.Attr(['data-testid', 'hello world']),
+ SelectorComp.ClassName('wow'),
+ ],
+ }),
+ Expr.Selector({
+ tag: 'input',
+ id: 'password',
+ selectors: [
+ SelectorComp.Attr(['type', 'password']),
+ SelectorComp.Attr(['placeholder', 'Password: ***']),
+ ],
+ }),
+ ])
+ })
+
+ it('should parse declarations', () => {
+ expect(
+ parseDeclarations(
+ `instance(button#something, map(--text: "wow", --color: red))`,
+ ),
+ ).toEqual([
+ Expr.Call({
+ name: 'instance',
+ args: [
+ Expr.Selector({
+ tag: 'button',
+ id: 'something',
+ selectors: [],
+ }),
+ Expr.Call({
+ name: 'map',
+ args: [
+ Expr.Pair({ key: '--text', value: Expr.LiteralString('wow') }),
+ Expr.Pair({ key: '--color', value: Expr.Identifier('red') }),
+ ],
+ }),
+ ],
+ }),
+ ])
+ })
})
})