diff --git a/examples/macros/components/covid19.tsx b/examples/macros/components/covid19.tsx new file mode 100644 index 0000000000000..52fee2ff35269 --- /dev/null +++ b/examples/macros/components/covid19.tsx @@ -0,0 +1,33 @@ +import { fetchCSV } from "macro:fetchCSV"; + +export const Covid19 = () => { + const rows = fetchCSV( + "https://covid19.who.int/WHO-COVID-19-global-data.csv", + { + last: 100, + columns: ["New_cases", "Date_reported", "Country"], + } + ); + + return ( +
+

Covid-19

+
last {rows.length} updates from the WHO
+
+
+
New Cases
+
Date
+
Country
+
+ + {rows.map((row, index) => ( +
+
{row[0]}
+
{row[1]}
+
{row[2]}
+
+ ))} +
+
+ ); +}; diff --git a/examples/macros/components/index.tsx b/examples/macros/components/index.tsx index 6c3e39be70fa3..20e58b7b7a27c 100644 --- a/examples/macros/components/index.tsx +++ b/examples/macros/components/index.tsx @@ -5,6 +5,7 @@ import { IPAddresses } from "./example"; const Start = function () { const root = document.createElement("div"); document.body.appendChild(root); + ReactDOM.render(, root); }; diff --git a/examples/macros/fetchCSV.tsx b/examples/macros/fetchCSV.tsx index 0709fd50053ab..b06b1e03ee12e 100644 --- a/examples/macros/fetchCSV.tsx +++ b/examples/macros/fetchCSV.tsx @@ -1,4 +1,12 @@ import Pappa from "papaparse"; +// Example usage: +// const rows = fetchCSV( +// "https://covid19.who.int/WHO-COVID-19-global-data.csv", +// { +// last: 100, +// columns: ["New_cases", "Date_reported", "Country"], +// } +// ); export async function fetchCSV(callExpression) { console.time("fetchCSV Total"); const [ diff --git a/examples/macros/matchInFile.tsx b/examples/macros/matchInFile.tsx index a73f7ee8bfbc0..1f5c20fb36957 100644 --- a/examples/macros/matchInFile.tsx +++ b/examples/macros/matchInFile.tsx @@ -1,8 +1,11 @@ // macro code -export function matchInFile(callExpression) { +export function matchInFile(callExpression: BunAST.CallExpression) { const [filePathNode, matcherNode] = callExpression.arguments; - const filePath: string = filePathNode.get(); - const matcher: RegExp = matcherNode.get(); + let filePath: string; + filePath = filePathNode.get(); + + let matcher: RegExp; + matcher = matcherNode.get(); const file: string = Bun.readFile(Bun.cwd + filePath); return ( @@ -18,3 +21,81 @@ export function matchInFile(callExpression) { ); } + +export declare namespace BunAST { + export abstract class ASTNode { + constructor(...args: any); + } + + export interface ASTElement< + P = any, + T extends string | JSXElementConstructor = + | string + | JSXElementConstructor + > { + type: T; + props: P; + key: Key | null; + } + + export abstract class Expression extends ASTNode {} + + export abstract class CallExpression extends Expression { + arguments: AnyExpression[]; + name: string; + target: AnyExpression; + } + + export abstract class StringExpression extends Expression { + get(): string; + value: string; + } + + export interface StringExpressionElementProps { + value: string; + } + + export type StringExpressionElement = ASTElement< + StringExpressionElementProps, + StringExpression + >; + + export abstract class RegExpExpression extends Expression { + get(): RegExp; + + flags: string; + pattern: string; + raw: string; + } + + export type AnyExpression = + | CallExpression + | StringExpression + | RegExpExpression; +} + +declare global { + namespace JSX { + interface Element extends BunAST.ASTElement {} + interface ElementClass extends BunAST.Expression {} + interface ElementAttributesProperty { + props: {}; + } + interface ElementChildrenAttribute { + children: {}; + } + + // // We can't recurse forever because `type` can't be self-referential; + // // let's assume it's reasonable to do a single React.lazy() around a single React.memo() / vice-versa + // type LibraryManagedAttributes = C extends React.MemoExoticComponent | React.LazyExoticComponent + // ? T extends React.MemoExoticComponent | React.LazyExoticComponent + // ? ReactManagedAttributes + // : ReactManagedAttributes + // : ReactManagedAttributes; + + interface IntrinsicElements { + // HTML + string: BunAST.StringExpressionElement; + } + } +} diff --git a/examples/macros/package.json b/examples/macros/package.json index de4e264534206..dff2c648e122c 100644 --- a/examples/macros/package.json +++ b/examples/macros/package.json @@ -5,8 +5,13 @@ "license": "MIT", "dependencies": { "moment": "^2.29.1", + "papaparse": "^5.3.1", "react": "^17.0.2", "react-dom": "^17.0.2", "react-refresh": "^0.10.0" + }, + "devDependencies": { + "@types/react": "^17.0.24", + "@types/react-dom": "^17.0.9" } } diff --git a/examples/macros/styles.css b/examples/macros/styles.css index 87f0ef1a81d27..a8109a8206d0a 100644 --- a/examples/macros/styles.css +++ b/examples/macros/styles.css @@ -18,9 +18,30 @@ body { font-family: monospace; } -.Lines { +.Table { + display: grid; + width: fit-content; +} + +.Row, +.Header { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + text-align: right; + + column-gap: 2rem; +} + +.Heading { + text-align: right; +} + +.Header { + border-bottom: 1px solid rgb(0, 255, 0); + margin-bottom: 20px; + padding-bottom: 20px; +} + +.Heading:nth-of-type(2) { text-align: left; - margin: 0 auto; - max-width: fit-content; - line-height: 1.5; }