From 5adea7c084440e02d37ab42622f07a6d8cb365b1 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 18:08:47 -0800 Subject: [PATCH 1/9] Generate an updated site from the ungulped code. --- .github/workflows/pages.yaml | 42 ++ Makefile | 6 +- nix/www.nix | 4 +- package-lock.json | 443 +++++++++++++++++++++- package.json | 4 +- script/build-site.ts | 105 +++++ src/web/icons.cubing.net/img/og-image.png | Bin 0 -> 58498 bytes src/web/icons.cubing.net/index.css | 159 ++++++++ src/web/icons.cubing.net/index.html | 218 +++++++++++ 9 files changed, 972 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/pages.yaml create mode 100644 script/build-site.ts create mode 100644 src/web/icons.cubing.net/img/og-image.png create mode 100644 src/web/icons.cubing.net/index.css create mode 100644 src/web/icons.cubing.net/index.html diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml new file mode 100644 index 0000000..144eac4 --- /dev/null +++ b/.github/workflows/pages.yaml @@ -0,0 +1,42 @@ +name: icons.cubing.net + +on: + push: + branches: [main] + +concurrency: + group: pages + cancel-in-progress: true + +jobs: + build-pages: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: nix build .#www --out-link ./www + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: ./www + + deploy-pages: + runs-on: ubuntu-latest + + needs: build-pages + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + # https://github.com/actions/deploy-pages#usage + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/Makefile b/Makefile index 15f5364..2a3b6af 100644 --- a/Makefile +++ b/Makefile @@ -4,12 +4,16 @@ bun.lockb: package-lock.json bun pm migrate --force .PHONY: build -build: build-lib +build: build-lib build-site .PHONY: build-lib build-lib: setup bun run script/build-lib.ts +.PHONY: build-site +build-site: setup + bun run script/build-site.ts + .PHONY: setup setup: bun.lockb ifndef NIX_BUILD_TOP diff --git a/nix/www.nix b/nix/www.nix index 4f01a3d..27d7ebf 100644 --- a/nix/www.nix +++ b/nix/www.nix @@ -30,9 +30,7 @@ ''; installPhase = '' - # TODO: https://github.com/cubing/icons/pull/138 - touch $out - # mv ./dist/web/icons.cubing.net $out + mv ./dist/web/icons.cubing.net $out ''; }; diff --git a/package-lock.json b/package-lock.json index f18b349..4950510 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,9 @@ "devDependencies": { "@biomejs/biome": "^1.9.4", "@types/bun": "^1.1.14", - "fantasticon": "^3.0.0" + "@types/jsdom": "^21.1.7", + "fantasticon": "^3.0.0", + "jsdom": "^25.0.1" } }, "node_modules/@biomejs/biome": { @@ -263,6 +265,18 @@ "bun-types": "1.1.37" } }, + "node_modules/@types/jsdom": { + "version": "21.1.7", + "resolved": "https://registry.npmjs.org/@types/jsdom/-/jsdom-21.1.7.tgz", + "integrity": "sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tough-cookie": "*", + "parse5": "^7.0.0" + } + }, "node_modules/@types/node": { "version": "22.10.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.4.tgz", @@ -273,6 +287,13 @@ "undici-types": "~6.20.0" } }, + "node_modules/@types/tough-cookie": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.5.tgz", + "integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/ws": { "version": "8.5.13", "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.13.tgz", @@ -301,6 +322,16 @@ "dev": true, "license": "ISC" }, + "node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/agentkeepalive": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", @@ -383,6 +414,13 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -615,6 +653,19 @@ "color-support": "bin.js" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/commander": { "version": "12.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", @@ -654,6 +705,19 @@ "node": ">= 8" } }, + "node_modules/cssstyle": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.1.0.tgz", + "integrity": "sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rrweb-cssom": "^0.7.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/cubic2quad": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/cubic2quad/-/cubic2quad-1.2.1.tgz", @@ -675,6 +739,20 @@ "node": ">=0.12" } }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/debug": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", @@ -693,6 +771,23 @@ } } }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -725,6 +820,19 @@ "iconv-lite": "^0.6.2" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -892,6 +1000,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -1055,6 +1178,19 @@ "dev": true, "license": "ISC" }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/http-cache-semantics": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", @@ -1062,6 +1198,34 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/humanize-ms": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", @@ -1078,7 +1242,6 @@ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "dev": true, "license": "MIT", - "optional": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" }, @@ -1163,6 +1326,13 @@ "dev": true, "license": "MIT" }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-promise": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", @@ -1200,6 +1370,47 @@ "dev": true, "license": "MIT" }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1344,6 +1555,29 @@ "dev": true, "license": "MIT" }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", @@ -1698,6 +1932,13 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, + "node_modules/nwsapi": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.16.tgz", + "integrity": "sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ==", + "dev": true, + "license": "MIT" + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1738,6 +1979,19 @@ "dev": true, "license": "(MIT AND Zlib)" }, + "node_modules/parse5": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", + "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.5.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1796,6 +2050,16 @@ "node": ">=10" } }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", @@ -1884,6 +2148,13 @@ "node": "*" } }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1910,8 +2181,7 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "dev": true, - "license": "MIT", - "optional": true + "license": "MIT" }, "node_modules/sax": { "version": "1.4.1", @@ -1920,6 +2190,19 @@ "dev": true, "license": "ISC" }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -2298,6 +2581,13 @@ "url": "https://github.com/fontello/svg2ttf?sponsor=1" } }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -2340,6 +2630,52 @@ "node": ">=0.12" } }, + "node_modules/tldts": { + "version": "6.1.70", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.70.tgz", + "integrity": "sha512-/W1YVgYVJd9ZDjey5NXadNh0mJXkiUMUue9Zebd0vpdo1sU+H4zFFTaJ1RKD4N6KFoHfcXy6l+Vu7bh+bdWCzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.70" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.70", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.70.tgz", + "integrity": "sha512-RNnIXDB1FD4T9cpQRErEqw6ZpjLlGdMOitdV+0xtbsnwr4YFka1zpc7D4KD+aAn8oSG5JyFrdasZTE04qDE9Yg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", + "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ttf2eot": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/ttf2eot/-/ttf2eot-3.1.0.tgz", @@ -2448,6 +2784,66 @@ "dev": true, "license": "MIT" }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.1.0.tgz", + "integrity": "sha512-jlf/foYIKywAt3x/XWKZ/3rz8OSJPiWktjmk891alJUEjiVxKX9LEO92qH3hv4aJ0mN3MWPvGMCy8jQi95xK4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2631,6 +3027,45 @@ "dev": true, "license": "ISC" }, + "node_modules/ws": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", diff --git a/package.json b/package.json index f8f075c..27d5aef 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,9 @@ "devDependencies": { "@biomejs/biome": "^1.9.4", "@types/bun": "^1.1.14", - "fantasticon": "^3.0.0" + "@types/jsdom": "^21.1.7", + "fantasticon": "^3.0.0", + "jsdom": "^25.0.1" }, "exports": { ".": { diff --git a/script/build-site.ts b/script/build-site.ts new file mode 100644 index 0000000..3197686 --- /dev/null +++ b/script/build-site.ts @@ -0,0 +1,105 @@ +import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; +import { join } from "node:path"; +import { JSDOM } from "jsdom"; + +const { CubingIcons } = await import( + "../dist/lib/@cubing/icons/cubing-icons.ts" +); + +const SITE_OUTPUT_DIR = "./dist/web/icons.cubing.net"; +const SITE_SRC_DIR = "./src/web/icons.cubing.net"; +const HTML_INDEX_FILENAME = "index.html"; +const CSS_INDEX_FILENAME = "index.css"; + +const LIB_OUTPUT_DIR = "./dist/lib"; + +await rm(SITE_OUTPUT_DIR, { force: true, recursive: true }); +await mkdir(SITE_OUTPUT_DIR, { recursive: true }); + +const indexSource = await readFile( + join(SITE_SRC_DIR, HTML_INDEX_FILENAME), + "utf-8", +); + +const dom = new JSDOM(indexSource); + +const { document } = dom.window; + +function mustExist(t: T | null): NonNullable { + if (!t) { + throw new Error("Missing element"); + } + return t; +} + +// Sort all current WCA events in the same order as the WCA website (ahead of former events). +// We'd import this from `cubing.js`, but: https://github.com/cubing/cubing.js/issues/351 +const wcaEventOrdering = [ + "333", + "222", + "444", + "555", + "666", + "777", + "333bf", + "333fm", + "333oh", + "clock", + "minx", + "pyram", + "skewb", + "sq1", + "444bf", + "555bf", + "333mbf", +]; +const classNamesOrdered = wcaEventOrdering.map((eventID) => `event-${eventID}`); +for (const className of Object.values(CubingIcons).sort()) { + if (!classNamesOrdered.includes(className)) { + classNamesOrdered.push(className); + } +} + +mustExist(document.querySelector("#source-notice")).remove(); +for (const prefix of ["event", "unofficial", "penalty"]) { + const [elem, ...extra] = document.getElementsByClassName(`group-${prefix}`); + if (!elem || extra.length > 0) { + throw new Error("Unexpected number of elems."); + } + const iconsList = mustExist(elem.querySelector("ul.icons-list")); + iconsList.textContent = ""; // Clear all children. + + for (const className of classNamesOrdered) { + if (className.startsWith(`${prefix}-`)) { + if (!className.match(/[a-zA-Z0-9\-]+/)) { + throw new Error("Unexpected class name."); + } + console.log(className); + const li = iconsList.appendChild(document.createElement("li")); + li.id = className; + const a = li.appendChild(document.createElement("a")); + a.href = `#${className}`; + const span = a.appendChild(document.createElement("span")); + span.classList.add("cubing-icon"); + span.classList.add(className); + const codeElem = a.appendChild(document.createElement("code")); + codeElem.append(`cubing-icon ${className}`); + } + } +} + +mustExist( + document.querySelector("head #cubing-icons-css-link"), +).href = "./@cubing/icons/cubing-icons.css"; + +// Copy all files. +await cp(join(SITE_SRC_DIR), join(SITE_OUTPUT_DIR), { recursive: true }); + +// Overwrite HTML file. +await writeFile(join(SITE_OUTPUT_DIR, HTML_INDEX_FILENAME), dom.serialize()); + +// Vendor lib. +// TODO: semantics don't match `cp` binary??? +await cp(LIB_OUTPUT_DIR, SITE_OUTPUT_DIR, { + recursive: true, +}); diff --git a/src/web/icons.cubing.net/img/og-image.png b/src/web/icons.cubing.net/img/og-image.png new file mode 100644 index 0000000000000000000000000000000000000000..a5a97d9865af810ffdfcb4a692c432b28b8c9ae0 GIT binary patch literal 58498 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 P;G?3bp-?Js{^9=t<%bXa literal 0 HcmV?d00001 diff --git a/src/web/icons.cubing.net/index.css b/src/web/icons.cubing.net/index.css new file mode 100644 index 0000000..9f42c01 --- /dev/null +++ b/src/web/icons.cubing.net/index.css @@ -0,0 +1,159 @@ +/* Adapted from https://github.com/lgarron/minimal-html-style */ +:root { + color-scheme: light dark; +} + +* { + box-sizing: border-box; +} + +html { + font-family: -apple-system, Roboto, Ubuntu, Tahoma, sans-serif; + font-size: 1rem; + padding: 0em 2em; + background: #4285f411; + display: grid; + justify-content: center; +} + +body { + margin: auto; + width: 100vw; +} + +navigation-bar { + width: 100%; + padding: 0 0.5rem; + display: grid; + align-items: baseline; + grid-template-columns: repeat(5, auto) 1fr auto; + justify-content: start; + background-color: #4285f422; + border-bottom: 1px solid color-mix(in oklab, currentColor 20%, transparent); +} + +navigation-bar a { + font-size: 1rem; + padding: 0.5rem; +} + +navigation-bar a:not(:hover) { + text-decoration: none; +} + +navigation-bar a:first-child { + font-size: 1.5em; +} + +@media (max-width: 40rem) { + navigation-bar { + grid-template-columns: 1fr; + padding: 0.5rem 2rem; + } + navigation-bar a { + padding: 0.1rem; + } +} + +.content { + width: calc(100vw - 4em); + max-width: 45em; + margin: auto; + padding-top: 1.5em; +} + +h1 { + margin-top: 0; +} + +.sample { + background: #4285f422; + padding: 1em; + border: 1px solid black; + font-size: 0.8em; +} + +.sample .dim { + opacity: 0.4; +} + +.sample.output { + padding: 0em; + font-size: 1.5em; +} + +/* Icons lists */ + +.icons-list { + width: 100%; + padding-left: 0; + list-style: none; + display: grid; + grid-template-columns: repeat(auto-fill, var(--icon-scale)); + grid-auto-rows: 1fr; + + --icon-scale: 6em; +} + +.icons-list li { + border: 1px solid currentColor; + padding: 0; +} + +.icons-list li a { + height: 100%; + background-color: color-mix(in oklab, currentColor 10%, transparent); + display: inline-block; + padding: 0.5em; + text-align: center; + font-size: 0.7em; + display: grid; + grid-template-columns: auto; + text-decoration: none; + overflow-wrap: anywhere; +} + +.icons-list li:nth-child(5n + 1) a { + color: light-dark(#222222, #dddddd); +} + +.icons-list li:nth-child(5n + 2) a { + color: color-mix(in oklab, orange 70%, currentColor); +} + +.icons-list li:nth-child(5n + 3) a { + color: color-mix(in oklab, green 70%, currentColor); +} + +.icons-list li:nth-child(5n + 4) a { + color: color-mix(in oklab, red 70%, currentColor); +} + +.icons-list li:nth-child(5n + 5) a { + color: color-mix(in oklab, blue 70%, currentColor); +} + +.icons-list li:is(:target, :hover) { + border-width: 4px; + margin: -3px; + border-radius: 3px; +} + +.icons-list li:target a { + /* color: light-dark(blue, rebeccapurple); */ + /* background-color: color-mix(in oklab, purple 60%, transparent); */ + background-color: color-mix(in oklab, currentColor 30%, transparent); +} + +.icons-list li a:hover { + text-shadow: 0 0 2em color-mix(in oklab, currentColor 50%, transparent); +} + +.icons-list li a:hover code { + text-decoration: underline; +} + +.icons-list .cubing-icon { + font-size: var(--icon-scale); + text-decoration: none; +} diff --git a/src/web/icons.cubing.net/index.html b/src/web/icons.cubing.net/index.html new file mode 100644 index 0000000..9e55fc5 --- /dev/null +++ b/src/web/icons.cubing.net/index.html @@ -0,0 +1,218 @@ + + + + + + Cubing icons + + + + + + + + + + + Cubing icons + Basic use + Use from npm + SVG + Icon catalog +
+ On GitHub +
+ +
+

It's time for cubing icons!

+ +

+ Cubing icons can be used for any cubing project under a free license. Use them for your web site or web app + today! +

+ +
+

Use cubing icons in your web project

+ +

+ The simplest way to use cubing icons in your project is to include one CSS <link> + element + on + your page and then use class on <span> elements + to + specify icons. +

+ +

+ Here's an example: +

+ +
+ + <!-- The following line is needed only once per page. -->
+ <link rel="stylesheet" href="https://cdn.cubing.net/v0/css/@cubing/icons"> +
+
+ <ul>
+   <li><span class="cubing-icon event-333"></span> 3×3×3</li>
+   <li><span class="cubing-icon event-clock"></span> Clock</li>
+   <li><span class="cubing-icon unofficial-fto"></span> FTO</li>
+ </ul> +
+
+ +

+ This is how it looks: +

+ +
+
    +
  • 3×3×3
  • +
  • Clock
  • +
  • FTO
  • +
+
+
+ +

+ For a list of available icons, consult the catalog. +

+ +
+

Using the npm package

+ +

+ Cubing icons are published as @cubing/icons + on npm. If you are more comfortable using npm for + your project dependencies, you should be able to install this package and use it with a + bundler of your choice in one of these ways: +

+ +

+

+ page.html + <link rel="stylesheet" href="@cubing/icons/css"> +
+

+

+

+ style.css + @import "@cubing/icons/css"; +
+

+

+

+ app.ts + + import { CubingIcons } from "@cubing/icons/ts";
+
+ // Work with a list of available icons
+ console.log(Object.values(CubingIcons)); +
+
+

+
+ +
+

SVG files

+

+ You can find .svg files of the icons by looking in the src/svg folder of the + project repository. +

+
+ +
+

Icon catalog

+ +

+ Icons are listed here with their CSS class names. +

+ +
+ Note: Only three icons from each group are included in the source HTML in the repo. +
+ +
+

WCA events (current and former)

+ +
+ +
+

Unofficial events

+ +
+ + +
+

Penalties

+ +
+
+
+ + + + From 7bf6cd8375a4417c3f562c778ab08400efb22157 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 19:55:46 -0800 Subject: [PATCH 2/9] `
` it up. --- src/web/icons.cubing.net/index.css | 5 +++++ src/web/icons.cubing.net/index.html | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/src/web/icons.cubing.net/index.css b/src/web/icons.cubing.net/index.css index 9f42c01..cb0426c 100644 --- a/src/web/icons.cubing.net/index.css +++ b/src/web/icons.cubing.net/index.css @@ -157,3 +157,8 @@ h1 { font-size: var(--icon-scale); text-decoration: none; } + +hr { + margin: 2em 0; + opacity: 50%; +} diff --git a/src/web/icons.cubing.net/index.html b/src/web/icons.cubing.net/index.html index 9e55fc5..1fe7112 100644 --- a/src/web/icons.cubing.net/index.html +++ b/src/web/icons.cubing.net/index.html @@ -33,6 +33,7 @@

It's time for cubing icons!
+

Use cubing icons in your web project

@@ -82,6 +83,7 @@

Use cubing icons in your web project

+

Using the npm package

@@ -118,6 +120,7 @@

Using the npm package

+

SVG files

You can find .svg files of the icons by looking in SVG files

+

Icon catalog

From 8323b7f936581041534d8b108891f03f80217618 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 21:20:44 -0800 Subject: [PATCH 3/9] Lotsa icons. --- script/build-site.ts | 16 +++++++++++++--- src/web/icons.cubing.net/index.css | 15 +++++++++++++++ src/web/icons.cubing.net/index.html | 2 ++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/script/build-site.ts b/script/build-site.ts index 3197686..23662e5 100644 --- a/script/build-site.ts +++ b/script/build-site.ts @@ -55,12 +55,25 @@ const wcaEventOrdering = [ ]; const classNamesOrdered = wcaEventOrdering.map((eventID) => `event-${eventID}`); for (const className of Object.values(CubingIcons).sort()) { + if (!className.match(/[a-zA-Z0-9\-]+/)) { + throw new Error("Unexpected class name."); + } if (!classNamesOrdered.includes(className)) { classNamesOrdered.push(className); } } +const allIconsElem = mustExist(document.querySelector("#all-icons")); +for (const className of classNamesOrdered) { + const a = allIconsElem.appendChild(document.createElement("a")); + a.href = `#${className}`; + const span = a.appendChild(document.createElement("span")); + span.classList.add("cubing-icon"); + span.classList.add(className); +} + mustExist(document.querySelector("#source-notice")).remove(); + for (const prefix of ["event", "unofficial", "penalty"]) { const [elem, ...extra] = document.getElementsByClassName(`group-${prefix}`); if (!elem || extra.length > 0) { @@ -71,9 +84,6 @@ for (const prefix of ["event", "unofficial", "penalty"]) { for (const className of classNamesOrdered) { if (className.startsWith(`${prefix}-`)) { - if (!className.match(/[a-zA-Z0-9\-]+/)) { - throw new Error("Unexpected class name."); - } console.log(className); const li = iconsList.appendChild(document.createElement("li")); li.id = className; diff --git a/src/web/icons.cubing.net/index.css b/src/web/icons.cubing.net/index.css index cb0426c..8ab7e39 100644 --- a/src/web/icons.cubing.net/index.css +++ b/src/web/icons.cubing.net/index.css @@ -82,6 +82,21 @@ h1 { font-size: 1.5em; } +#all-icons { + font-size: 1.75em; + overflow-wrap: anywhere; + letter-spacing: 0.25em; +} + +#all-icons a { + color: currentColor; + text-decoration: none; +} + +#all-icons a:hover { + text-shadow: 0 0 0.5em color-mix(in oklab, currentColor 100%, transparent); +} + /* Icons lists */ .icons-list { diff --git a/src/web/icons.cubing.net/index.html b/src/web/icons.cubing.net/index.html index 1fe7112..4b42e7d 100644 --- a/src/web/icons.cubing.net/index.html +++ b/src/web/icons.cubing.net/index.html @@ -26,6 +26,8 @@

It's time for cubing icons!

+
+

Cubing icons can be used for any cubing project under a free license. Use them for your web site or web app From 3cc74658c028878c0d9740b6f3a4fdb61b0e1762 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 21:27:16 -0800 Subject: [PATCH 4/9] Multiple source notices. --- script/build-site.ts | 8 +++++++- src/web/icons.cubing.net/index.html | 13 ++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/script/build-site.ts b/script/build-site.ts index 23662e5..a707440 100644 --- a/script/build-site.ts +++ b/script/build-site.ts @@ -1,3 +1,4 @@ +import assert from "node:assert"; import { cp, mkdir, readFile, rm, writeFile } from "node:fs/promises"; import { join } from "node:path"; import { JSDOM } from "jsdom"; @@ -64,6 +65,7 @@ for (const className of Object.values(CubingIcons).sort()) { } const allIconsElem = mustExist(document.querySelector("#all-icons")); +allIconsElem.textContent = ""; for (const className of classNamesOrdered) { const a = allIconsElem.appendChild(document.createElement("a")); a.href = `#${className}`; @@ -72,7 +74,11 @@ for (const className of classNamesOrdered) { span.classList.add(className); } -mustExist(document.querySelector("#source-notice")).remove(); +const notices = document.querySelectorAll(".source-notice"); +assert.equal(notices.length, 2); +for (const notice of notices) { + notice.remove(); +} for (const prefix of ["event", "unofficial", "penalty"]) { const [elem, ...extra] = document.getElementsByClassName(`group-${prefix}`); diff --git a/src/web/icons.cubing.net/index.html b/src/web/icons.cubing.net/index.html index 4b42e7d..f5c2e25 100644 --- a/src/web/icons.cubing.net/index.html +++ b/src/web/icons.cubing.net/index.html @@ -27,6 +27,12 @@

It's time for cubing icons!

+ +
+
+ Note: Only three icons are included in the source HTML in the repo. All icons are included in the compiled HTML.

Cubing icons can be used for any cubing project under a Icon catalog Icons are listed here with their CSS class names.

-
- Note: Only three icons from each group are included in the source HTML in the repo. +
+ Note: Only three icons from each group are included in the source HTML in the repo. All icons are included in + the compiled HTML.
From d152504e3ae815792ff6037b85872c1f6a8969a8 Mon Sep 17 00:00:00 2001 From: Jeremy Fleischman Date: Thu, 2 Jan 2025 23:10:03 -0800 Subject: [PATCH 5/9] Tweaking the looks! Paried on this with @lgarron --- src/web/icons.cubing.net/index.css | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/web/icons.cubing.net/index.css b/src/web/icons.cubing.net/index.css index 8ab7e39..fc56da4 100644 --- a/src/web/icons.cubing.net/index.css +++ b/src/web/icons.cubing.net/index.css @@ -10,15 +10,11 @@ html { font-family: -apple-system, Roboto, Ubuntu, Tahoma, sans-serif; font-size: 1rem; - padding: 0em 2em; background: #4285f411; - display: grid; - justify-content: center; } body { - margin: auto; - width: 100vw; + margin: 0; } navigation-bar { @@ -71,6 +67,7 @@ h1 { padding: 1em; border: 1px solid black; font-size: 0.8em; + overflow-wrap: anywhere; } .sample .dim { @@ -89,12 +86,12 @@ h1 { } #all-icons a { - color: currentColor; text-decoration: none; + color: currentColor; } -#all-icons a:hover { - text-shadow: 0 0 0.5em color-mix(in oklab, currentColor 100%, transparent); +#all-icons a:not(:hover) { + opacity: 25%; } /* Icons lists */ @@ -160,10 +157,6 @@ h1 { background-color: color-mix(in oklab, currentColor 30%, transparent); } -.icons-list li a:hover { - text-shadow: 0 0 2em color-mix(in oklab, currentColor 50%, transparent); -} - .icons-list li a:hover code { text-decoration: underline; } From 2e677e1bd6d0c2a62ef163438c79880553ca6827 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 23:38:27 -0800 Subject: [PATCH 6/9] Fix up development config. --- .github/workflows/CI.yaml | 13 +++++++++++-- .github/workflows/pages.yaml | 4 ++-- Makefile | 12 ++++++------ nix/dev-shell.nix | 2 +- nix/{formatting.nix => lint.nix} | 0 nix/{www.nix => web.nix} | 6 +++--- 6 files changed, 23 insertions(+), 14 deletions(-) rename nix/{formatting.nix => lint.nix} (100%) rename nix/{www.nix => web.nix} (83%) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 40835e3..0e3ef20 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -3,10 +3,19 @@ on: workflow_call: jobs: - check: + build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix flake check + - run: make build-lib + - run: make build-web + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DeterminateSystems/nix-installer-action@main + - uses: DeterminateSystems/magic-nix-cache-action@main + - run: make lint diff --git a/.github/workflows/pages.yaml b/.github/workflows/pages.yaml index 144eac4..fc86058 100644 --- a/.github/workflows/pages.yaml +++ b/.github/workflows/pages.yaml @@ -15,11 +15,11 @@ jobs: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: nix build .#www --out-link ./www + - run: nix build .#web --out-link ./dist/web/icons.cubing.net - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: ./www + path: ./dist/web/icons.cubing.net deploy-pages: runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index 2a3b6af..1221502 100644 --- a/Makefile +++ b/Makefile @@ -4,15 +4,15 @@ bun.lockb: package-lock.json bun pm migrate --force .PHONY: build -build: build-lib build-site +build: build-lib build-web .PHONY: build-lib build-lib: setup bun run script/build-lib.ts -.PHONY: build-site -build-site: setup - bun run script/build-site.ts +.PHONY: build-web +build-web: setup + bun run script/build-web.ts .PHONY: setup setup: bun.lockb @@ -23,11 +23,11 @@ endif .PHONY: lint lint: setup - npx @biomejs/biome check + bun x @biomejs/biome check .PHONY: format format: setup - npx @biomejs/biome check --write" + bun x @biomejs/biome check --write .PHONY: clean clean: diff --git a/nix/dev-shell.nix b/nix/dev-shell.nix index cbfc1b3..c14e18c 100644 --- a/nix/dev-shell.nix +++ b/nix/dev-shell.nix @@ -5,7 +5,7 @@ { devShells.default = pkgs.mkShell { inputsFrom = [ - self'.packages.www + self'.packages.web ]; }; }; diff --git a/nix/formatting.nix b/nix/lint.nix similarity index 100% rename from nix/formatting.nix rename to nix/lint.nix diff --git a/nix/www.nix b/nix/web.nix similarity index 83% rename from nix/www.nix rename to nix/web.nix index 27d7ebf..17bb0b1 100644 --- a/nix/www.nix +++ b/nix/web.nix @@ -13,8 +13,8 @@ }; in { - packages.www = pkgs.stdenvNoCC.mkDerivation { - name = "www"; + packages.web = pkgs.stdenvNoCC.mkDerivation { + name = "web"; inherit src; nativeBuildInputs = [ @@ -34,6 +34,6 @@ ''; }; - checks.www = self'.packages.www; + checks.web = self'.packages.web; }; } From 13f8b3ad9272d3209bbda9312c42573c41058eef Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 23:50:03 -0800 Subject: [PATCH 7/9] [CI.yaml] Revert to single `nix flake check`. --- .github/workflows/CI.yaml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 0e3ef20..40835e3 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -3,19 +3,10 @@ on: workflow_call: jobs: - build: + check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: DeterminateSystems/nix-installer-action@main - uses: DeterminateSystems/magic-nix-cache-action@main - - run: make build-lib - - run: make build-web - - lint: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: DeterminateSystems/nix-installer-action@main - - uses: DeterminateSystems/magic-nix-cache-action@main - - run: make lint + - run: nix flake check From 3ff7c0ddfd260b6d66cedc58a8d87f08fba3656b Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 23:50:53 -0800 Subject: [PATCH 8/9] [flake.nix] Update ordering. --- flake.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flake.nix b/flake.nix index ab8cd1c..d82d2eb 100644 --- a/flake.nix +++ b/flake.nix @@ -13,9 +13,9 @@ flake-parts.lib.mkFlake { inherit inputs; } { systems = import inputs.systems; imports = [ - ./nix/formatting.nix ./nix/dev-shell.nix - ./nix/www.nix + ./nix/lint.nix + ./nix/web.nix ]; }; } From e7b873b44eb69ab76e8932628c86a1b49eb31f38 Mon Sep 17 00:00:00 2001 From: Lucas Garron Date: Thu, 2 Jan 2025 23:52:20 -0800 Subject: [PATCH 9/9] Update `build-web` script name. --- script/{build-site.ts => build-web.ts} | 1 - 1 file changed, 1 deletion(-) rename script/{build-site.ts => build-web.ts} (98%) diff --git a/script/build-site.ts b/script/build-web.ts similarity index 98% rename from script/build-site.ts rename to script/build-web.ts index a707440..33dcade 100644 --- a/script/build-site.ts +++ b/script/build-web.ts @@ -10,7 +10,6 @@ const { CubingIcons } = await import( const SITE_OUTPUT_DIR = "./dist/web/icons.cubing.net"; const SITE_SRC_DIR = "./src/web/icons.cubing.net"; const HTML_INDEX_FILENAME = "index.html"; -const CSS_INDEX_FILENAME = "index.css"; const LIB_OUTPUT_DIR = "./dist/lib";