Skip to content

Commit

Permalink
refactor: store Map instead of runtime lookups
Browse files Browse the repository at this point in the history
  • Loading branch information
jonambas committed Apr 6, 2024
1 parent 88b5a5f commit dbd7764
Show file tree
Hide file tree
Showing 18 changed files with 331 additions and 220 deletions.
49 changes: 49 additions & 0 deletions src/__tests__/codegen.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import type { CodegenPrepareHookArgs } from '@pandacss/types';
import { codegen } from '../codegen';
import { createContext } from '../context';

const context = createContext({
foo: { 100: { value: { base: 'whitesmoke', lg: 'palegreen' } } },
bar: { 100: '{colors.green.200}' },
});

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",{"base":"whitesmoke","lg":"palegreen"}],["bar.100","{colors.green.200}"]]'));
export const ct = (path) => {
if (!path) return 'panda-plugin-ct-path-empty';
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" | "bar.100") => string;",
"file": "css.d.ts",
}
`);
});
});
47 changes: 47 additions & 0 deletions src/__tests__/ct.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { ct, ctTemplate } from '../ct';

const tokens = {
foo: { a: { b: { c: { value: { base: '10px', lg: '20px' } } } } },
bar: { baz: { 100: { value: {} }, 200: { value: {} } } },
baz: { 100: 'hello', 200: { value: 'goodbye' } },
};

describe('ct', () => {
it('gets a string', () => {
expect(ct(tokens, 'baz.100')).toBe('hello');
});

it('gets a value object', () => {
expect(ct(tokens, 'foo.a.b.c')).toMatchInlineSnapshot(
`
{
"base": "10px",
"lg": "20px",
}
`,
);
});

it('gets a value string', () => {
expect(ct(tokens, 'baz.200')).toMatchInlineSnapshot(`"goodbye"`);
});

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

describe('getTemplate', () => {
it('generates a ct function', () => {
expect(ctTemplate).toMatchInlineSnapshot(`
"
export const ct = (path) => {
if (!path) return 'panda-plugin-ct-path-empty';
if (!pluginCtMap.has(path)) return 'panda-plugin-ct-alias-not-found';
return pluginCtMap.get(path);
};
"
`);
});
});
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();
});
});
51 changes: 51 additions & 0 deletions src/__tests__/map.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { makeMap, makePaths, mapTemplate } from '../map';

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

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",
}
`);
});
});
50 changes: 50 additions & 0 deletions src/__tests__/parser.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { parser } from '../parser';
import { createContext } from '../context';

const context = createContext({
foo: { 100: { value: { base: 'whitesmoke', lg: 'palegreen' } } },
bar: { 100: '{colors.green.200}' },
});

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

expect(res).toMatchInlineSnapshot(
`"<div className={css({ bg: {"base":"whitesmoke","lg":"palegreen"}, color: '{colors.green.200}')})/>"`,
);
});

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

expect(res).toBeUndefined();
});

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

expect(res).toMatchInlineSnapshot(`"<div className={css({ bg: ct("") })/>"`);
});
});
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);
});
});
12 changes: 6 additions & 6 deletions src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ 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';
import { ctTemplate } from './ct';

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 += ctTemplate;

const cssDtsFile = cssFn.files.find((f) => f.file.includes('css.d.'));
if (!cssDtsFile) return args.artifacts;
Expand Down
Loading

0 comments on commit dbd7764

Please sign in to comment.