typing.works 0.0.0-stage → 0.3.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ typing.works — terminal
2
+ Copyright © 2026 Perspective. All rights reserved.
3
+
4
+ 이 소프트웨어(실행 파일과 함께 배포되는 파일)는 무료로 내려받아 개인적·비상업적으로 쓸 수 있습니다.
5
+ 다음은 허락하지 않습니다: 수정, 재배포·재판매, 역설계·디컴파일·분해(관련 법이 명시적으로 허용하는 범위를 넘어서),
6
+ typing.works 서비스에 대한 자동화된 남용(랭크 기록 조작 등).
7
+
8
+ You may download and use this software free of charge for personal, non-commercial use.
9
+ You may not modify, redistribute or resell it, or reverse engineer, decompile or disassemble it
10
+ (except to the extent applicable law expressly permits), or use it to abuse the typing.works service.
11
+
12
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. IN NO EVENT SHALL THE
13
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY ARISING FROM THE SOFTWARE
14
+ OR ITS USE.
15
+
16
+ typing.works 서비스 이용에는 typing.works 이용약관과 개인정보처리방침이 적용됩니다.
package/README.md CHANGED
@@ -1,3 +1,83 @@
1
- # Temporary Holding Version
1
+ # typing.works — terminal (beta)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 터미널에서 치는 [typing.works](https://typing.works). 한글·영문 타자 연습, 웹과 같은 판정, 로그인하면 기록·통계·랭크전까지.
4
+ Typing practice from [typing.works](https://typing.works), in your terminal — Korean & English, same scoring as the web, records, stats and ranked matches.
5
+
6
+ ## 설치 · Install
7
+
8
+ macOS · Linux
9
+
10
+ ```sh
11
+ curl -fsSL https://cdn.jsdelivr.net/npm/typing.works/install.sh | sh
12
+ ```
13
+
14
+ Windows 10 · 11 (PowerShell)
15
+
16
+ ```powershell
17
+ irm https://cdn.jsdelivr.net/npm/typing.works/install.ps1 | iex
18
+ ```
19
+
20
+ 아무것도 미리 깔 필요가 없습니다. 실행 파일을 받아 해시를 대조하고 `~/.local/bin`(Windows 는 `%LOCALAPPDATA%\typingworks\bin`)에 둡니다 — 그다음 `typingworks`.
21
+ Nothing else needed. Downloads the binary, verifies its checksum, puts it on your PATH — then run `typingworks`.
22
+
23
+ 다른 방법 · Other ways:
24
+
25
+ ```sh
26
+ npx typing.works # Node 가 있으면, 설치 없이 바로 · run without installing
27
+ npm i -g typing.works # Node · install → `typingworks`
28
+ brew install pers-dev/tap/typing.works # Homebrew
29
+ ```
30
+
31
+ macOS (Apple Silicon · Intel) · Linux (x64 · arm64 · 32-bit x86) · Windows 10 1809+ · 11 (x64 · arm64, Windows Terminal 권장).
32
+ 통신(로그인 · 기록)에만 `curl` 을 씁니다(Windows 10+ 에 들어 있습니다). 인터넷 없이도 연습 · 판정 · 기록은 그대로 됩니다.
33
+ Works offline; `curl` is used only for sign-in, records and ranked (built into Windows 10+).
34
+
35
+ ## 쓰는 법 · Keys
36
+
37
+ 켜면 바로 단문을 칩니다. · It opens straight into typing.
38
+
39
+ | 키 | |
40
+ |---|---|
41
+ | Enter · Space | 문장 끝 · finish |
42
+ | Esc | 처음부터 · restart |
43
+ | ↑ ↓ | 다음·이전 문장 · next/prev |
44
+ | Tab | 한/영 — 입력기는 영문으로 두고 두벌식 자리 그대로 · Korean/English (keep your OS input in English) |
45
+ | ^S ^L ^P | 단문 · 장문 · 팬그램 · sentence · paragraph · pangram |
46
+ | ^E | 문장 언어 · language |
47
+ | ^Z | 문장 크게/보통(macOS 터미널 · xterm) · bigger text |
48
+ | ^R | 기록 · 통계 · records & stats |
49
+ | ^K | 랭크전 · ranked |
50
+ | ^O ^A ^G ^Q | 설정 · 계정 · 도움말 · 끝 · settings · account · help · quit |
51
+
52
+ 계정은 typing.works 와 같습니다. 한글은 한글이 든 고정폭 글꼴(D2Coding · Sarasa Mono K 등)에서 가장 보기 좋습니다.
53
+
54
+ ## 익명 사용 통계 · Anonymous usage stats
55
+
56
+ 어떻게 쓰이는지 알려고 아주 적은 것만 보냅니다. · We send a small amount of anonymous data to learn how it's used.
57
+
58
+ - **보내는 것 · sent**: 켰다 · 묶음을 끝냈다(언어 · 갈래 · 문장 수 · 평균 타/분 · 정확도) · 랭크 판 결과 · 로그인했다 — 판 번호 · OS · 터미널 이름과 함께. 사람이 아니라 이 기기에서 만든 난수 ID로 셉니다.
59
+ - **보내지 않는 것 · never sent**: 친 글 · 문장 · 계정(이메일 · 닉네임).
60
+ - **끄기 · opt out**: 설정(^O) «익명 사용 통계» · `TW_NO_TELEMETRY=1` · `DO_NOT_TRACK=1` · `typingworks --no-telemetry`
61
+ - **무엇이 나가는지 보기 · see exactly what is sent**: `TW_TELEMETRY_LOG=~/tw-telemetry.log typingworks`
62
+
63
+ ## 새 판 · Updates
64
+
65
+ 켤 때(6시간에 한 번) npm 에 새 판이 있는지 보고, 있으면 오른쪽 위에 알립니다. **^U** 를 누르면 깐 방법대로 올리고 새 판으로 다시 켭니다.
66
+ Checks npm for a newer version (every 6 hours) and shows it top-right. Press **^U** to update the way you installed it and restart.
67
+
68
+ | 깐 방법 · installed with | ^U 가 돌리는 것 · runs |
69
+ |---|---|
70
+ | brew | `brew upgrade typing.works` |
71
+ | npm i -g | `npm i -g typing.works@latest` |
72
+ | npx | `npx typing.works@latest` |
73
+ | 설치 스크립트 · install script | 같은 스크립트를 다시 · reruns `install.sh` / `install.ps1` |
74
+
75
+ 끄기 · disable: `TW_NO_UPDATE_CHECK=1`
76
+
77
+ ## 저장 · Data
78
+
79
+ `~/.typingworks` — 설정 · 이 기기의 기록 · 로그인 토큰(이 파일에만, 권한 600). 지우면 처음 상태가 됩니다.
80
+
81
+ ## License
82
+
83
+ © 2026 Perspective. All rights reserved. 무료로 쓸 수 있습니다. 자세한 것은 LICENSE.
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ // typing.works — 이 기기에 맞는 실행 파일을 골라 그대로 넘긴다(입출력 · 종료 코드 · 신호 그대로). 설치 스크립트는 없다.
3
+ "use strict";
4
+ const { spawnSync } = require("child_process");
5
+ const path = require("path");
6
+ const fs = require("fs");
7
+ const key = `${process.platform}-${process.arch}`;
8
+ const exe = path.join(__dirname, "..", "vendor", key, process.platform === "win32" ? "typingworks.exe" : "typingworks");
9
+ if (!fs.existsSync(exe)) {
10
+ console.error(`typing.works: ${key} 은 아직 지원하지 않습니다 — macOS · Linux(x64 · arm64 · x86) · Windows(x64 · arm64).`);
11
+ console.error(`typing.works: ${key} is not supported yet — macOS, Linux and Windows (x64 · arm64).`);
12
+ process.exit(1);
13
+ }
14
+ try { fs.accessSync(exe, fs.constants.X_OK); } catch { try { fs.chmodSync(exe, 0o755); } catch {} }
15
+ const r = spawnSync(exe, process.argv.slice(2), { stdio: "inherit" });
16
+ if (r.error) { console.error(`typing.works: ${r.error.message}`); process.exit(1); }
17
+ if (r.signal) process.kill(process.pid, r.signal);
18
+ process.exit(r.status === null ? 1 : r.status);
package/install.ps1 ADDED
@@ -0,0 +1,97 @@
1
+ # typing.works - terminal installer for Windows
2
+ # irm https://cdn.jsdelivr.net/npm/typing.works/install.ps1 | iex
3
+ #
4
+ # What it does
5
+ # 1. Downloads the typing.works npm package (about 2 MB, holds all seven binaries) and takes the one for this PC
6
+ # (Windows 10 1809+ / 11, x64 or arm64)
7
+ # 2. Verifies it against the sha512 the npm registry publishes - stops on mismatch
8
+ # 3. Puts typingworks.exe and typing.works.exe in %LOCALAPPDATA%\typingworks\bin (override: TW_INSTALL_DIR)
9
+ # 4. Adds that folder to your user PATH (skip: TW_NO_MODIFY_PATH=1)
10
+ # The version follows the latest "typing.works" on npm (pin: TW_VERSION). Ctrl+U in the app re-runs this script.
11
+ # No source code is downloaded - only the binary, README and LICENSE.
12
+ # Uninstall: delete that folder and %USERPROFILE%\.typingworks
13
+ # (ASCII only on purpose: Windows PowerShell 5.1 reads BOM-less script files in the ANSI code page.)
14
+ & {
15
+ $ErrorActionPreference = 'Stop'
16
+ $ProgressPreference = 'SilentlyContinue' # the progress bar slows downloads a lot on PowerShell 5.1
17
+ [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
18
+ $reg = if ($env:TW_REGISTRY) { $env:TW_REGISTRY } else { 'https://registry.npmjs.org' } # an npm mirror, if you use one
19
+ $dir = if ($env:TW_INSTALL_DIR) { $env:TW_INSTALL_DIR } else { Join-Path $env:LOCALAPPDATA 'typingworks\bin' }
20
+
21
+ # The real CPU - pick arm64 even when x64 PowerShell runs under emulation on ARM
22
+ $arch = $null
23
+ try { $arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString() } catch { }
24
+ if (-not $arch) { $arch = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } }
25
+ switch -regex ($arch) {
26
+ '^(Arm64|ARM64)$' { $arch = 'arm64' }
27
+ '^(X64|AMD64)$' { $arch = 'x64' }
28
+ default { throw "typing.works: $arch is not supported yet (Windows x64 / arm64)" }
29
+ }
30
+
31
+ # Version and the package's sha512 in one request - latest unless TW_VERSION is set
32
+ $tag = if ($env:TW_VERSION) { $env:TW_VERSION } else { 'latest' }
33
+ $meta = $null
34
+ try { $meta = Invoke-RestMethod -UseBasicParsing "$reg/typing.works/$tag" } catch { }
35
+ if (-not $meta -or -not $meta.version -or -not $meta.dist.integrity) { throw 'typing.works: could not read the npm registry (check your internet connection)' }
36
+ $ver = $meta.version
37
+ $integrity = $meta.dist.integrity
38
+ if ($integrity -notlike 'sha512-*') { throw "typing.works: unexpected integrity format: $integrity" }
39
+ $tar = (Get-Command tar.exe -ErrorAction SilentlyContinue).Source # built in since Windows 10 1803
40
+ if (-not $tar) { throw 'typing.works: tar.exe was not found (Windows 10 1803 or later is needed)' }
41
+ # Download with the built-in curl.exe (Windows 10 1803+). PowerShell 5.1's Invoke-WebRequest follows GitHub's redirect to a
42
+ # signed asset URL but mangles the signature and gets 404 (seen 2026-10-13). Fall back to it only when curl.exe is missing.
43
+ $curl = (Get-Command curl.exe -ErrorAction SilentlyContinue).Source
44
+ function Get-File([string]$from, [string]$to) {
45
+ if ($curl -and $from -notlike 'file:*') {
46
+ & $curl -fsSL --retry 2 -o $to $from
47
+ if ($LASTEXITCODE -ne 0) { throw "typing.works: download failed ($LASTEXITCODE): $from" }
48
+ } else {
49
+ Invoke-WebRequest -UseBasicParsing $from -OutFile $to
50
+ }
51
+ }
52
+ $tmp = Join-Path ([IO.Path]::GetTempPath()) ('typingworks-' + [guid]::NewGuid().ToString('N'))
53
+ New-Item -ItemType Directory -Path $tmp | Out-Null
54
+ try {
55
+ Write-Host "typing.works $ver (win32-$arch) downloading..."
56
+ $tgz = Join-Path $tmp "typing.works-$ver.tgz"
57
+ Get-File "$reg/typing.works/-/typing.works-$ver.tgz" $tgz
58
+ $want = -join ([Convert]::FromBase64String($integrity.Substring(7)) | ForEach-Object { $_.ToString('x2') })
59
+ $got = (Get-FileHash -Algorithm SHA512 $tgz).Hash.ToLower()
60
+ if ($got -ne $want) { throw 'typing.works: checksum mismatch - not installed' }
61
+ $inner = "package/vendor/win32-$arch/typingworks.exe"
62
+ & $tar -xzf $tgz -C $tmp $inner
63
+ if ($LASTEXITCODE -ne 0) { throw "typing.works: could not extract $inner" }
64
+
65
+ New-Item -ItemType Directory -Force -Path $dir | Out-Null
66
+ # A running .exe cannot be deleted but can be renamed - move the old one aside, then place the new one (Ctrl+U comes this way)
67
+ foreach ($n in @('typingworks.exe', 'typing.works.exe')) {
68
+ $p = Join-Path $dir $n
69
+ Remove-Item ($p + '.old') -Force -ErrorAction SilentlyContinue
70
+ if (Test-Path $p) { Move-Item $p ($p + '.old') -Force }
71
+ }
72
+ $exe = Join-Path $dir 'typingworks.exe'
73
+ Copy-Item (Join-Path $tmp ("package\vendor\win32-$arch\typingworks.exe")) $exe
74
+ Copy-Item $exe (Join-Path $dir 'typing.works.exe') # same program under both names
75
+ foreach ($n in @('typingworks.exe.old', 'typing.works.exe.old')) { Remove-Item (Join-Path $dir $n) -Force -ErrorAction SilentlyContinue }
76
+
77
+ # Tell the app it was installed by this script, so Ctrl+U re-runs it (UTF-8 without BOM - user folders may be non-ASCII)
78
+ $tw = Join-Path $HOME '.typingworks'
79
+ New-Item -ItemType Directory -Force -Path $tw | Out-Null
80
+ [IO.File]::WriteAllText((Join-Path $tw 'install-script'), $exe + "`n", (New-Object Text.UTF8Encoding $false))
81
+
82
+ Write-Host "OK typing.works $ver -> $exe"
83
+ $userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
84
+ $has = $false
85
+ if ($userPath) { foreach ($e in $userPath.Split(';')) { if ($e.TrimEnd('\') -ieq $dir.TrimEnd('\')) { $has = $true } } }
86
+ if (-not $has -and $env:TW_NO_MODIFY_PATH -ne '1') {
87
+ $new = if ($userPath) { $userPath.TrimEnd(';') + ';' + $dir } else { $dir }
88
+ [Environment]::SetEnvironmentVariable('Path', $new, 'User')
89
+ $env:Path = $env:Path.TrimEnd(';') + ';' + $dir
90
+ Write-Host " added $dir to your PATH - open a new terminal, then run: typingworks"
91
+ } else {
92
+ Write-Host ' run: typingworks'
93
+ }
94
+ } finally {
95
+ Remove-Item $tmp -Recurse -Force -ErrorAction SilentlyContinue
96
+ }
97
+ }
package/install.sh ADDED
@@ -0,0 +1,97 @@
1
+ #!/bin/sh
2
+ # typing.works — terminal 설치 · install
3
+ # curl -fsSL https://cdn.jsdelivr.net/npm/typing.works/install.sh | sh
4
+ #
5
+ # 하는 일 · what it does
6
+ # 1. npm 의 typing.works 꾸러미(실행 파일 일곱 가지가 든 약 2MB)를 받아 이 기기(macOS · Linux, arm64 · x64 · x86)에 맞는 것만 꺼낸다
7
+ # 2. npm 이 알려 주는 sha512 와 대조한다 — 다르면 멈춘다
8
+ # 3. ~/.local/bin 에 typingworks 와 typing.works 를 둔다(TW_INSTALL_DIR 로 바꿀 수 있다)
9
+ # 4. 그 폴더가 PATH 에 없으면 셸 설정 파일에 한 줄 더하고 알린다
10
+ # 판 번호는 npm 의 typing.works 최신 판을 따른다(TW_VERSION=0.3.0 처럼 고를 수 있다). 앱 안 ^U 가 이 스크립트를 다시 돌린다.
11
+ # 소스 코드는 없다 — npm 꾸러미에는 실행 파일 · 설명서 · 라이선스 · 이 스크립트뿐. 지우기: rm ~/.local/bin/typingworks ~/.local/bin/typing.works ; rm -rf ~/.typingworks
12
+ set -eu
13
+
14
+ REG="${TW_REGISTRY:-https://registry.npmjs.org}" # npm 미러를 쓰는 곳이면 바꾼다
15
+ DIR="${TW_INSTALL_DIR:-$HOME/.local/bin}"
16
+ say() { printf '%s\n' "$*"; }
17
+ die() { printf 'typing.works: %s\n' "$*" >&2; exit 1; }
18
+
19
+ command -v curl >/dev/null 2>&1 || die "curl 이 필요합니다 · curl is required"
20
+ command -v tar >/dev/null 2>&1 || die "tar 가 필요합니다 · tar is required"
21
+
22
+ os="$(uname -s)"; arch="$(uname -m)"
23
+ case "$os" in
24
+ Darwin) os=darwin ;;
25
+ Linux) os=linux ;;
26
+ *) die "$os 은 아직 지원하지 않습니다 — macOS · Linux (Windows 는 PowerShell 설치를 쓰세요) · $os is not supported yet" ;;
27
+ esac
28
+ case "$arch" in
29
+ arm64|aarch64) arch=arm64 ;;
30
+ x86_64|amd64) arch=x64 ;;
31
+ i386|i486|i586|i686) arch=ia32 ;;
32
+ *) die "$arch 은 아직 지원하지 않습니다 · $arch is not supported yet" ;;
33
+ esac
34
+ [ "$os" = darwin ] && [ "$arch" = ia32 ] && die "32비트 macOS 는 지원하지 않습니다 · 32-bit macOS is not supported"
35
+ # Rosetta 로 돌린 셸이어도 진짜 칩에 맞춘다
36
+ if [ "$os" = darwin ] && [ "$arch" = x64 ] && [ "$(sysctl -n sysctl.proc_translated 2>/dev/null || echo 0)" = 1 ]; then arch=arm64; fi
37
+
38
+ # 판 번호와 꾸러미의 sha512 를 한 번에 — 판을 안 주면 latest
39
+ meta="$(curl -fsSL "$REG/typing.works/${TW_VERSION:-latest}")" || die "판 정보를 못 읽었습니다(인터넷 연결을 확인하세요) · could not reach the npm registry"
40
+ ver="$(printf '%s' "$meta" | grep -o '"version":"[^"]*"' | head -n 1 | cut -d'"' -f4)"
41
+ integ="$(printf '%s' "$meta" | grep -o '"integrity":"sha512-[^"]*"' | head -n 1 | cut -d'"' -f4)"
42
+ [ -n "$ver" ] && [ -n "$integ" ] || die "판 정보가 이상합니다 · unexpected registry response"
43
+
44
+ # base64 → 16진수(base64 -d 는 GNU · 새 macOS, -D 는 옛 macOS, 없으면 openssl)
45
+ b64hex() {
46
+ for d in "base64 -d" "base64 -D" "openssl base64 -d -A"; do
47
+ h="$(printf '%s' "$1" | $d 2>/dev/null | od -An -v -tx1 | tr -d ' \n')"
48
+ [ -n "$h" ] && { printf '%s' "$h"; return 0; }
49
+ done
50
+ return 1
51
+ }
52
+ want="$(b64hex "${integ#sha512-}")" || die "sha512 를 풀 도구가 없습니다 · no base64 tool"
53
+
54
+ tmp="$(mktemp -d 2>/dev/null || mktemp -d -t typingworks)"
55
+ trap 'rm -rf "$tmp"' EXIT INT TERM
56
+ tgz="$tmp/typing.works-$ver.tgz"
57
+
58
+ say "typing.works $ver ($os-$arch) 받는 중 · downloading…"
59
+ curl -fsSL "$REG/typing.works/-/typing.works-$ver.tgz" -o "$tgz" || die "받지 못했습니다 · download failed"
60
+ if command -v sha512sum >/dev/null 2>&1; then got="$(sha512sum "$tgz" | cut -d' ' -f1)"
61
+ elif command -v shasum >/dev/null 2>&1; then got="$(shasum -a 512 "$tgz" | cut -d' ' -f1)"
62
+ elif command -v openssl >/dev/null 2>&1; then got="$(openssl dgst -sha512 -r "$tgz" | cut -d' ' -f1)"
63
+ else die "sha512 도구가 없어 대조할 수 없습니다 · no sha512 tool"; fi
64
+ [ "$got" = "$want" ] || die "해시가 다릅니다 — 설치하지 않았습니다 · checksum mismatch, not installed"
65
+
66
+ tar -xzf "$tgz" -C "$tmp" "package/vendor/$os-$arch/typingworks" || die "풀지 못했습니다 · could not extract"
67
+ mv "$tmp/package/vendor/$os-$arch/typingworks" "$tmp/typingworks"
68
+ mkdir -p "$DIR"
69
+ # 같은 폴더에 새 이름으로 둔 뒤 바꿔 끼운다 — 돌고 있는 typingworks 가 있어도 안전하다(^U 가 이 길로 온다)
70
+ cp "$tmp/typingworks" "$DIR/.typingworks.new"
71
+ chmod 755 "$DIR/.typingworks.new"
72
+ mv -f "$DIR/.typingworks.new" "$DIR/typingworks"
73
+ ln -sf typingworks "$DIR/typing.works"
74
+
75
+ # 앱이 «스크립트로 깔았다»를 알게 — ^U 가 이 스크립트를 다시 돌린다
76
+ mkdir -p "$HOME/.typingworks"
77
+ printf '%s\n' "$DIR/typingworks" > "$HOME/.typingworks/install-script"
78
+
79
+ say "✓ typing.works $ver → $DIR/typingworks"
80
+
81
+ case ":$PATH:" in
82
+ *":$DIR:"*) say " 실행 · run: typingworks" ;;
83
+ *)
84
+ line="export PATH=\"$DIR:\$PATH\""
85
+ case "${SHELL:-}" in
86
+ */zsh) rc="$HOME/.zshrc" ;;
87
+ */bash) if [ "$os" = darwin ]; then rc="$HOME/.bash_profile"; else rc="$HOME/.bashrc"; fi ;;
88
+ *) rc="$HOME/.profile" ;;
89
+ esac
90
+ if [ "${TW_NO_MODIFY_PATH:-}" != 1 ] && ! grep -qsF "$line" "$rc"; then
91
+ printf '\n# typing.works\n%s\n' "$line" >> "$rc"
92
+ say " $DIR 를 PATH 에 더했습니다($rc) · added to PATH"
93
+ fi
94
+ say " 새 터미널을 열거나 · open a new terminal, or: $line"
95
+ say " 실행 · run: typingworks"
96
+ ;;
97
+ esac
package/package.json CHANGED
@@ -1,6 +1,17 @@
1
1
  {
2
2
  "name": "typing.works",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.0-beta.10",
4
+ "description": "typing.works in your terminal — Korean & English typing practice, records, stats and ranked matches",
5
+ "bin": {
6
+ "typing.works": "bin/typing.works.js",
7
+ "typingworks": "bin/typing.works.js"
8
+ },
9
+ "files": ["bin", "vendor", "install.sh", "install.ps1", "README.md", "LICENSE"],
10
+ "os": ["darwin", "linux", "win32"],
11
+ "cpu": ["arm64", "x64", "ia32"],
12
+ "engines": { "node": ">=14" },
13
+ "license": "SEE LICENSE IN LICENSE",
14
+ "homepage": "https://typing.works",
15
+ "author": "typing.works",
16
+ "keywords": ["typing", "typing-practice", "typing-test", "korean", "hangul", "terminal", "tui", "cli", "wpm"]
17
+ }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file