어제 글을 존나 날림으로 썼는데 왜 그러냐 하면 그 글의 내용 이외에 mui 적용하려고 똥꼬쑈를 하다가 결국에는 안되었기 때문이었다. 아니 esm.sh 통해서 설치까지는 되는데 스타일이 제대로 안먹음… 쉬발…
오늘은 왜 늦게 쓰기 시작하냐면 우마무스메 3기 마지막화를 봐야했기 때문이다.
여튼 이어서…
mui가 안되므로 울며 겨자먹기로 부트스트랩을 써봅시다. 붙스트랩이 좋은 점은 css는 그냥 cdn 암거나 가져다 쓰거나 공식사이트에서 css받아서 적용하면 된다는 것이다. 물론 버전은 잘 맞춰야겠지..
사실 어제 부트스트랩도 시도를 안해본건 아닌데, esm.sh 명령어로 추가하려고 하면 @types/react-transition-group 관련 에러가 발생한다. 그러므로 deno.json에 수동으로 추가해줍시다.
deno.json
{
"tasks": {
"esm:add": "deno run -A https://esm.sh/v135 add",
"esm:update": "deno run -A https://esm.sh/v135 update",
"esm:remove": "deno run -A https://esm.sh/v135 remove",
"bundle": "deno run -A bundle.ts",
"cache": "deno cache --reload --lock=lock.json --lock-write deps.*"
},
"imports": {
"react-bootstrap": "https://esm.sh/v135/react-bootstrap@2.9.2",
"react-bootstrap/": "https://esm.sh/v135/react-bootstrap@2.9.2/",
"react-dom": "https://esm.sh/v135/*react-dom@18.2.0",
"react-dom/": "https://esm.sh/v135/*react-dom@18.2.0/",
"react": "https://esm.sh/v135/react@18.2.0",
"react/": "https://esm.sh/v135/react@18.2.0/",
"$std": "https://deno.land/std@0.210.0",
"$std/": "https://deno.land/std@0.210.0/"
},
"scopes": {
"https://esm.sh/v135/": {
"loose-envify": "https://esm.sh/v135/loose-envify@1.4.0",
"scheduler": "https://esm.sh/v135/scheduler@0.23.0"
}
},
"compilerOptions": {
"lib": [
"dom",
"esnext",
"deno.dom",
"deno.window"
],
"jsx": "react-jsx",
"jsxImportSource": "react"
}
}
deps.bundle.ts
export * as esbuild from "https://deno.land/x/esbuild@v0.19.2/mod.js";
export { denoPlugins } from "https://deno.land/x/esbuild_deno_loader@0.8.2/mod.ts";
export { resolve } from "$std/path/mod.ts";
deps.bootstrap.ts
export * from "react-bootstrap";
dist/index.html
<!DOCTYPE html>
<html lang="ko">
<head>
<title>Deno Bundle Tests</title>
<meta charset="utf-8" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css"
integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM"
crossorigin="anonymous"
/>
</head>
<body>
<div id="root"></div>
http://./bundle.js
</body>
</html>
테스트이므로 그냥 cdn에 있는 걸 썼다.
bundle.ts
import { denoPlugins, esbuild, resolve } from "./deps.bundle.ts";
await esbuild.build({
plugins: [...denoPlugins({
configPath: resolve(Deno.cwd(), "deno.json")
})],
entryPoints: ["./src/index.tsx"],
outfile: "./dist/bundle.js",
bundle: true,
format: "esm",
minify: true,
});
esbuild.stop();
이렇게 설정해 두면 react-bootstrap을 쓸 수 있다!
fresh는 tailwindcss를 쓸 수 있지만… 난 그거 못하겠더라…
그래서 오늘 해볼 것은 xlsx 파일을 CSV 파일(UTF-8)로 변경하는 것입니다.
여기서는 sheetjs를 사용할 것인데… 이것도 업데이트 안된지 2년이나 됐네… index.tsx는 생략하고 App.tsx만 보면 다음과 같다.
src/App.tsx
import * as React from "react";
import { XLSX } from "../deps.xlsx.ts";
import { Button, Card, Form, InputGroup, Table } from "../deps.bootstrap.ts";
export default function App(): JSX.Element {
const [workbook, setWorkbook] = React.useState<ReturnType<typeof XLSX.read> | null>(null);
const [file, setFile] = React.useState<File | null>(null);
const [sheets, setSheets] = React.useState<Array<string>>([]);
function onChangeFile(e: React.ChangeEvent<HTMLInputElement>) {
const currentTarget = e.currentTarget as HTMLInputElement;
if (currentTarget?.files?.length === 1) {
setFile(currentTarget.files[0]);
}
}
async function onOpenFile() {
if (file === null) {
return;
}
const buffer = await file.arrayBuffer();
const workbook = XLSX.read(buffer, { type: "buffer" });
setWorkbook(workbook);
setSheets(workbook.SheetNames as Array<string>);
}
function downloadAsCSV(sheetName: string) {
const sheet = workbook?.Sheets[sheetName];
if (file === null || sheet === undefined) {
return;
}
const downloader = document.createElement("a");
downloader.href = URL.createObjectURL(new Blob([XLSX.utils.sheet_to_csv(sheet)]));
downloader.download = `${file.name} - ${sheetName}.csv`;
downloader.click();
}
return (
<Card style={{ width: "100%", height: "50vh", marginTop: "25vh" }}>
<Card.Header>
<Card.Title>XLSX 2 CSV : {file?.name}</Card.Title>
</Card.Header>
<Card.Body>
<Card.Text>
<Table striped bordered hover>
<colgroup>
<col style={{ width: "80%" }} />
<col style={{ width: "20%" }} />
</colgroup>
<thead>
<tr>
<th>Sheet Name</th>
<th>Controls</th>
</tr>
</thead>
<tbody>
{
sheets.map((sheet, index) => (
<tr key={sheet}>
<td>{sheet}</td>
<td>
<Button variant="secondary" onClick={() => downloadAsCSV(sheet)}>Convert & Save</Button>
</td>
</tr>
))
}
</tbody>
</Table>
</Card.Text>
</Card.Body>
<Card.Footer>
<InputGroup style={{ display: "flex" }}>
<InputGroup.Text>File</InputGroup.Text>
<Form.Control type="file" onChange={onChangeFile} accept=".xlsx"/>
<Button type="button" onClick={onOpenFile} disabled={file === null}>Open</Button>
</InputGroup>
</Card.Footer>
</Card>
);
}
deps.xlsx.ts
// @deno-types="https://cdn.sheetjs.com/xlsx-0.20.1/package/types/index.d.ts"
export * as XLSX from "https://cdn.sheetjs.com/xlsx-0.20.1/package/xlsx.mjs";
XLSX를 esm.sh에서 참조하여 해보려고 했으나 제대로 작동하지 않았고, sheetjs의 deno 지원쪽 페이지에서 찾은 js 경로로 했더니 잘 작동하는데, 문제는 얘는 타입이 없.,…. 는 줄 알았는데 페이지 내 코드 주석인 // @deno-types…를 추가하니 잘 불러온다. XLSX.Workbook이나 ReturnType<typeof XLSX.read>나 같으므로 상관이 없다.
끗
답글 남기기