Skip to content

Commit

Permalink
refactor: improve runtime alias lookups (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonambas authored Apr 6, 2024
1 parent 88b5a5f commit 25af4ac
Show file tree
Hide file tree
Showing 16 changed files with 288 additions and 220 deletions.
48 changes: 48 additions & 0 deletions src/__tests__/codegen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { CodegenPrepareHookArgs } from '@pandacss/types';
import { codegen } from '../codegen';
import { createContext } from '../context';

const context = createContext({
foo: { 100: { value: '#fff' }, 200: { value: { base: '#000' } } },
bar: { 100: 'red', 200: 'blue' },
});

const args: CodegenPrepareHookArgs = {
artifacts: [
{
id: 'css-fn',
files: [
{ file: 'css.mjs', code: '' },
{ file: 'css.d.ts', code: '' },
],
},
],
changed: [],
};

describe('codegen', () => {
it('generates ct runtime code', () => {
const result = codegen(args, context) as any[];
expect(result[0].files[0]).toMatchInlineSnapshot(`
{
"code": "
const pluginCtMap = new Map(JSON.parse('[["foo.100","#fff"],["foo.200",{"base":"#000"}],["bar.100","red"],["bar.200","blue"]]'));
export const ct = (path) => {
if (!pluginCtMap.has(path)) return 'panda-plugin-ct-alias-not-found';
return pluginCtMap.get(path);
};
",
"file": "css.mjs",
}
`);

expect(result[0].files[1]).toMatchInlineSnapshot(`
{
"code": "
export const ct: (alias: "foo.100" | "foo.200" | "bar.100" | "bar.200") => string;",
"file": "css.d.ts",
}
`);
});
});
72 changes: 0 additions & 72 deletions src/__tests__/get.test.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { pluginComponentTokens } from '..';

describe('pluginComponentTokens', () => {
it('returns a PandaPlugin', () => {
expect(pluginComponentTokens).toBeTypeOf('function');
expect(pluginComponentTokens({}).name).toBeDefined();
expect(pluginComponentTokens({}).hooks).toBeDefined();
});
});
76 changes: 76 additions & 0 deletions src/__tests__/map.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { get, makeMap, makePaths, mapTemplate } from '../map';

const tokens = {
foo: { 100: { value: '#fff' }, 200: { value: { base: '#000' } } },
bar: { 100: 'red', 200: 'blue' },
};

describe('get', () => {
it('gets a string', () => {
expect(get(tokens, 'bar.100')).toBe('red');
});

it('gets a value object', () => {
expect(get(tokens, 'foo.200')).toMatchInlineSnapshot(
`
{
"base": "#000",
}
`,
);
});

it('gets a value string', () => {
expect(get(tokens, 'foo.100')).toMatchInlineSnapshot(`"#fff"`);
});

it('gets an undefined token', () => {
expect(get(tokens, 'nope.nope')).toBeUndefined();
expect(get(tokens, 'foo.baz')).toBeUndefined();
});
});

describe('makePaths', () => {
it('makes paths', () => {
expect(makePaths(tokens)).toMatchInlineSnapshot(`
[
"foo.100",
"foo.200",
"bar.100",
"bar.200",
]
`);
});
});

describe('mapTemplate', () => {
it('serializes a Map', () => {
const map = new Map<string, any>([
['foo.100', '#fff'],
['foo.200', { base: '#000' }],
]);

expect(mapTemplate(map)).toMatchInlineSnapshot(
`
"
const pluginCtMap = new Map(JSON.parse('[["foo.100","#fff"],["foo.200",{"base":"#000"}]]'));
"
`,
);
});
});

describe('makeMap', () => {
it('makes a map', () => {
expect(makeMap(tokens)).toMatchInlineSnapshot(`
Map {
"foo.100" => "#fff",
"foo.200" => {
"base": "#000",
},
"bar.100" => "red",
"bar.200" => "blue",
}
`);
});
});
37 changes: 37 additions & 0 deletions src/__tests__/parser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { parser } from '../parser';
import { createContext } from '../context';

const context = createContext({
foo: { 100: { value: '#fff' }, 200: { value: { base: '#000' } } },
bar: { 100: 'red', 200: 'blue' },
});

describe('parser', () => {
it('parses', () => {
const res = parser(
{
configure: () => {},
filePath: 'test.tsx',
content: `<div className={css({ bg: ct("foo.200"), color: ct('bar.100'))})/>`,
},
context,
);

expect(res).toMatchInlineSnapshot(
`"<div className={css({ bg: {"base":"#000"}, color: 'red')})/>"`,
);
});

it('skips without "ct(" in contents', () => {
const res = parser(
{
configure: () => {},
filePath: 'test.tsx',
content: `<div className={css({ bg: "red.200" })/>`,
},
context,
);

expect(res).toBeUndefined();
});
});
6 changes: 0 additions & 6 deletions src/__tests__/tsconfig.json

This file was deleted.

53 changes: 14 additions & 39 deletions src/__tests__/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,24 @@
import { isObject, makePaths } from '../utils';
import { isObjectWithValue, isObject } from '../utils';

describe('isObject', () => {
it('returns true if an object', () => {
expect(isObject({})).toBe(true);
expect(isObject({ foo: 'bar' })).toBe(true);
describe('isObjectWithValue', () => {
it('returns true for an object with a value property', () => {
expect(isObjectWithValue({ value: '' })).toBe(true);
expect(isObjectWithValue({ value: {} })).toBe(true);
});

it('returns false if not an object', () => {
expect(isObject(1)).toBe(false);
expect(isObject('1')).toBe(false);
expect(isObject(undefined)).toBe(false);
expect(isObject(null)).toBe(false);
expect(isObject([1, 2, 3])).toBe(false);
it('returns false for an object without a value property', () => {
expect(isObjectWithValue({})).toBe(false);
});
});

describe('makePaths', () => {
it('makes paths', () => {
expect(
makePaths({
foo: { 100: { value: '#fff' }, 200: '' },
bar: { 100: '', 200: '' },
}),
).toMatchInlineSnapshot(`
[
"foo.100",
"foo.200",
"bar.100",
"bar.200",
]
`);
describe('isObject', () => {
it('returns true for an object', () => {
expect(isObject({})).toBe(true);
});

it('makes paths with object values', () => {
expect(
makePaths({
foo: { a: { b: { c: { value: { base: '', lg: '' } } } } },
bar: { baz: { 100: { value: '#fff' }, 200: { value: {} } } },
}),
).toMatchInlineSnapshot(`
[
"foo.a.b.c",
"bar.baz.100",
"bar.baz.200",
]
`);
it('returns false for not an object', () => {
expect(isObject([1, 2, 3])).toBe(false);
expect(isObject(null)).toBe(false);
expect(isObject(undefined)).toBe(false);
});
});
16 changes: 10 additions & 6 deletions src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,28 @@ import type {
MaybeAsyncReturn,
Artifact,
} from '@pandacss/types';
import { makePaths } from './utils';
import { makePaths, mapTemplate } from './map';
import type { PluginContext } from './types';
import { getTemplate } from './get';

export const codegen = (
args: CodegenPrepareHookArgs,
context: Partial<PluginContext>,
context: PluginContext,
): MaybeAsyncReturn<void | Artifact[]> => {
const tokens = context.tokens ?? {};
if (!tokens) return;
const { tokens, map } = context;

const cssFn = args.artifacts.find((a) => a.id === 'css-fn');
if (!cssFn) return args.artifacts;

const cssFile = cssFn.files.find((f) => f.file.includes('css.mjs'));
if (!cssFile) return args.artifacts;

cssFile.code += getTemplate(tokens);
cssFile.code += mapTemplate(map);
cssFile.code += `
export const ct = (path) => {
if (!pluginCtMap.has(path)) return 'panda-plugin-ct-alias-not-found';
return pluginCtMap.get(path);
};
`;

const cssDtsFile = cssFn.files.find((f) => f.file.includes('css.d.'));
if (!cssDtsFile) return args.artifacts;
Expand Down
12 changes: 8 additions & 4 deletions src/create-project.ts → src/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Project, ts } from 'ts-morph';
import type { ComponentTokens, PluginContext } from './types';
import { makeMap } from './map';

export const createProject = () => {
return new Project({
export const createContext = (tokens: ComponentTokens): PluginContext => ({
project: new Project({
compilerOptions: {
jsx: ts.JsxEmit.React,
jsxFactory: 'React.createElement',
Expand All @@ -16,5 +18,7 @@ export const createProject = () => {
skipAddingFilesFromTsConfig: true,
skipFileDependencyResolution: true,
skipLoadingLibFiles: true,
});
};
}),
tokens,
map: makeMap(tokens),
});
Loading

0 comments on commit 25af4ac

Please sign in to comment.