Compare commits
No commits in common. "7566bf86125fe737bc6df9692a8bcda44d983d14" and "d27d11d9467c8d4ef1d7ace2fa584ecff1410a9c" have entirely different histories.
7566bf8612
...
d27d11d946
13
README.md
13
README.md
@ -6,15 +6,4 @@
|
|||||||
```bash
|
```bash
|
||||||
mdbook serve
|
mdbook serve
|
||||||
```
|
```
|
||||||
를 통해서 [문서](http://localhost:3000)을 웹브라우저로 볼 수 있습니다.
|
를 통해서 [문서](http://localhost:3000)을 웹브라우저로 볼 수 있습니다.
|
||||||
|
|
||||||
## cli.py
|
|
||||||
|
|
||||||
deno가 설치되어 있어야 합니다.
|
|
||||||
|
|
||||||
처음 실행시 issue를 가지고 오는 작업이 필요합니다. 먼저, `GITHUB_TOKEN` 환경변수에 깃헛 token을 설정해주세요. `.env`를 지원합니다.
|
|
||||||
토큰을 발급받기 위해선 [다음 링크](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)를 참조하면 됩니다.
|
|
||||||
```bash
|
|
||||||
./cli.py build --update_issues
|
|
||||||
```
|
|
||||||
를 실행해 주세요.
|
|
@ -3,12 +3,9 @@ import { Issue } from "./githubType.ts";
|
|||||||
import { copy } from "https://deno.land/std@0.136.0/fs/mod.ts";
|
import { copy } from "https://deno.land/std@0.136.0/fs/mod.ts";
|
||||||
import { readAll } from "https://deno.land/std@0.135.0/streams/mod.ts"
|
import { readAll } from "https://deno.land/std@0.135.0/streams/mod.ts"
|
||||||
import { parse as argParse } from "https://deno.land/std@0.135.0/flags/mod.ts";
|
import { parse as argParse } from "https://deno.land/std@0.135.0/flags/mod.ts";
|
||||||
import {
|
import { normalize, join as pathJoin, fromFileUrl, parse as parsePath
|
||||||
normalize, join as pathJoin, fromFileUrl, parse as parsePath
|
, relative } from "https://deno.land/std@0.135.0/path/mod.ts";
|
||||||
, relative
|
|
||||||
} from "https://deno.land/std@0.135.0/path/mod.ts";
|
|
||||||
import * as Eta from "https://deno.land/x/eta@v1.12.3/mod.ts";
|
import * as Eta from "https://deno.land/x/eta@v1.12.3/mod.ts";
|
||||||
import { createReactive } from "./reactivity.ts";
|
|
||||||
|
|
||||||
async function readContent(path?: string): Promise<string> {
|
async function readContent(path?: string): Promise<string> {
|
||||||
let content = "[]";
|
let content = "[]";
|
||||||
@ -72,17 +69,16 @@ async function readAndPrint(args: {
|
|||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const parsedArg = argParse(Deno.args);
|
const parsedArg = argParse(Deno.args);
|
||||||
const { issue_path, outDirArg, w, watch } = parsedArg;
|
const { issue_path, outDir, w, watch } = parsedArg;
|
||||||
const watchMode = w || watch;
|
const watchMode = w || watch;
|
||||||
if (typeof issue_path !== "undefined" && typeof issue_path !== "string") {
|
if (typeof issue_path !== "undefined" && typeof issue_path !== "string") {
|
||||||
console.log("Please provide a path to the json file.");
|
console.log("Please provide a path to the json file.");
|
||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
if (typeof outDirArg !== "undefined" && typeof outDirArg !== "string") {
|
if (typeof outDir !== "undefined" && typeof outDir !== "string") {
|
||||||
console.log("Please provide a path to the output file.");
|
console.log("Please provide a path to the output file.");
|
||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
}
|
}
|
||||||
const outDir = (outDirArg ?? "build");
|
|
||||||
if (typeof watchMode !== "undefined" && typeof watchMode !== "boolean") {
|
if (typeof watchMode !== "undefined" && typeof watchMode !== "boolean") {
|
||||||
console.log("Please provide a boolean value for w.");
|
console.log("Please provide a boolean value for w.");
|
||||||
Deno.exit(1);
|
Deno.exit(1);
|
||||||
@ -99,29 +95,14 @@ async function main() {
|
|||||||
views: viewPath,
|
views: viewPath,
|
||||||
"view cache": false,
|
"view cache": false,
|
||||||
});
|
});
|
||||||
const issuesR = await createReactive(async () => {
|
|
||||||
const c = await readContent(issue_path);
|
const c = await readContent(issue_path);
|
||||||
const issues = JSON.parse(c) as Issue[];
|
const issues = JSON.parse(c) as Issue[];
|
||||||
issues.sort((a, b) => a.number - b.number);
|
issues.sort((a, b) => a.number - b.number);
|
||||||
return issues;
|
|
||||||
});
|
|
||||||
|
|
||||||
const targets = ["SUMMARY.md", "overall.md", "specific.md", "intro.md", "support.md"];
|
const targets = ["SUMMARY.md", "overall.md", "specific.md", "intro.md", "support.md"];
|
||||||
|
|
||||||
const targetsR = await Promise.all(targets.map(async (t) => {
|
await readAndPrint({ issue_path, outDir, targets });
|
||||||
return await createReactive(() => {
|
|
||||||
return readAndPrint({ issue_path, outDir, targets:[t] });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
));
|
|
||||||
issuesR.wireTo(...targetsR);
|
|
||||||
const copyOp = await createReactive(async () => {
|
|
||||||
const files = [...Deno.readDirSync(viewPath)].map(x => x.name).filter(x => !x.endsWith(".md"));
|
|
||||||
const op = files.map(x => copy(pathJoin(viewPath, x), pathJoin(outDir, x), { overwrite: true }));
|
|
||||||
await Promise.all(op);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (watchMode) {
|
if (watchMode) {
|
||||||
const watcher = Deno.watchFs([viewPath, issue_path as string]);
|
const watcher = Deno.watchFs([viewPath, issue_path as string]);
|
||||||
for await (const event of watcher) {
|
for await (const event of watcher) {
|
||||||
@ -130,20 +111,28 @@ async function main() {
|
|||||||
new TextEncoder().encode("\x1b[2J\x1b[0f"),
|
new TextEncoder().encode("\x1b[2J\x1b[0f"),
|
||||||
);
|
);
|
||||||
console.log(`reloading ${event.paths.join(", ")}`);
|
console.log(`reloading ${event.paths.join(", ")}`);
|
||||||
|
let reloadAll = false;
|
||||||
for (const path of event.paths) {
|
for (const path of event.paths) {
|
||||||
const p = parsePath(path);
|
const p = parsePath(path);
|
||||||
if (p.dir === viewPath) {
|
if (targets.includes(p.base)) {
|
||||||
if(p.ext === ".md") {
|
readAndPrint({
|
||||||
targetsR[targets.indexOf(p.base)].update();
|
issue_path: issue_path as string,
|
||||||
}
|
outDir: outDir as string,
|
||||||
else{
|
targets: [p.base]
|
||||||
copyOp.update();
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (p.base === "issues.json") {
|
else{
|
||||||
await issuesR.update();
|
reloadAll = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (reloadAll) {
|
||||||
|
readAndPrint({
|
||||||
|
issue_path: issue_path as string,
|
||||||
|
outDir: outDir as string,
|
||||||
|
targets: targets
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
interface Reactive<T>{
|
|
||||||
readonly value: T;
|
|
||||||
update: () => Promise<void>;
|
|
||||||
wireTo(...r: Reactive<unknown>[]): void;
|
|
||||||
unwireTo(r: Reactive<unknown>): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function createReactive<T>(fn: () => Promise<T>): Promise<Reactive<T>> {
|
|
||||||
let v = await fn();
|
|
||||||
let listeners: Reactive<unknown>[] = [];
|
|
||||||
|
|
||||||
return {
|
|
||||||
get value() : T {
|
|
||||||
return v;
|
|
||||||
},
|
|
||||||
async update(){
|
|
||||||
const ret = await fn();
|
|
||||||
v = ret;
|
|
||||||
await Promise.all(listeners.map(o => o.update()));
|
|
||||||
},
|
|
||||||
wireTo(...r: Reactive<unknown>[]) {
|
|
||||||
listeners.push(...r);
|
|
||||||
},
|
|
||||||
unwireTo(r: Reactive<unknown>) {
|
|
||||||
listeners = listeners.filter(o => o !== r);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
@ -125,7 +125,7 @@ classDiagram
|
|||||||
|
|
||||||
### 3.7.2. 사용자 인터페이스 상세
|
### 3.7.2. 사용자 인터페이스 상세
|
||||||
|
|
||||||
![interface](./interface.png)
|
|
||||||
|
|
||||||
### 3.7.4. 특징(Feature)
|
### 3.7.4. 특징(Feature)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user