-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
478 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports = { | ||
extends: ['@wyw-in-js/eslint-config/library'], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
const config = require('@wyw-in-js/babel-config'); | ||
|
||
module.exports = config; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
testMatch: ['**/__tests__/**/*.test.ts'], | ||
transform: { | ||
'^.+\\.ts$': [ | ||
'ts-jest', | ||
{ | ||
tsconfig: 'tsconfig.spec.json', | ||
}, | ||
], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
{ | ||
"name": "@wyw-in-js/object-syntax", | ||
"private": true, | ||
"version": "0.0.1", | ||
"dependencies": { | ||
"@griffel/core": "1.5.0", | ||
"@wyw-in-js/processor-utils": "workspace:*" | ||
}, | ||
"devDependencies": { | ||
"@babel/core": "^7.23.0", | ||
"@babel/traverse": "^7.23.0", | ||
"@babel/types": "^7.23.0", | ||
"@types/babel__core": "^7.20.2", | ||
"@types/babel__traverse": "^7.20.2", | ||
"@types/node": "^16.18.55", | ||
"@wyw-in-js/babel-config": "workspace:*", | ||
"@wyw-in-js/eslint-config": "workspace:*", | ||
"@wyw-in-js/shared": "workspace:*", | ||
"@wyw-in-js/transform": "workspace:*", | ||
"@wyw-in-js/ts-config": "workspace:*", | ||
"dedent": "^1.5.1" | ||
}, | ||
"engines": { | ||
"node": ">=16.0.0" | ||
}, | ||
"exports": { | ||
"./package.json": "./package.json", | ||
".": { | ||
"types": "./types/index.d.ts", | ||
"import": "./esm/index.js", | ||
"default": "./lib/index.js" | ||
}, | ||
"./*": { | ||
"types": "./types/*.d.ts", | ||
"import": "./esm/*.js", | ||
"default": "./lib/*.js" | ||
} | ||
}, | ||
"files": [ | ||
"esm/", | ||
"lib/", | ||
"processors/", | ||
"types/" | ||
], | ||
"license": "MIT", | ||
"linaria": { | ||
"tags": { | ||
"makeStyles": "./lib/processors/makeStyles.js" | ||
} | ||
}, | ||
"main": "lib/index.js", | ||
"module": "esm/index.js", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"scripts": { | ||
"build:esm": "babel src --out-dir esm --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start", | ||
"build:lib": "cross-env NODE_ENV=legacy babel src --out-dir lib --extensions '.js,.jsx,.ts,.tsx' --source-maps --delete-dir-on-start", | ||
"build:types": "tsc", | ||
"lint": "eslint --ext .js,.ts .", | ||
"test": "jest --config ./jest.config.js --rootDir src" | ||
}, | ||
"types": "types/index.d.ts" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true, | ||
}); | ||
|
||
exports.default = require('../lib/processors/makeStyles').default; |
168 changes: 168 additions & 0 deletions
168
examples/object-syntax/src/__tests__/getTagProcessor.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import { join } from 'path'; | ||
|
||
import { parseSync } from '@babel/core'; | ||
import traverse from '@babel/traverse'; | ||
import dedent from 'dedent'; | ||
|
||
import type { BaseProcessor } from '@wyw-in-js/processor-utils'; | ||
import { getTagProcessor } from '@wyw-in-js/transform'; | ||
|
||
interface IRunOptions { | ||
ts?: boolean; | ||
} | ||
|
||
const run = (code: string, options: IRunOptions = {}): BaseProcessor | null => { | ||
const opts = { | ||
filename: join(__dirname, options.ts ? 'test.ts' : 'test.js'), | ||
root: '.', | ||
code: true, | ||
ast: true, | ||
presets: options.ts ? ['@babel/preset-typescript'] : [], | ||
}; | ||
const rootNode = parseSync(code, opts)!; | ||
let result: BaseProcessor | null = null; | ||
traverse(rootNode, { | ||
Identifier(path) { | ||
const processor = getTagProcessor(path, opts, { | ||
displayName: true, | ||
evaluate: true, | ||
}); | ||
|
||
if (processor) { | ||
result = processor; | ||
} | ||
}, | ||
}); | ||
|
||
return result; | ||
}; | ||
|
||
function tagToString(processor: BaseProcessor | null): string | undefined { | ||
if (!processor) return undefined; | ||
return processor.toString(); | ||
} | ||
|
||
describe('getTagProcessor', () => { | ||
it('should find correct import', () => { | ||
const result = run( | ||
dedent` | ||
import { makeStyles } from "@wyw-in-js/object-syntax"; | ||
export const Square = makeStyles({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('makeStyles(…)'); | ||
expect(result?.tagSource).toEqual({ | ||
imported: 'makeStyles', | ||
source: '@wyw-in-js/object-syntax', | ||
}); | ||
}); | ||
|
||
it('renamed({})', () => { | ||
const result = run( | ||
dedent` | ||
import { makeStyles as renamed } from "@wyw-in-js/object-syntax"; | ||
export const Square = renamed({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('renamed(…)'); | ||
expect(result?.tagSource).toEqual({ | ||
imported: 'makeStyles', | ||
source: '@wyw-in-js/object-syntax', | ||
}); | ||
}); | ||
|
||
it('(0, objectSyntax.makeStyles)()', () => { | ||
const result = run( | ||
dedent` | ||
const objectSyntax = require("@wyw-in-js/object-syntax"); | ||
export const Square = (0, objectSyntax.makeStyles)({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('objectSyntax.makeStyles(…)'); | ||
expect(result?.tagSource).toEqual({ | ||
imported: 'makeStyles', | ||
source: '@wyw-in-js/object-syntax', | ||
}); | ||
}); | ||
|
||
it('imported from file', () => { | ||
const result = run( | ||
dedent` | ||
import { makeStyles } from '../makeStyles'; | ||
export const square = makeStyles({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('makeStyles(…)'); | ||
expect(result?.tagSource).toEqual({ | ||
imported: 'makeStyles', | ||
source: '../makeStyles', | ||
}); | ||
}); | ||
|
||
it('require and access with prop', () => { | ||
const result = run( | ||
dedent` | ||
const renamed = require('@wyw-in-js/object-syntax').makeStyles; | ||
export const Square = renamed({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('renamed(…)'); | ||
}); | ||
|
||
it('require and destructing', () => { | ||
const result = run( | ||
dedent` | ||
const { makeStyles } = require('@wyw-in-js/object-syntax'); | ||
export const Square = makeStyles({}); | ||
` | ||
); | ||
|
||
expect(tagToString(result)).toBe('makeStyles(…)'); | ||
}); | ||
|
||
describe('invalid usage', () => { | ||
it('makeStyles``', () => { | ||
const runner = () => | ||
run( | ||
dedent`import { makeStyles } from "@wyw-in-js/object-syntax"; export const square = makeStyles\`\`;` | ||
); | ||
|
||
expect(runner).toThrow('Invalid usage of `makeStyles` function'); | ||
}); | ||
|
||
it('makeStyles.div``', () => { | ||
const runner = () => | ||
run( | ||
dedent`import { makeStyles } from "@wyw-in-js/object-syntax"; export const square = makeStyles.div\`\`;` | ||
); | ||
|
||
expect(runner).toThrow('Invalid usage of `makeStyles` function'); | ||
}); | ||
|
||
it('makeStyles("div")``', () => { | ||
const runner = () => | ||
run( | ||
dedent`import { makeStyles } from "@wyw-in-js/object-syntax"; export const square = makeStyles("div")\`\`;` | ||
); | ||
|
||
expect(runner).toThrow('Invalid usage of `makeStyles` function'); | ||
}); | ||
|
||
it('do not throw if css is not a call', () => { | ||
const runner = () => | ||
run(dedent`export { makeStyles } from "@wyw-in-js/object-syntax";`); | ||
|
||
expect(runner).not.toThrow(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { makeStyles } from './makeStyles'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export function makeStyles<Slots extends string | number>( | ||
// eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
stylesBySlots: Record<Slots, unknown> | ||
): () => Record<Slots, string> { | ||
throw new Error('Cannot be called in runtime'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* eslint-disable class-methods-use-this */ | ||
import type { Expression } from '@babel/types'; | ||
import { resolveStyleRulesForSlots } from '@griffel/core'; | ||
import type { | ||
StylesBySlots, | ||
CSSClassesMapBySlot, | ||
CSSRulesByBucket, | ||
} from '@griffel/core/types'; | ||
|
||
import type { | ||
ValueCache, | ||
Params, | ||
TailProcessorParams, | ||
} from '@wyw-in-js/processor-utils'; | ||
import { BaseProcessor, validateParams } from '@wyw-in-js/processor-utils'; | ||
|
||
export default class MakeStylesProcessor extends BaseProcessor { | ||
#cssClassMap: CSSClassesMapBySlot<string> | undefined; | ||
|
||
#cssRulesByBucket: CSSRulesByBucket | undefined; | ||
|
||
readonly #slotsExpName: string | number | boolean | null; | ||
|
||
public constructor(params: Params, ...args: TailProcessorParams) { | ||
validateParams( | ||
params, | ||
['callee', 'call'], | ||
'Invalid usage of `makeStyles` function' | ||
); | ||
const [callee, callParam] = params; | ||
|
||
super([callee], ...args); | ||
|
||
const { ex } = callParam[1]; | ||
if (ex.type === 'Identifier') { | ||
this.dependencies.push(callParam[1]); | ||
this.#slotsExpName = ex.name; | ||
} else if (ex.type === 'NullLiteral') { | ||
this.#slotsExpName = null; | ||
} else { | ||
this.#slotsExpName = ex.value; | ||
} | ||
} | ||
|
||
public override get asSelector(): string { | ||
throw new Error('The result of makeStyles cannot be used as a selector.'); | ||
} | ||
|
||
public override get value(): Expression { | ||
return this.astService.nullLiteral(); | ||
} | ||
|
||
public override build(valueCache: ValueCache) { | ||
const slots = valueCache.get(this.#slotsExpName) as StylesBySlots<string>; | ||
[this.#cssClassMap, this.#cssRulesByBucket] = | ||
resolveStyleRulesForSlots(slots); | ||
} | ||
|
||
public override doEvaltimeReplacement(): void { | ||
this.replacer(this.value, false); | ||
} | ||
|
||
public override doRuntimeReplacement(): void { | ||
if (!this.#cssClassMap || !this.#cssRulesByBucket) { | ||
throw new Error( | ||
'Styles are not extracted yet. Please call `build` first.' | ||
); | ||
} | ||
|
||
const t = this.astService; | ||
|
||
const importedStyles = t.addNamedImport('__styles', '@griffel/react'); | ||
|
||
const cssClassMap = t.objectExpression( | ||
Object.entries(this.#cssClassMap).map(([slot, classesMap]) => { | ||
return t.objectProperty( | ||
t.identifier(slot), | ||
t.objectExpression( | ||
Object.entries(classesMap).map(([className, classValue]) => | ||
t.objectProperty( | ||
t.identifier(className), | ||
Array.isArray(classValue) | ||
? t.arrayExpression(classValue.map((i) => t.stringLiteral(i))) | ||
: t.stringLiteral(classValue) | ||
) | ||
) | ||
) | ||
); | ||
}) | ||
); | ||
|
||
const cssRulesByBucket = t.objectExpression( | ||
Object.entries(this.#cssRulesByBucket).map(([bucket, rules]) => { | ||
return t.objectProperty( | ||
t.identifier(bucket), | ||
t.arrayExpression( | ||
// FIXME: rule can be [string, Record<string, unknown>] | ||
rules.map((rule) => t.stringLiteral(rule as string)) | ||
) | ||
); | ||
}) | ||
); | ||
|
||
const stylesCall = t.callExpression(importedStyles, [ | ||
cssClassMap, | ||
cssRulesByBucket, | ||
]); | ||
this.replacer(stylesCall, true); | ||
} | ||
|
||
public override toString(): string { | ||
return `${super.toString()}(…)`; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"exclude": [] | ||
} |
Oops, something went wrong.