Skip to content

Commit 7350610

Browse files
authored
Merge pull request #78 from ilo-token/master
0.6.0
2 parents af1eecf + af9b211 commit 7350610

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+2144
-2415
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,35 @@ NOTE: Before publishing:
1010
<!--
1111
<details>
1212
<summary>On development changelog</summary>
13+
14+
## (On development)
15+
1316
The latest on-development version can be accessed by building the source code.
1417
On this on-development version, things can be broken.
1518
</details>
1619
-->
1720

21+
## 0.6.0
22+
23+
Released 22 April 2025
24+
25+
ilo Token can now translate prepositions. This includes preposition before "la"
26+
such as "tawa mi la sina pona" and prepositional predicate such as "mi kepeken
27+
ilo".
28+
29+
- Implement translation of preposition.
30+
- Implement "nanpa X la" translation.
31+
- Context clauses can now be translated into adverbs e.g. "pona la mi moku" will
32+
be translated as "nicely, I ate".
33+
- Fix "nanpa" translation: Before it translated into just "position" instead of
34+
e.g. "position 1".
35+
- When telo misikeke is enabled, it won't mark words defined in the custom
36+
dictionary.
37+
- Improve error messages for bugs. A detailed instruction for bug reporting is
38+
now shown.
39+
- Improve custom dictionary error messages. There is now a dedicated space for
40+
displaying errors.
41+
1842
## 0.5.3
1943

2044
Released 2 April 2025

CONTRIBUTING.md

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,13 @@ about the pages to get you started. Remember you can always ask for help in the
55
[discussion](#Discussion) or privately through my email:
66
77

8-
## [Wiki](https://github.com/ilo-token/ilo-token.github.io/wiki)
9-
10-
The wiki is a place full of useful information for contributors from how the
11-
code works to guidelines for editing the dictionary!
12-
13-
It's not perfect however. If you spot a mistake, please open an issue.
14-
158
## [Issue](https://github.com/ilo-token/ilo-token.github.io/issues)
169

17-
The issue page is intended for tracking the development of ilo Token as well as
18-
its wiki. You may open an issue for:
10+
The issue page is intended for tracking the development of ilo Token. You may
11+
open an issue for:
1912

2013
- Bug report
2114
- Feature request
22-
- Fix suggestion to the wiki
2315

2416
Please remember to search first before opening an issue, it might already exist!
2517
Also check the [changelog](./CHANGELOG.md) and open the on-development
@@ -51,8 +43,6 @@ Please search first before opening a new page! Duplicate pages are unnecessary.
5143
Before forking and editing, please claim an issue first or open an issue then
5244
claim it. After that, you can start away. This is necessary to avoid wasted
5345
duplicate efforts.
54-
[The wiki](https://github.com/ilo-token/ilo-token.github.io/wiki) contains
55-
useful information for contributors.
5646

5747
You **don't** have to open a new issue this if:
5848

@@ -71,7 +61,7 @@ More things to remember:
7161
`// This code is browser/Deno only`.
7262

7363
(The following aren't strict rules. It's perfectly fine to not follow any of
74-
these, we can adapt.)
64+
these for any reason e.g. you just want to fix typo.)
7565

7666
- Ensure all the files are formatted: Run `deno fmt`.
7767
- Make sure you don't accidentally make more tests fail: Run

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ interpretation of the text. No machine learning involved.
1313

1414
After using `git clone`, you'll need [Deno](https://deno.com/) for this project.
1515
Then you'll need to install the dependencies before running any command:
16-
`deno install`.
16+
`deno install --frozen`.
1717

1818
After this, you can start away by running `deno task start` then open the link
1919
provided by the stdout to open a local copy of ilo Token. The server will

build/build.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,22 @@
11
// This code is Deno only
22

33
import * as ESBuild from "esbuild";
4-
import { OPTIONS } from "./config.ts";
54
import * as Dictionary from "../dictionary/build.ts";
5+
import { OPTIONS } from "./config.ts";
66

77
const BUILD_OPTIONS: ESBuild.BuildOptions = {
88
...OPTIONS,
99
minify: true,
1010
define: { LIVE_RELOAD: "false" },
1111
};
12-
1312
if (import.meta.main) {
14-
await Dictionary.build();
15-
await ESBuild.build(BUILD_OPTIONS);
13+
const start = performance.now();
14+
if (await Dictionary.build()) {
15+
await ESBuild.build(BUILD_OPTIONS);
16+
const end = performance.now();
17+
// deno-lint-ignore no-console
18+
console.log(`Total time took: ${Math.floor(end - start)}ms`);
19+
} else {
20+
Deno.exitCode = 1;
21+
}
1622
}

build/dev.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,33 @@
33
import { assert } from "@std/assert/assert";
44
import { exists } from "@std/fs/exists";
55
import { BuildOptions, context } from "esbuild";
6-
import { AsyncDisposableStack } from "../misc/async_disposable_stack.ts";
76
import { OPTIONS } from "./config.ts";
87

8+
const DICTIONARY = new URL("../dictionary/dictionary.ts", import.meta.url);
9+
910
const BUILD_OPTIONS: BuildOptions = {
1011
...OPTIONS,
1112
minify: false,
1213
define: { LIVE_RELOAD: "true" },
1314
};
1415
async function watchMain(): Promise<AsyncDisposable> {
1516
await using stack = new AsyncDisposableStack();
16-
const buildContext = await context(BUILD_OPTIONS);
17-
stack.defer(async () => await buildContext.dispose());
18-
buildContext.watch();
19-
buildContext.serve({ servedir: "./dist/" });
20-
return stack.move();
17+
const buildContext = stack.use({
18+
context: await context(BUILD_OPTIONS),
19+
async [Symbol.asyncDispose](): Promise<void> {
20+
await this.context.dispose();
21+
},
22+
});
23+
buildContext.context.watch();
24+
buildContext.context.serve({ servedir: "./dist/" });
25+
stack.move();
26+
return buildContext;
2127
}
2228
async function watchDictionary(): Promise<number> {
2329
const command = new Deno.Command(Deno.execPath(), {
2430
args: [
2531
"run",
32+
"-E=NO_COLOR",
2633
"-R=./dictionary/dictionary",
2734
"-W=./dictionary/dictionary.ts",
2835
"--no-prompt",
@@ -43,17 +50,17 @@ async function watchDictionary(): Promise<number> {
4350
return status.code;
4451
}
4552
if (import.meta.main) {
46-
let statusCode: number;
47-
{
48-
if (
49-
!await exists(new URL("../dictionary/dictionary.ts", import.meta.url))
50-
) {
51-
const Dictionary = await import("../dictionary/build.ts");
52-
await Dictionary.build();
53+
if (!await exists(DICTIONARY)) {
54+
const Dictionary = await import("../dictionary/build.ts");
55+
if (!await Dictionary.build()) {
56+
await Dictionary.buildWithDictionary(new Map());
57+
// deno-lint-ignore no-console
58+
console.error(
59+
"Dictionary failed to build. Empty dictionary is used instead. Please fix it.",
60+
);
5361
}
54-
const statusCodePromise = watchDictionary();
55-
await using _ = await watchMain();
56-
statusCode = await statusCodePromise;
5762
}
58-
Deno.exit(statusCode);
63+
const statusCodePromise = watchDictionary();
64+
await using _ = await watchMain();
65+
Deno.exitCode = await statusCodePromise;
5966
}

deno.json

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
},
1919
"update": {
2020
"description": "Updates dependencies and telo misikeke",
21-
"command": "deno outdated --update && deno run -N=api.linku.la,gitlab.com -W=./telo_misikeke/linku_data.json,./telo_misikeke/Parser.js,./telo_misikeke/rules.js --no-prompt --frozen --cached-only ./telo_misikeke/update.ts"
21+
"command": "deno outdated --update && deno run -N=gitlab.com -W=./telo_misikeke/linku_data.json,./telo_misikeke/Parser.js,./telo_misikeke/rules.js --no-prompt --frozen --cached-only ./telo_misikeke/update.ts"
2222
},
2323
"build-dictionary": {
2424
"description": "Builds the dictionary at `./dictionary/dictionary.ts`",
25-
"command": "deno run -R=./dictionary/dictionary -W=./dictionary/dictionary.ts --no-prompt --frozen --cached-only ./dictionary/build.ts"
25+
"command": "deno run -E=NO_COLOR -R=./dictionary/dictionary -W=./dictionary/dictionary.ts --no-prompt --frozen --cached-only ./dictionary/build.ts"
2626
}
2727
},
2828
"fmt": {
@@ -55,7 +55,6 @@
5555
"no-self-compare",
5656
"no-sparse-arrays",
5757
"no-sync-fn-in-async-fn",
58-
"no-throw-literal",
5958
"no-useless-rename",
6059
"prefer-ascii",
6160
"single-var-declarator"
@@ -69,7 +68,7 @@
6968
"@std/async": "jsr:@std/async@^1.0.12",
7069
"@std/cache": "jsr:@std/cache@^0.2.0",
7170
"@std/collections": "jsr:@std/collections@^1.0.10",
72-
"@std/fs": "jsr:@std/fs@^1.0.15",
71+
"@std/fs": "jsr:@std/fs@^1.0.16",
7372
"@std/html": "jsr:@std/html@^1.0.3",
7473
"@std/random": "jsr:@std/random@^0.1.0",
7574
"@std/regexp": "jsr:@std/regexp@^1.0.1",

deno.lock

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

dictionary/build.ts

Lines changed: 97 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
// This code is Deno only
22

3-
import { parseDictionary } from "./parser.ts";
3+
// deno-lint-ignore-file no-console
4+
5+
import { ArrayResultError } from "../src/array_result.ts";
6+
import { PositionedError } from "../src/parser/parser_lib.ts";
7+
import { dictionaryParser } from "./parser.ts";
8+
import { Dictionary } from "./type.ts";
49

510
const SOURCE = new URL("./dictionary", import.meta.url);
611
const DESTINATION = new URL("./dictionary.ts", import.meta.url);
712

8-
export async function build(): Promise<void> {
9-
// deno-lint-ignore no-console
10-
console.log("Building dictionary...");
11-
const text = await Deno.readTextFile(SOURCE);
13+
export async function buildWithDictionary(
14+
dictionary: Dictionary,
15+
): Promise<void> {
1216
const json = JSON.stringify(
13-
Object.fromEntries(parseDictionary(text)),
17+
Object.fromEntries(dictionary),
1418
undefined,
1519
2,
1620
);
@@ -22,9 +26,93 @@ import { Dictionary } from "./type.ts";
2226
export const dictionary: Dictionary = new Map(Object.entries(${json}));
2327
`;
2428
await Deno.writeTextFile(DESTINATION, code);
25-
// deno-lint-ignore no-console
26-
console.log("Building dictionary done");
29+
}
30+
export async function build(): Promise<boolean> {
31+
console.log("Building dictionary...");
32+
const start = performance.now();
33+
const text = await Deno.readTextFile(SOURCE);
34+
const startDictionary = performance.now();
35+
const result = dictionaryParser.parse(text);
36+
const endDictionary = performance.now();
37+
let dictionary: Dictionary;
38+
if (!result.isError()) {
39+
dictionary = result.array[0];
40+
} else {
41+
displayError(text, result.errors);
42+
return false;
43+
}
44+
await buildWithDictionary(dictionary);
45+
const end = performance.now();
46+
const total = Math.floor(end - start);
47+
const parsing = Math.floor(endDictionary - startDictionary);
48+
console.log(
49+
`Building dictionary done in ${total}ms (parsing dictionary took ${parsing}ms)`,
50+
);
51+
return true;
52+
}
53+
function displayError(
54+
source: string,
55+
errors: ReadonlyArray<ArrayResultError>,
56+
): void {
57+
let color: boolean;
58+
try {
59+
color = Deno.env.get("NO_COLOR") !== "1";
60+
} catch (error) {
61+
if (error instanceof Deno.errors.NotCapable) {
62+
color = true;
63+
} else {
64+
throw error;
65+
}
66+
}
67+
const red = color ? "color: red" : "";
68+
const sourceStyle = color ? "color: blue" : "";
69+
for (const error of errors) {
70+
console.error(`%cError%c: ${error.message}`, red, "");
71+
if (error instanceof PositionedError && error.position != null) {
72+
const { position, length } = error.position;
73+
const end = position + length;
74+
// The only instance returning -1 is useful
75+
const startLine = source.lastIndexOf("\n", position) + 1;
76+
let currentLine = startLine;
77+
let currentPosition = position;
78+
79+
while (true) {
80+
const index = source.indexOf("\n", currentLine);
81+
const nextLine = index === -1 ? source.length : index + 1;
82+
const line = source.slice(currentLine, nextLine).trimEnd();
83+
console.error(line);
84+
let relativeStart = Math.min(
85+
currentPosition - currentLine,
86+
line.length,
87+
);
88+
let relativeEnd = Math.min(end - currentLine, line.length);
89+
if (relativeEnd - relativeStart === 0) {
90+
if (relativeStart !== 0) {
91+
relativeStart--;
92+
}
93+
if (relativeEnd !== line.length) {
94+
relativeEnd++;
95+
}
96+
}
97+
console.error(
98+
`${" ".repeat(relativeStart)}%c${
99+
"^".repeat(relativeEnd - relativeStart)
100+
}`,
101+
red,
102+
);
103+
if (end <= nextLine) {
104+
break;
105+
} else {
106+
currentLine = currentPosition = nextLine;
107+
}
108+
}
109+
const line = source.slice(0, startLine).match(/\n/g)?.length ?? 1;
110+
const column = position - startLine + 1;
111+
console.error(` at %c${SOURCE}:${line}:${column}`, sourceStyle);
112+
console.error();
113+
}
114+
}
27115
}
28116
if (import.meta.main) {
29-
await build();
117+
Deno.exitCode = await build() ? 0 : 1;
30118
}

0 commit comments

Comments
 (0)