Skip to content

Commit 3ce2c95

Browse files
committed
Import
0 parents  commit 3ce2c95

9 files changed

+1487
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules
2+
/dist

Makefile

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
start:
2+
npm run start
3+
build:
4+
npm run build
5+
test:
6+
npm run test
7+
clean:
8+
npm run clean
9+
10+
.PHONY: build test clean

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# React `use c`
2+
3+
Use C in your React!
4+
5+
<img width="590" alt="image" src="https://github.com/elnardu/react-use-c/assets/8999001/495c39d6-3fb1-437d-9af0-03020c215159">
6+
7+
https://github.com/elnardu/react-use-c/assets/8999001/24a433d9-af89-4962-a0a1-ba6533092d0b
8+
9+
## TODO
10+
11+
- [ ] Add more folders and files with code that does nothing to look more professional
12+
- [ ] Create `create-react-use-c` package cuz this ecosystem is broken
13+
- [ ] Add typescript support
14+
- [ ] Make somebody else figure out publishing this to npm (I am still not over it)
15+
- [ ] Remove typescript support
16+
- [ ] Tell windows ppl to just use WSL
17+
- [ ] esbuild is not cursed enough, gotta switch to something else

build.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const esbuild = require("esbuild");
2+
const fs = require("fs/promises");
3+
const fsButWihtoutPromises = require("fs");
4+
const path = require("path");
5+
6+
function findClosingBrace(string) {
7+
let c = 0;
8+
let i = 0;
9+
// prob doesn't work with unicode
10+
while (i < string.length) {
11+
const ch = string[i];
12+
if (ch === "{") c++;
13+
else if (ch === "}") c--;
14+
if (c == -1) return i;
15+
i++;
16+
}
17+
return null;
18+
}
19+
20+
function transformToUseC(args) {
21+
const content = fsButWihtoutPromises.readFileSync(args.path, "utf8");
22+
const splits = content.split(/["']use c["'];/);
23+
let result = splits[0];
24+
for (let i = 1; i < splits.length; i++) {
25+
const endOfCCode = findClosingBrace(splits[i]);
26+
const cCode = splits[i].slice(0, endOfCCode);
27+
result += `return runC("${encodeURIComponent(cCode)}");`;
28+
result += splits[i].slice(endOfCCode, splits[i].length);
29+
}
30+
return result;
31+
}
32+
33+
const useCPlugin = {
34+
name: "use-c",
35+
setup(build) {
36+
build.onLoad({ filter: /.js$/ }, (args) => ({
37+
contents: transformToUseC(args),
38+
loader: "js",
39+
}));
40+
41+
build.onLoad({ filter: /.jsx$/ }, (args) => ({
42+
contents: transformToUseC(args),
43+
loader: "jsx",
44+
}));
45+
},
46+
};
47+
48+
function sleep(ms) {
49+
return new Promise((resolve) => {
50+
setTimeout(resolve, ms);
51+
});
52+
}
53+
54+
async function build() {
55+
await fs.rm("dist", { recursive: true, force: true });
56+
await fs.mkdir("dist", { recursive: true });
57+
58+
console.log("Building project");
59+
await sleep(Math.random() * 5000); // gotta keep up with the trends
60+
61+
await esbuild.build({
62+
entryPoints: ["client.jsx"],
63+
outfile: "dist/js.js",
64+
minify: true,
65+
bundle: true,
66+
sourcemap: true,
67+
plugins: [useCPlugin],
68+
});
69+
70+
await fs.cp("index.html", "dist/index.html");
71+
}
72+
73+
build().catch((err) => {
74+
console.error(err);
75+
process.exit(1);
76+
});

client.jsx

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { useState } from "react";
2+
import ReactDOM from "react-dom";
3+
4+
// I haven't used any of this bs in a year, hopefully it still the same
5+
6+
/// Look mum! I am so cool, I put strings into a different file
7+
function css(strings) {
8+
let style = document.getElementById("css-in-js-style-thing");
9+
if (!style) {
10+
style = document.createElement("style");
11+
style.id = "css-in-js-style-thing";
12+
document.head.appendChild(style);
13+
}
14+
15+
const randomClassId = Math.random().toString(36).slice(2);
16+
style.textContent += `
17+
.${randomClassId} {
18+
${strings[0]}
19+
}`;
20+
return randomClassId;
21+
}
22+
23+
async function runC(code) {
24+
const res = await fetch("/rpc/rce", {
25+
method: "POST",
26+
body: JSON.stringify({ code: code }),
27+
headers: {
28+
"Content-Type": "application/json",
29+
},
30+
});
31+
return await res.json();
32+
}
33+
34+
const appStyles = css`
35+
margin: 3rem auto;
36+
max-width: 600px;
37+
padding: 0 1rem;
38+
`;
39+
40+
const App = () => (
41+
<div className={appStyles}>
42+
<h1>React use C demo</h1>
43+
<Demo />
44+
</div>
45+
);
46+
47+
const Demo = () => {
48+
const [output, setOutput] = useState(null);
49+
const cHelloWorld = async () => {
50+
"use c";
51+
#include <stdio.h>
52+
int main() {
53+
printf("Hello from C!\n");
54+
return 0;
55+
}
56+
};
57+
const onClick = async () => {
58+
const out = await cHelloWorld();
59+
setOutput(out.stdout);
60+
};
61+
62+
return (
63+
<div>
64+
<button onClick={onClick}>Run C code!</button>
65+
<p>Output from C:</p>
66+
<pre>{ output }</pre>
67+
</div>
68+
);
69+
};
70+
71+
ReactDOM.render(<App />, document.getElementById("app"));

index.html

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>React use C demo</title>
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
<script src="/js.js"></script>
11+
</body>
12+
</html>

0 commit comments

Comments
 (0)