From 163536bb98385e7bf17adfd84336a004a8fedb69 Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Tue, 6 Jan 2026 19:13:21 +0900 Subject: [PATCH 1/4] =?UTF-8?q?copyAllDTSFiles=E3=82=92scripts=E3=83=87?= =?UTF-8?q?=E3=82=A3=E3=83=AC=E3=82=AF=E3=83=88=E3=83=AA=E3=81=AB=E7=A7=BB?= =?UTF-8?q?=E5=8B=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- copyAllDTSFiles.ts => scripts/copyAllDTSFiles.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename copyAllDTSFiles.ts => scripts/copyAllDTSFiles.ts (91%) diff --git a/package.json b/package.json index dde9ba0..e6d08b7 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint": "npm run cf-typegen && next lint", "tsc": "npm run cf-typegen && tsc", "format": "prettier --write app/", - "copyAllDTSFiles": "tsx ./copyAllDTSFiles.ts", + "copyAllDTSFiles": "tsx ./scripts/copyAllDTSFiles.ts", "cf-preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview --port 3000", "cf-deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy", "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts" diff --git a/copyAllDTSFiles.ts b/scripts/copyAllDTSFiles.ts similarity index 91% rename from copyAllDTSFiles.ts rename to scripts/copyAllDTSFiles.ts index fe3b647..1aafd9f 100644 --- a/copyAllDTSFiles.ts +++ b/scripts/copyAllDTSFiles.ts @@ -1,7 +1,7 @@ // node_modules/typescript/lib からd.tsファイルをすべてpublic/typescript/version/にコピーする。 import { knownLibFilesForCompilerOptions } from "@typescript/vfs"; -import { compilerOptions } from "./app/terminal/typescript/runtime"; +import { compilerOptions } from "../app/terminal/typescript/runtime"; import ts from "typescript"; import fs from "node:fs/promises"; import { existsSync } from "node:fs"; From b4012c4dbe6365fad6120d56687d28d3264fe016 Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:09:50 +0900 Subject: [PATCH 2/4] =?UTF-8?q?m-plus-rounded-1c=E3=81=8B=E3=82=89hinting?= =?UTF-8?q?=E3=82=92=E6=B6=88=E3=81=97=E3=81=9F=E3=82=82=E3=81=AE=E3=82=92?= =?UTF-8?q?public/=E3=81=AB=E6=9B=B8=E3=81=8D=E5=87=BA=E3=81=97=E3=81=A6?= =?UTF-8?q?=E4=BD=BF=E3=81=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + app/globals.css | 17 +++--- app/layout.tsx | 6 ++- app/lib/auth.ts | 2 +- app/terminal/terminal.tsx | 2 +- package-lock.json | 71 +++++++++++++++---------- package.json | 8 ++- public/_headers | 4 ++ scripts/removeHinting.ts | 109 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 176 insertions(+), 44 deletions(-) create mode 100644 scripts/removeHinting.ts diff --git a/.gitignore b/.gitignore index 181e30d..2128524 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ next-env.d.ts /public/typescript/ +/public/m-plus-rounded-1c-nohint/ diff --git a/app/globals.css b/app/globals.css index 9f1c86b..3df0776 100644 --- a/app/globals.css +++ b/app/globals.css @@ -129,22 +129,21 @@ mycdark: 確実にフォントを統一するためにRoundedM+を指定することにした 以前NotoSansJPを指定していたが、xterm.jsで全角の()の幅がバグった */ - --font-mono: - "Inconsolata Variable", "Rounded M+ 1c", "Rounded M+ 1p", - "M PLUS Rounded 1c", monospace; + --font-mono: "Inconsolata Variable", "M PLUS Rounded 1c NoHint", monospace; /* 本家のフォント名は Rounded M+ 1c 、または1pでもいいかも - layout.tsxでインポートしているwebフォントが M PLUS Rounded 1c + layout.tsxでインポートしているwebフォントが M PLUS Rounded 1c NoHint + scripts/removeHinting.ts で M PLUS Rounded 1c からHintingを除去したものを使っている + (HintingがあるとWindowsでジャギーが発生する) それ以下はM+をダウンロードするまでの間表示されるswap用フォールバックとしてM+に見た目が近いものを指定。 Hiragino Maru Gothic は見た目はめっちゃきれいなんだけど太字がない :cry: - Meiryo は日本語の形がM+に近いが、英数がダメ */ --font-sans: - "Rounded M+ 1c", "Rounded M+ 1p", "M PLUS Rounded 1c", - /* 以下fallback */ "M+ 1c", "MigMix 1c", "Migu 1c", - "Hiragino Maru Gothic ProN", "Noto Sans", "Arial", "Liberation Sans", - "Meiryo", sans-serif, + "M PLUS Rounded 1c NoHint", /* 以下fallback */ "Rounded M+ 1c", + "Rounded M+ 1p", "M+ 1c", "MigMix 1c", "Migu 1c", + "Hiragino Maru Gothic ProN", "Segoe UI", "Noto Sans", "Arial", + "Liberation Sans", "BIZ UDゴシック", "Meiryo", sans-serif, /* TailwindCSSでデフォルトで指定されていた絵文字フォントは一応残しておく */ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; diff --git a/app/layout.tsx b/app/layout.tsx index 036996f..26d779a 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,7 +1,9 @@ import type { Metadata } from "next"; import "@fontsource-variable/inconsolata"; -import "@fontsource/m-plus-rounded-1c/400.css"; -import "@fontsource/m-plus-rounded-1c/700.css"; +// import "@fontsource/m-plus-rounded-1c/400.css"; +// import "@fontsource/m-plus-rounded-1c/700.css"; +import "@/../public/m-plus-rounded-1c-nohint/400.css"; +import "@/../public/m-plus-rounded-1c-nohint/700.css"; import "./globals.css"; import { Navbar } from "./navbar"; import { Sidebar } from "./sidebar"; diff --git a/app/lib/auth.ts b/app/lib/auth.ts index a74b4fa..67ecd7e 100644 --- a/app/lib/auth.ts +++ b/app/lib/auth.ts @@ -69,7 +69,7 @@ export async function getAuthServer( }, font: { defaultFamily: - "'Rounded M+ 1c', 'Rounded M+ 1p', 'M PLUS Rounded 1c', 'M+ 1c', 'MigMix 1c', 'Migu 1c', 'Hiragino Maru Gothic ProN', 'Noto Sans', 'Arial', 'Liberation Sans', sans-serif", + "'M PLUS Rounded 1c NoHint', 'Rounded M+ 1c', 'Rounded M+ 1p', 'M+ 1c', 'MigMix 1c', 'Migu 1c', 'Hiragino Maru Gothic ProN', 'Segoe UI', 'Noto Sans', 'Arial', 'Liberation Sans', 'BIZ UDゴシック', 'Meiryo', sans-serif", monoFamily: "Inconsolata, monospace", }, disableTitleBorder: true, diff --git a/app/terminal/terminal.tsx b/app/terminal/terminal.tsx index de5a8ce..efa3057 100644 --- a/app/terminal/terminal.tsx +++ b/app/terminal/terminal.tsx @@ -134,7 +134,7 @@ export function useTerminal(props: TerminalProps) { lineHeight: 1.2, letterSpacing: 0, fontFamily: - "'Inconsolata Variable', 'Rounded M+ 1c', 'Rounded M+ 1p', 'M PLUS Rounded 1c', monospace", + "'Inconsolata Variable', 'M PLUS Rounded 1c NoHint', monospace", theme: computeTerminalTheme(), }); terminalInstanceRef.current = term; diff --git a/package-lock.json b/package-lock.json index 5a6ee7c..97dcb0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "@types/mocha": "^10.0.10", "@types/node": "^20", "@types/object-inspect": "^1.13.0", + "@types/pako": "^2.0.4", "@types/pg": "^8.15.5", "@types/prismjs": "^1.26.5", "@types/react": "^19", @@ -58,6 +59,8 @@ "drizzle-kit": "^0.31.5", "eslint": "^9", "eslint-config-next": "~15.4.10", + "fonteditor-core": "^2.6.3", + "pako": "^2.1.0", "prettier": "^3.6.2", "prisma": "^6.18.0", "tailwindcss": "^4", @@ -8018,7 +8021,6 @@ "version": "1.4.5", "resolved": "https://registry.npmjs.org/@better-auth/core/-/core-1.4.5.tgz", "integrity": "sha512-dQ3hZOkUJzeBXfVEPTm2LVbzmWwka1nqd9KyWmB2OMlMfjr7IdUeBX4T7qJctF67d7QDhlX95jMoxu6JG0Eucw==", - "peer": true, "dependencies": { "@standard-schema/spec": "^1.0.0", "zod": "^4.1.12" @@ -8048,14 +8050,12 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/@better-auth/utils/-/utils-0.3.0.tgz", "integrity": "sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@better-fetch/fetch": { "version": "1.1.18", "resolved": "https://registry.npmjs.org/@better-fetch/fetch/-/fetch-1.1.18.tgz", - "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==", - "peer": true + "integrity": "sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA==" }, "node_modules/@bjorn3/browser_wasi_shim": { "version": "0.3.0", @@ -8256,7 +8256,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -9991,6 +9990,7 @@ "integrity": "sha512-I5sbpSIAHiB+b6UttofhrN/UJXII+4tZPAq1qugzwCwLIL8EZLV7F/JyHUrEIiGgQpEXzpnjlJ+zwcEhheGvCw==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "@types/node": "^22.15.30", "@types/pg": "^8.8.0" @@ -10005,6 +10005,7 @@ "integrity": "sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog==", "license": "MIT", "optional": true, + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -10158,7 +10159,6 @@ "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", "license": "MIT", - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -12473,6 +12473,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/pako": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz", + "integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/pg": { "version": "8.15.5", "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz", @@ -12496,7 +12503,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -12573,7 +12579,6 @@ "integrity": "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/types": "8.46.0", @@ -13103,6 +13108,16 @@ "win32" ] }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xterm/addon-fit": { "version": "0.11.0-beta.115", "resolved": "https://registry.npmjs.org/@xterm/addon-fit/-/addon-fit-0.11.0-beta.115.tgz", @@ -13116,8 +13131,7 @@ "version": "5.6.0-beta.115", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.6.0-beta.115.tgz", "integrity": "sha512-EJXAW6dbxPuwQnLfTmPB5R3M5uu8qp24ltHdjCcfwGpudKxQRoDEbq1IeGrVLIuRc/8TbnT1U07dXUX7kyGYEQ==", - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/abort-controller": { "version": "3.0.0", @@ -13155,7 +13169,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -13648,7 +13661,6 @@ "resolved": "https://registry.npmjs.org/better-call/-/better-call-1.1.4.tgz", "integrity": "sha512-NJouLY6IVKv0nDuFoc6FcbKDFzEnmgMNofC9F60Mwx1Ecm7X6/Ecyoe5b+JSVZ42F/0n46/M89gbYP1ZCVv8xQ==", "license": "MIT", - "peer": true, "dependencies": { "@better-auth/utils": "^0.3.0", "@better-fetch/fetch": "^1.1.4", @@ -15020,7 +15032,6 @@ "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", "hasInstallScript": true, "license": "MIT", - "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -15101,7 +15112,6 @@ "integrity": "sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -15276,7 +15286,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -15880,6 +15889,15 @@ "dev": true, "license": "ISC" }, + "node_modules/fonteditor-core": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/fonteditor-core/-/fonteditor-core-2.6.3.tgz", + "integrity": "sha512-YUryIKjkenjZ41E7JvM3V+02Ak4mTHDDTwBWgs9KBzypzHqLZHuua1UDRevZNTKawmnq1dbBAa70Jddl2+F4FQ==", + "dev": true, + "dependencies": { + "@xmldom/xmldom": "^0.8.3" + } + }, "node_modules/for-each": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", @@ -17293,7 +17311,6 @@ "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz", "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/panva" } @@ -17420,7 +17437,6 @@ "resolved": "https://registry.npmjs.org/kysely/-/kysely-0.28.8.tgz", "integrity": "sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA==", "license": "MIT", - "peer": true, "engines": { "node": ">=20.0.0" } @@ -18174,7 +18190,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -18765,8 +18780,7 @@ "url": "https://opencollective.com/unified" } ], - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -19590,7 +19604,6 @@ } ], "license": "MIT", - "peer": true, "engines": { "node": "^20.0.0 || >=22.0.0" } @@ -19632,7 +19645,6 @@ "resolved": "https://registry.npmjs.org/next/-/next-15.4.10.tgz", "integrity": "sha512-itVlc79QjpKMFMRhP+kbGKaSG/gZM6RCvwhEbwmCNF06CdDiNaoHcbeg0PqkEa2GOcn8KJ0nnc7+yL7EjoYLHQ==", "license": "MIT", - "peer": true, "dependencies": { "@next/env": "15.4.10", "@swc/helpers": "0.5.15", @@ -20038,6 +20050,13 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "license": "BlueOak-1.0.0" }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -20150,7 +20169,6 @@ "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz", "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==", "license": "MIT", - "peer": true, "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", @@ -21833,7 +21851,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -22057,7 +22074,6 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -22105,7 +22121,6 @@ "resolved": "https://registry.npmjs.org/unenv/-/unenv-2.0.0-rc.24.tgz", "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", "license": "MIT", - "peer": true, "dependencies": { "pathe": "^2.0.3" } @@ -22115,7 +22130,6 @@ "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", "license": "MIT", - "peer": true, "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", @@ -22487,7 +22501,6 @@ "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.54.0.tgz", "integrity": "sha512-bANFsjDwJLbprYoBK+hUDZsVbUv2SqJd8QvArLIcZk+fPq4h/Ohtj5vkKXD3k0s2bD1DXLk08D+hYmeNH+xC6A==", "license": "MIT OR Apache-2.0", - "peer": true, "dependencies": { "@cloudflare/kv-asset-handler": "0.4.1", "@cloudflare/unenv-preset": "2.7.13", diff --git a/package.json b/package.json index e6d08b7..b33094a 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,14 @@ "private": true, "type": "module", "scripts": { - "dev": "npm run cf-typegen && npm run copyAllDTSFiles && next dev", - "build": "npm run cf-typegen && npm run copyAllDTSFiles && next build", + "dev": "npm run cf-typegen && npm run copyAllDTSFiles && npm run removeHinting && next dev", + "build": "npm run cf-typegen && npm run copyAllDTSFiles && npm run removeHinting && next build", "start": "next start", "lint": "npm run cf-typegen && next lint", "tsc": "npm run cf-typegen && tsc", "format": "prettier --write app/", "copyAllDTSFiles": "tsx ./scripts/copyAllDTSFiles.ts", + "removeHinting": "tsx ./scripts/removeHinting.ts", "cf-preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview --port 3000", "cf-deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy", "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts" @@ -57,6 +58,7 @@ "@types/mocha": "^10.0.10", "@types/node": "^20", "@types/object-inspect": "^1.13.0", + "@types/pako": "^2.0.4", "@types/pg": "^8.15.5", "@types/prismjs": "^1.26.5", "@types/react": "^19", @@ -66,6 +68,8 @@ "drizzle-kit": "^0.31.5", "eslint": "^9", "eslint-config-next": "~15.4.10", + "fonteditor-core": "^2.6.3", + "pako": "^2.1.0", "prettier": "^3.6.2", "prisma": "^6.18.0", "tailwindcss": "^4", diff --git a/public/_headers b/public/_headers index 133717c..2dbf410 100644 --- a/public/_headers +++ b/public/_headers @@ -4,3 +4,7 @@ Cross-Origin-Embedder-Policy: require-corp /typescript/* Cache-Control: public,max-age=31536000,immutable +/m-plus-rounded-1c-nohint/*.woff + Cache-Control: public,max-age=31536000,immutable +/m-plus-rounded-1c-nohint/*.woff2 + Cache-Control: public,max-age=31536000,immutable diff --git a/scripts/removeHinting.ts b/scripts/removeHinting.ts new file mode 100644 index 0000000..150e6dc --- /dev/null +++ b/scripts/removeHinting.ts @@ -0,0 +1,109 @@ +import { createFont, woff2 } from "fonteditor-core"; +import { existsSync } from "node:fs"; +import { mkdir, readdir, readFile, writeFile } from "node:fs/promises"; +import path from "node:path"; +import pako from "pako"; +import crypto from "node:crypto"; + +const fontsPath = "./node_modules/@fontsource/m-plus-rounded-1c/files/"; +const cssPath = "./node_modules/@fontsource/m-plus-rounded-1c/"; +const outPath = "./public/m-plus-rounded-1c-nohint/"; +const outURLBase = "/m-plus-rounded-1c-nohint"; + +const weights = [400, 700]; +const woffHashes = new Map(); +const woff2Hashes = new Map(); + +if (existsSync(outPath)) { + console.log(`Output directory ${outPath} already exists.`); + console.log("To regenerate font files, please delete the directory."); +} else { + await woff2.init(); + await mkdir(outPath); + + async function removeHintingFromFont(file: string) { + const fontBuffer = await readFile(path.join(fontsPath, file)); + + const font = createFont(fontBuffer, { + type: "woff", + hinting: false, + kerning: true, + compound2simple: false, + inflate: (data) => Array.from(pako.inflate(Uint8Array.from(data))), + }); + + const woffBuffer = font.write({ + type: "woff", + hinting: false, + kerning: true, + deflate: (data) => Array.from(pako.deflate(Uint8Array.from(data))), + }) as Buffer; + const woffHash = crypto + .createHash("sha256") + .update(woffBuffer) + .digest("hex") + .slice(0, 8); + woffHashes.set(path.parse(file).name, woffHash); + const outFileName = path.parse(file).name + `-nohint-${woffHash}.woff`; + writeFile( + `./public/m-plus-rounded-1c-nohint/${outFileName}`, + woffBuffer + ).then(() => { + console.log(`Processed ${file} -> ${outFileName}`); + }); + + const woff2Buffer = font.write({ + type: "woff2", + hinting: false, + kerning: true, + }) as Buffer; + const woff2Hash = crypto + .createHash("sha256") + .update(woff2Buffer) + .digest("hex") + .slice(0, 8); + woff2Hashes.set(path.parse(file).name, woff2Hash); + const outFileName2 = path.parse(file).name + `-nohint-${woff2Hash}.woff2`; + writeFile( + `./public/m-plus-rounded-1c-nohint/${outFileName2}`, + woff2Buffer + ).then(() => { + console.log(`Processed ${file} -> ${outFileName2}`); + }); + } + + async function rewriteCSS(file: string) { + let css = await readFile(path.join(cssPath, file), "utf-8"); + css = css.replace(/url\((.+?)\)/g, (match, p1) => { + const parsedPath = path.parse(p1); + const hash = + path.extname(p1) === ".woff" + ? woffHashes.get(parsedPath.name) + : woff2Hashes.get(parsedPath.name); + return `url(${outURLBase}/${parsedPath.name}-nohint-${hash}${path.extname(p1)})`; + }); + css = css.replaceAll( + "font-family: 'M PLUS Rounded 1c'", + "font-family: 'M PLUS Rounded 1c NoHint'" + ); + await writeFile(path.join(outPath, file), css, "utf-8"); + console.log(`Rewritten CSS: ${file}`); + } + + for (const file of await readdir(fontsPath)) { + if ( + path.extname(file) === ".woff" && + weights.some((w) => file.includes(w.toString())) + ) { + await removeHintingFromFont(file); + } + } + for (const file of await readdir(cssPath)) { + if ( + path.extname(file) === ".css" && + weights.some((w) => file.includes(w.toString())) + ) { + rewriteCSS(file); + } + } +} From 26aa0e274e02f18221426a58441103e059a91f4f Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Tue, 6 Jan 2026 21:15:42 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E3=83=8F=E3=83=83=E3=82=B7=E3=83=A5?= =?UTF-8?q?=E3=81=AFwebpack=E3=81=AB=E4=BB=BB=E3=81=9B=E3=82=8C=E3=81=B0?= =?UTF-8?q?=E8=89=AF=E3=81=8B=E3=81=A3=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- app/layout.tsx | 4 ++-- public/_headers | 4 ---- scripts/removeHinting.ts | 38 ++++++-------------------------------- 4 files changed, 9 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 2128524..7eaedd6 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,4 @@ next-env.d.ts /public/typescript/ -/public/m-plus-rounded-1c-nohint/ +/app/m-plus-rounded-1c-nohint/ diff --git a/app/layout.tsx b/app/layout.tsx index 26d779a..bd0f049 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,8 +2,8 @@ import type { Metadata } from "next"; import "@fontsource-variable/inconsolata"; // import "@fontsource/m-plus-rounded-1c/400.css"; // import "@fontsource/m-plus-rounded-1c/700.css"; -import "@/../public/m-plus-rounded-1c-nohint/400.css"; -import "@/../public/m-plus-rounded-1c-nohint/700.css"; +import "@/m-plus-rounded-1c-nohint/400.css"; +import "@/m-plus-rounded-1c-nohint/700.css"; import "./globals.css"; import { Navbar } from "./navbar"; import { Sidebar } from "./sidebar"; diff --git a/public/_headers b/public/_headers index 2dbf410..133717c 100644 --- a/public/_headers +++ b/public/_headers @@ -4,7 +4,3 @@ Cross-Origin-Embedder-Policy: require-corp /typescript/* Cache-Control: public,max-age=31536000,immutable -/m-plus-rounded-1c-nohint/*.woff - Cache-Control: public,max-age=31536000,immutable -/m-plus-rounded-1c-nohint/*.woff2 - Cache-Control: public,max-age=31536000,immutable diff --git a/scripts/removeHinting.ts b/scripts/removeHinting.ts index 150e6dc..8df420e 100644 --- a/scripts/removeHinting.ts +++ b/scripts/removeHinting.ts @@ -3,16 +3,12 @@ import { existsSync } from "node:fs"; import { mkdir, readdir, readFile, writeFile } from "node:fs/promises"; import path from "node:path"; import pako from "pako"; -import crypto from "node:crypto"; const fontsPath = "./node_modules/@fontsource/m-plus-rounded-1c/files/"; const cssPath = "./node_modules/@fontsource/m-plus-rounded-1c/"; -const outPath = "./public/m-plus-rounded-1c-nohint/"; -const outURLBase = "/m-plus-rounded-1c-nohint"; +const outPath = "./app/m-plus-rounded-1c-nohint/"; const weights = [400, 700]; -const woffHashes = new Map(); -const woff2Hashes = new Map(); if (existsSync(outPath)) { console.log(`Output directory ${outPath} already exists.`); @@ -38,17 +34,8 @@ if (existsSync(outPath)) { kerning: true, deflate: (data) => Array.from(pako.deflate(Uint8Array.from(data))), }) as Buffer; - const woffHash = crypto - .createHash("sha256") - .update(woffBuffer) - .digest("hex") - .slice(0, 8); - woffHashes.set(path.parse(file).name, woffHash); - const outFileName = path.parse(file).name + `-nohint-${woffHash}.woff`; - writeFile( - `./public/m-plus-rounded-1c-nohint/${outFileName}`, - woffBuffer - ).then(() => { + const outFileName = path.parse(file).name + `-nohint.woff`; + writeFile(path.join(outPath, outFileName), woffBuffer).then(() => { console.log(`Processed ${file} -> ${outFileName}`); }); @@ -57,17 +44,8 @@ if (existsSync(outPath)) { hinting: false, kerning: true, }) as Buffer; - const woff2Hash = crypto - .createHash("sha256") - .update(woff2Buffer) - .digest("hex") - .slice(0, 8); - woff2Hashes.set(path.parse(file).name, woff2Hash); - const outFileName2 = path.parse(file).name + `-nohint-${woff2Hash}.woff2`; - writeFile( - `./public/m-plus-rounded-1c-nohint/${outFileName2}`, - woff2Buffer - ).then(() => { + const outFileName2 = path.parse(file).name + `-nohint.woff2`; + writeFile(path.join(outPath, outFileName2), woff2Buffer).then(() => { console.log(`Processed ${file} -> ${outFileName2}`); }); } @@ -76,11 +54,7 @@ if (existsSync(outPath)) { let css = await readFile(path.join(cssPath, file), "utf-8"); css = css.replace(/url\((.+?)\)/g, (match, p1) => { const parsedPath = path.parse(p1); - const hash = - path.extname(p1) === ".woff" - ? woffHashes.get(parsedPath.name) - : woff2Hashes.get(parsedPath.name); - return `url(${outURLBase}/${parsedPath.name}-nohint-${hash}${path.extname(p1)})`; + return `url(./${parsedPath.name}-nohint${parsedPath.ext})`; }); css = css.replaceAll( "font-family: 'M PLUS Rounded 1c'", From ded3dbf785eebfc014ec5fb911942eaa188c7074 Mon Sep 17 00:00:00 2001 From: na-trium-144 <100704180+na-trium-144@users.noreply.github.com> Date: Wed, 7 Jan 2026 00:49:04 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E3=81=9C=E3=82=93=E3=81=B6await=E3=81=99?= =?UTF-8?q?=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/removeHinting.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/removeHinting.ts b/scripts/removeHinting.ts index 8df420e..27b0c35 100644 --- a/scripts/removeHinting.ts +++ b/scripts/removeHinting.ts @@ -35,7 +35,7 @@ if (existsSync(outPath)) { deflate: (data) => Array.from(pako.deflate(Uint8Array.from(data))), }) as Buffer; const outFileName = path.parse(file).name + `-nohint.woff`; - writeFile(path.join(outPath, outFileName), woffBuffer).then(() => { + await writeFile(path.join(outPath, outFileName), woffBuffer).then(() => { console.log(`Processed ${file} -> ${outFileName}`); }); @@ -45,7 +45,7 @@ if (existsSync(outPath)) { kerning: true, }) as Buffer; const outFileName2 = path.parse(file).name + `-nohint.woff2`; - writeFile(path.join(outPath, outFileName2), woff2Buffer).then(() => { + await writeFile(path.join(outPath, outFileName2), woff2Buffer).then(() => { console.log(`Processed ${file} -> ${outFileName2}`); }); } @@ -77,7 +77,7 @@ if (existsSync(outPath)) { path.extname(file) === ".css" && weights.some((w) => file.includes(w.toString())) ) { - rewriteCSS(file); + await rewriteCSS(file); } } }