Skip to content

Commit 6ec9664

Browse files
committed
implement development server
1 parent ada8ce1 commit 6ec9664

File tree

11 files changed

+142
-117
lines changed

11 files changed

+142
-117
lines changed

README.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,14 @@ interpretation of the text. No machine learning involved.
99
**It is work in progress!**
1010
[We welcome contributors however!](./CONTRIBUTING.md)
1111

12-
## Building locally
12+
## Starting development server
1313

14-
You'll need [Deno](https://deno.com/) for this project. Then you'll need to
15-
install the dependencies before running any command: `deno install`.
14+
After obtaining a local copy, You'll need [Deno](https://deno.com/) for this
15+
project. Then you'll need to install the dependencies before running any
16+
command: `deno install`.
1617

17-
After this, you can start away by running `deno task watch` then open
18-
`./dist/index.html` using your favorite browser. Run `deno task` to see more
19-
useful command lines.
18+
After this, you can start away by running `deno task start` then follow the link
19+
provide by the stdout to open a local copy of ilo Token. This server will
20+
auto-reload the webpage whenever there are changes to the code.
21+
22+
Run `deno task` to see more useful command lines.

build.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// This code is Deno only
2+
3+
import * as ESBuild from "esbuild";
4+
import { OPTIONS } from "./config.ts";
5+
import * as Dictionary from "./dictionary/build.ts";
6+
7+
const BUILD_OPTIONS: ESBuild.BuildOptions = { ...OPTIONS, minify: true };
8+
9+
if (import.meta.main) {
10+
await Dictionary.build();
11+
await ESBuild.build(BUILD_OPTIONS);
12+
}

bundle.ts

Lines changed: 0 additions & 84 deletions
This file was deleted.

config.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This code is Deno only
2+
3+
import { denoPlugins } from "@luca/esbuild-deno-loader";
4+
import * as ESBuild from "esbuild";
5+
6+
export const OPTIONS: ESBuild.BuildOptions = {
7+
entryPoints: ["./src/main.ts"],
8+
outfile: "./dist/main.js",
9+
format: "iife",
10+
bundle: true,
11+
sourcemap: "linked",
12+
target: [`es${new Date().getFullYear() - 3}`],
13+
plugins: [...denoPlugins()],
14+
logLevel: "info",
15+
};

deno.json

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@
44
},
55
"tasks": {
66
"build": {
7-
"description": "Builds `./dist/main.js` as minified file with source mapping at `./dist/main.js.map`. This command also builds the dictionary at `./dictionary/dictionary.ts`.",
8-
"command": "deno run -E -R -W -N=jsr.io --allow-run --no-prompt --frozen --cached-only ./bundle.ts build"
7+
"description": "Builds every static files needed for GitHub pages",
8+
"command": "deno run -E -R -W -N=jsr.io --allow-run --no-prompt --frozen --cached-only ./build.ts"
99
},
10-
"watch": {
11-
"description": "Similar to `deno task build` but doesn't minify the code. This command also watches the source code and rebuilds `./dist/main.js` or `./dictionary/dictionary.ts` whenever necessary. This DOESN'T auto-refreshes the webpage.",
12-
"command": "deno run -E -R -W -N=jsr.io --allow-run --no-prompt --frozen --cached-only ./bundle.ts watch"
13-
},
14-
"start-server": {
15-
"description": "Starts a local server serving `./dist/` statically",
16-
"command": "deno run -N=0.0.0.0 -R=./dist/ --no-prompt jsr:@std/http/file-server ./dist/"
10+
"start": {
11+
"description": "Starts a development server. The provided page will auto-reload whenever there are changes to the code.",
12+
"command": "deno run -E -R -W -N=jsr.io --allow-run --no-prompt --frozen --cached-only ./dev.ts"
1713
},
1814
"repl": {
1915
"description": "Starts a REPL",
@@ -73,6 +69,7 @@
7369
"@std/async": "jsr:@std/async@^1.0.12",
7470
"@std/cache": "jsr:@std/cache@^0.2.0",
7571
"@std/collections": "jsr:@std/collections@^1.0.10",
72+
"@std/fs": "jsr:@std/fs@^1.0.15",
7673
"@std/html": "jsr:@std/html@^1.0.3",
7774
"@std/random": "jsr:@std/random@^0.1.0",
7875
"@std/regexp": "jsr:@std/regexp@^1.0.1",

deno.lock

Lines changed: 12 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dev.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// This code is Deno only
2+
3+
import { exists } from "@std/fs/exists";
4+
import * as ESBuild from "esbuild";
5+
import { OPTIONS } from "./config.ts";
6+
7+
const BUILD_OPTIONS: ESBuild.BuildOptions = {
8+
...OPTIONS,
9+
minify: false,
10+
define: { LIVE_RELOAD: "true" },
11+
};
12+
if (import.meta.main) {
13+
if (!await exists(new URL("./dictionary/dictionary.ts", import.meta.url))) {
14+
const Dictionary = await import("./dictionary/build.ts");
15+
await Dictionary.build();
16+
}
17+
const command = new Deno.Command("deno", {
18+
args: [
19+
"run",
20+
"-R=./dictionary/dictionary",
21+
"-W=./dictionary/dictionary.ts",
22+
"--no-prompt",
23+
"--frozen",
24+
"--cached-only",
25+
"--watch",
26+
"./dictionary/watch.ts",
27+
],
28+
cwd: new URL("./", import.meta.url),
29+
stdout: "inherit",
30+
stderr: "inherit",
31+
stdin: "null",
32+
});
33+
const process = command.spawn();
34+
const context = await ESBuild.context(BUILD_OPTIONS);
35+
await context.watch();
36+
await context.serve({ servedir: "./dist/" });
37+
await process.status;
38+
}

dictionary/build.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { Dictionary } from "./type.ts";
2222
export const dictionary: Dictionary = new Map(Object.entries(${json}));
2323
`;
2424
await Deno.writeTextFile(DESTINATION, code);
25+
// deno-lint-ignore no-console
26+
console.log("Building dictionary done");
2527
}
2628
if (import.meta.main) {
2729
await build();

dictionary/watch.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// This code is Deno only
2+
3+
import { unreachable } from "@std/assert/unreachable";
4+
import { debounce } from "@std/async/debounce";
5+
import { build } from "./build.ts";
6+
7+
async function tryBuild(): Promise<void> {
8+
try {
9+
await build();
10+
} catch (error) {
11+
console.log(error);
12+
}
13+
}
14+
if (import.meta.main) {
15+
const watcher = Deno.watchFs("./dictionary/dictionary");
16+
let task = Promise.resolve();
17+
const buildDebounced = debounce(() => {
18+
task = task.then(tryBuild);
19+
}, 500);
20+
buildDebounced();
21+
buildDebounced.flush();
22+
for await (const _ of watcher) {
23+
buildDebounced();
24+
}
25+
unreachable();
26+
}

src/main.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
// This code is browser only
22

3+
declare const LIVE_RELOAD: boolean;
4+
5+
// auto-refresh when source code have changed
6+
if (typeof LIVE_RELOAD !== "undefined" && LIVE_RELOAD) {
7+
new EventSource("/esbuild")
8+
.addEventListener("change", () => location.reload());
9+
}
10+
311
import { dictionary } from "../dictionary/dictionary.ts";
412
import { asComment } from "../dictionary/misc.ts";
513
import PROJECT_DATA from "../project_data.json" with { type: "json" };
@@ -143,15 +151,6 @@ function main(): void {
143151
}
144152
}
145153

146-
// remove unused local storage data
147-
const used = [DICTIONARY_KEY, ...Object.keys(settings)];
148-
const unused = [...new Array(localStorage.length).keys()]
149-
.map((i) => localStorage.key(i)!)
150-
.filter((key) => !used.includes(key));
151-
for (const key of unused) {
152-
localStorage.removeItem(key);
153-
}
154-
155154
// initial text area size
156155
resizeTextarea();
157156
function resizeTextarea(): void {
@@ -304,10 +303,18 @@ function errorsFixable(errors: ReadonlyArray<unknown>): boolean {
304303
return errors.length > 0 &&
305304
errors.every((error) => error instanceof ArrayResultError);
306305
}
307-
if (typeof document !== "undefined") {
308-
if (document.readyState === "loading") {
309-
document.addEventListener("DOMContentLoaded", main);
310-
} else {
311-
main();
312-
}
306+
307+
if (document.readyState === "loading") {
308+
document.addEventListener("DOMContentLoaded", main);
309+
} else {
310+
main();
311+
}
312+
313+
// remove unused local storage data
314+
const used = [DICTIONARY_KEY, ...Object.keys(settings)];
315+
const unused = [...new Array(localStorage.length).keys()]
316+
.map((i) => localStorage.key(i)!)
317+
.filter((key) => !used.includes(key));
318+
for (const key of unused) {
319+
localStorage.removeItem(key);
313320
}

0 commit comments

Comments
 (0)