Skip to content

Commit

Permalink
feat(parser): add support for import aliases, fix jsx parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
jonambas committed Apr 7, 2024
1 parent 2d1d973 commit 02f3510
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 54 deletions.
7 changes: 1 addition & 6 deletions src/__tests__/codegen.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
import { codegen } from '../codegen';
import { createContext } from '../context';

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

describe('codegen', () => {
it('generates ct runtime code', () => {
Expand Down
8 changes: 8 additions & 0 deletions src/__tests__/fixtures.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createContext } from '../context';

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

export const context = createContext(tokens);
8 changes: 3 additions & 5 deletions src/__tests__/map.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { get, makeMap, makePaths, mapTemplate } from '../map';

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

describe('get', () => {
it('gets a string', () => {
Expand All @@ -15,6 +11,7 @@ describe('get', () => {
`
{
"base": "#000",
"lg": "#111",
}
`,
);
Expand Down Expand Up @@ -67,6 +64,7 @@ describe('makeMap', () => {
"foo.100" => "#fff",
"foo.200" => {
"base": "#000",
"lg": "#111",
},
"bar.100" => "red",
"bar.200" => "blue",
Expand Down
83 changes: 60 additions & 23 deletions src/__tests__/parser.test.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,74 @@
import { parser } from '../parser';
import { createContext } from '../context';
import { context } from './fixtures';

const context = createContext({
foo: { 100: { value: '#fff' }, 200: { value: { base: '#000' } } },
bar: { 100: 'red', 200: 'blue' },
});
export const makeParser = (content: string) => {
return parser(
{
configure: () => {},
filePath: 'test.tsx',
content,
},
context,
);
};

describe('parser', () => {
it('parses', () => {
const res = parser(
{
configure: () => {},
filePath: 'test.tsx',
content: `<div className={css({ bg: ct("foo.200"), color: ct('bar.100'))})/>`,
const res = makeParser(`
import { css, ct, cva } from '@/styled-system/css';
const styles = cva({
base: {
// background: ct('foo.200'),
color: ct('bar.200'),
},
context,
);
});
export const Component = () => {
return (<div
className={
css({
bg: ct('foo.200'),
color: ct('bar.100')
})}
/>);
`);

expect(res).toMatchInlineSnapshot(
`"<div className={css({ bg: {"base":"#000"}, color: 'red')})/>"`,
`
"import { css, ct, cva } from '@/styled-system/css';
const styles = cva({
base: {
// background: ct('foo.200'),
color: 'blue',
},
});
export const Component = () => {
return (<div
className={
css({
bg: {"base":"#000","lg":"#111"},
color: 'red'
})}
/>);
"
`,
);
});

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

expect(
makeParser(`import { css } from '@/styled-system/css`),
).toBeUndefined();

expect(res).toBeUndefined();
expect(
makeParser(`import { ct } from '@/styled-system/css`),
).toBeUndefined();
});
});
53 changes: 33 additions & 20 deletions src/parser.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,49 @@
import type { ParserResultBeforeHookArgs } from '@pandacss/types';
import type { PluginContext } from './types';
import { isObject } from './utils';
import { ts } from 'ts-morph';

export const parser = (
args: ParserResultBeforeHookArgs,
context: PluginContext,
): string | void => {
const { project, map } = context;

// TODO: handle `import { ct as xyz }` aliasing
const content = args.content;
if (!content.includes('ct(')) return;

const source = project.createSourceFile('__temp-ct-parser.ts', content, {
// Note: parser won't replace `ct` calls in JSX without .tsx
const source = project.createSourceFile('__ct-parser.tsx', args.content, {
overwrite: true,
});

let text = source.getText();
const calls = text.match(/ct\(['"][\w.]+['"]\)/g) ?? [];

for (const call of calls) {
const path = call
.match(/['"][\w.]+['"]/)
?.toString()
.replace(/['"]/g, '');
if (!path) continue;
const value = map.get(path);
text = text.replace(
call,
isObject(value) ? JSON.stringify(value) : `'${value}'`,
);
let ctExists = false;
let ctReplaced = false;
let ctAlias = 'ct';

for (const node of source.getImportDeclarations()) {
if (!node.getText().includes('ct')) continue;
for (const named of node.getNamedImports()) {
if (named.getText() === 'ct') {
ctExists = true;
ctAlias = named.getAliasNode()?.getText() ?? 'ct';
break;
}
}
}

if (!ctExists) return;

for (const node of source.getDescendantsOfKind(
ts.SyntaxKind.CallExpression,
)) {
if (node.getExpression().getText() === ctAlias) {
const path = node.getArguments()[0]?.getText().replace(/['"]/g, '');
const value = map.get(path);

node.replaceWithText(
isObject(value) ? JSON.stringify(value) : `'${value}'`,
);
ctReplaced = true;
}
}

return text;
return ctReplaced ? source.getText() : undefined;
};
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// import { LoggerInterface } from '@pandacss/types';
import { type Project } from 'ts-morph';

export type ComponentTokens = { [k: string]: string | ComponentTokens };
Expand All @@ -6,4 +7,5 @@ export type PluginContext = {
project: Project;
tokens: ComponentTokens;
map: Map<string, string | object>;
// logger?: LoggerInterface;
};

0 comments on commit 02f3510

Please sign in to comment.