3 files added
20 files modified
| | |
| | | "nav": CustomEvent<{ url: string }>; |
| | | } |
| | | |
| | | declare global { |
| | | interface Document { |
| | | addEventListener<K extends keyof CustomEventMap>(type: K, |
| | | listener: (this: Document, ev: CustomEventMap[K]) => void): void; |
| | | dispatchEvent<K extends keyof CustomEventMap>(ev: CustomEventMap[K]): void; |
| | | } |
| | | } |
| | | declare const fetchData: Promise<ContentIndex> |
| | |
| | | "@napi-rs/simple-git": "^0.1.8", |
| | | "chalk": "^4.1.2", |
| | | "cli-spinner": "^0.2.10", |
| | | "d3": "^7.8.5", |
| | | "d3-force-reuse": "^1.0.1", |
| | | "esbuild-sass-plugin": "^2.9.0", |
| | | "github-slugger": "^2.0.0", |
| | | "globby": "^13.1.4", |
| | |
| | | }, |
| | | "devDependencies": { |
| | | "@types/cli-spinner": "^0.2.1", |
| | | "@types/d3": "^7.4.0", |
| | | "@types/hast": "^2.3.4", |
| | | "@types/node": "^20.1.2", |
| | | "@types/pretty-time": "^1.1.2", |
| | |
| | | "@types/node": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3": { |
| | | "version": "7.4.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.0.tgz", |
| | | "integrity": "sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-array": "*", |
| | | "@types/d3-axis": "*", |
| | | "@types/d3-brush": "*", |
| | | "@types/d3-chord": "*", |
| | | "@types/d3-color": "*", |
| | | "@types/d3-contour": "*", |
| | | "@types/d3-delaunay": "*", |
| | | "@types/d3-dispatch": "*", |
| | | "@types/d3-drag": "*", |
| | | "@types/d3-dsv": "*", |
| | | "@types/d3-ease": "*", |
| | | "@types/d3-fetch": "*", |
| | | "@types/d3-force": "*", |
| | | "@types/d3-format": "*", |
| | | "@types/d3-geo": "*", |
| | | "@types/d3-hierarchy": "*", |
| | | "@types/d3-interpolate": "*", |
| | | "@types/d3-path": "*", |
| | | "@types/d3-polygon": "*", |
| | | "@types/d3-quadtree": "*", |
| | | "@types/d3-random": "*", |
| | | "@types/d3-scale": "*", |
| | | "@types/d3-scale-chromatic": "*", |
| | | "@types/d3-selection": "*", |
| | | "@types/d3-shape": "*", |
| | | "@types/d3-time": "*", |
| | | "@types/d3-time-format": "*", |
| | | "@types/d3-timer": "*", |
| | | "@types/d3-transition": "*", |
| | | "@types/d3-zoom": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-array": { |
| | | "version": "3.0.5", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.5.tgz", |
| | | "integrity": "sha512-Qk7fpJ6qFp+26VeQ47WY0mkwXaiq8+76RJcncDEfMc2ocRzXLO67bLFRNI4OX1aGBoPzsM5Y2T+/m1pldOgD+A==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-axis": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.2.tgz", |
| | | "integrity": "sha512-uGC7DBh0TZrU/LY43Fd8Qr+2ja1FKmH07q2FoZFHo1eYl8aj87GhfVoY1saJVJiq24rp1+wpI6BvQJMKgQm8oA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-selection": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-brush": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.2.tgz", |
| | | "integrity": "sha512-2TEm8KzUG3N7z0TrSKPmbxByBx54M+S9lHoP2J55QuLU0VSQ9mE96EJSAOVNEqd1bbynMjeTS9VHmz8/bSw8rA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-selection": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-chord": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.2.tgz", |
| | | "integrity": "sha512-abT/iLHD3sGZwqMTX1TYCMEulr+wBd0SzyOQnjYNLp7sngdOHYtNkMRI5v3w5thoN+BWtlHVDx2Osvq6fxhZWw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-color": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", |
| | | "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-contour": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.2.tgz", |
| | | "integrity": "sha512-k6/bGDoAGJZnZWaKzeB+9glgXCYGvh6YlluxzBREiVo8f/X2vpTEdgPy9DN7Z2i42PZOZ4JDhVdlTSTSkLDPlQ==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-array": "*", |
| | | "@types/geojson": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-delaunay": { |
| | | "version": "6.0.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz", |
| | | "integrity": "sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-dispatch": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.2.tgz", |
| | | "integrity": "sha512-rxN6sHUXEZYCKV05MEh4z4WpPSqIw+aP7n9ZN6WYAAvZoEAghEK1WeVZMZcHRBwyaKflU43PCUAJNjFxCzPDjg==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-drag": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.2.tgz", |
| | | "integrity": "sha512-qmODKEDvyKWVHcWWCOVcuVcOwikLVsyc4q4EBJMREsoQnR2Qoc2cZQUyFUPgO9q4S3qdSqJKBsuefv+h0Qy+tw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-selection": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-dsv": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.1.tgz", |
| | | "integrity": "sha512-76pBHCMTvPLt44wFOieouXcGXWOF0AJCceUvaFkxSZEu4VDUdv93JfpMa6VGNFs01FHfuP4a5Ou68eRG1KBfTw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-ease": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", |
| | | "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-fetch": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.2.tgz", |
| | | "integrity": "sha512-gllwYWozWfbep16N9fByNBDTkJW/SyhH6SGRlXloR7WdtAaBui4plTP+gbUgiEot7vGw/ZZop1yDZlgXXSuzjA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-dsv": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-force": { |
| | | "version": "3.0.4", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.4.tgz", |
| | | "integrity": "sha512-q7xbVLrWcXvSBBEoadowIUJ7sRpS1yvgMWnzHJggFy5cUZBq2HZL5k/pBSm0GdYWS1vs5/EDwMjSKF55PDY4Aw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-format": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz", |
| | | "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-geo": { |
| | | "version": "3.0.3", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.3.tgz", |
| | | "integrity": "sha512-bK9uZJS3vuDCNeeXQ4z3u0E7OeJZXjUgzFdSOtNtMCJCLvDtWDwfpRVWlyt3y8EvRzI0ccOu9xlMVirawolSCw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/geojson": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-hierarchy": { |
| | | "version": "3.1.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", |
| | | "integrity": "sha512-9hjRTVoZjRFR6xo8igAJyNXQyPX6Aq++Nhb5ebrUF414dv4jr2MitM2fWiOY475wa3Za7TOS2Gh9fmqEhLTt0A==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-interpolate": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", |
| | | "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-color": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-path": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", |
| | | "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-polygon": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.0.tgz", |
| | | "integrity": "sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-quadtree": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz", |
| | | "integrity": "sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-random": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.1.tgz", |
| | | "integrity": "sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-scale": { |
| | | "version": "4.0.3", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.3.tgz", |
| | | "integrity": "sha512-PATBiMCpvHJSMtZAMEhc2WyL+hnzarKzI6wAHYjhsonjWJYGq5BXTzQjv4l8m2jO183/4wZ90rKvSeT7o72xNQ==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-time": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-scale-chromatic": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", |
| | | "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-selection": { |
| | | "version": "3.0.5", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.5.tgz", |
| | | "integrity": "sha512-xCB0z3Hi8eFIqyja3vW8iV01+OHGYR2di/+e+AiOcXIOrY82lcvWW8Ke1DYE/EUVMsBl4Db9RppSBS3X1U6J0w==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-shape": { |
| | | "version": "3.1.1", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.1.tgz", |
| | | "integrity": "sha512-6Uh86YFF7LGg4PQkuO2oG6EMBRLuW9cbavUW46zkIO5kuS2PfTqo2o9SkgtQzguBHbLgNnU90UNsITpsX1My+A==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-path": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-time": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", |
| | | "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-time-format": { |
| | | "version": "4.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.0.tgz", |
| | | "integrity": "sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-timer": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", |
| | | "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/d3-transition": { |
| | | "version": "3.0.3", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.3.tgz", |
| | | "integrity": "sha512-/S90Od8Id1wgQNvIA8iFv9jRhCiZcGhPd2qX0bKF/PS+y0W5CrXKgIiELd2CvG1mlQrWK/qlYh3VxicqG1ZvgA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-selection": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/d3-zoom": { |
| | | "version": "3.0.3", |
| | | "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.3.tgz", |
| | | "integrity": "sha512-OWk1yYIIWcZ07+igN6BeoG6rqhnJ/pYe+R1qWFM2DtW49zsoSjgb9G5xB0ZXA8hh2jAzey1XuRmMSoXdKw8MDA==", |
| | | "dev": true, |
| | | "dependencies": { |
| | | "@types/d3-interpolate": "*", |
| | | "@types/d3-selection": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/debug": { |
| | | "version": "4.1.8", |
| | | "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", |
| | |
| | | "@types/ms": "*" |
| | | } |
| | | }, |
| | | "node_modules/@types/geojson": { |
| | | "version": "7946.0.10", |
| | | "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", |
| | | "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", |
| | | "dev": true |
| | | }, |
| | | "node_modules/@types/hast": { |
| | | "version": "2.3.4", |
| | | "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", |
| | |
| | | "node": ">= 8" |
| | | } |
| | | }, |
| | | "node_modules/d3": { |
| | | "version": "7.8.5", |
| | | "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz", |
| | | "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==", |
| | | "dependencies": { |
| | | "d3-array": "3", |
| | | "d3-axis": "3", |
| | | "d3-brush": "3", |
| | | "d3-chord": "3", |
| | | "d3-color": "3", |
| | | "d3-contour": "4", |
| | | "d3-delaunay": "6", |
| | | "d3-dispatch": "3", |
| | | "d3-drag": "3", |
| | | "d3-dsv": "3", |
| | | "d3-ease": "3", |
| | | "d3-fetch": "3", |
| | | "d3-force": "3", |
| | | "d3-format": "3", |
| | | "d3-geo": "3", |
| | | "d3-hierarchy": "3", |
| | | "d3-interpolate": "3", |
| | | "d3-path": "3", |
| | | "d3-polygon": "3", |
| | | "d3-quadtree": "3", |
| | | "d3-random": "3", |
| | | "d3-scale": "4", |
| | | "d3-scale-chromatic": "3", |
| | | "d3-selection": "3", |
| | | "d3-shape": "3", |
| | | "d3-time": "3", |
| | | "d3-time-format": "4", |
| | | "d3-timer": "3", |
| | | "d3-transition": "3", |
| | | "d3-zoom": "3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-array": { |
| | | "version": "3.2.4", |
| | | "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", |
| | | "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", |
| | | "dependencies": { |
| | | "internmap": "1 - 2" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-axis": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", |
| | | "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-brush": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-3.0.0.tgz", |
| | | "integrity": "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==", |
| | | "dependencies": { |
| | | "d3-dispatch": "1 - 3", |
| | | "d3-drag": "2 - 3", |
| | | "d3-interpolate": "1 - 3", |
| | | "d3-selection": "3", |
| | | "d3-transition": "3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-chord": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-3.0.1.tgz", |
| | | "integrity": "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==", |
| | | "dependencies": { |
| | | "d3-path": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-color": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", |
| | | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-contour": { |
| | | "version": "4.0.2", |
| | | "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-4.0.2.tgz", |
| | | "integrity": "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==", |
| | | "dependencies": { |
| | | "d3-array": "^3.2.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-delaunay": { |
| | | "version": "6.0.4", |
| | | "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz", |
| | | "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==", |
| | | "dependencies": { |
| | | "delaunator": "5" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-dispatch": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", |
| | | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-drag": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", |
| | | "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", |
| | | "dependencies": { |
| | | "d3-dispatch": "1 - 3", |
| | | "d3-selection": "3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-dsv": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz", |
| | | "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==", |
| | | "dependencies": { |
| | | "commander": "7", |
| | | "iconv-lite": "0.6", |
| | | "rw": "1" |
| | | }, |
| | | "bin": { |
| | | "csv2json": "bin/dsv2json.js", |
| | | "csv2tsv": "bin/dsv2dsv.js", |
| | | "dsv2dsv": "bin/dsv2dsv.js", |
| | | "dsv2json": "bin/dsv2json.js", |
| | | "json2csv": "bin/json2dsv.js", |
| | | "json2dsv": "bin/json2dsv.js", |
| | | "json2tsv": "bin/json2dsv.js", |
| | | "tsv2csv": "bin/dsv2dsv.js", |
| | | "tsv2json": "bin/dsv2json.js" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-dsv/node_modules/commander": { |
| | | "version": "7.2.0", |
| | | "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", |
| | | "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", |
| | | "engines": { |
| | | "node": ">= 10" |
| | | } |
| | | }, |
| | | "node_modules/d3-dsv/node_modules/iconv-lite": { |
| | | "version": "0.6.3", |
| | | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", |
| | | "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", |
| | | "dependencies": { |
| | | "safer-buffer": ">= 2.1.2 < 3.0.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=0.10.0" |
| | | } |
| | | }, |
| | | "node_modules/d3-ease": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", |
| | | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-fetch": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-3.0.1.tgz", |
| | | "integrity": "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==", |
| | | "dependencies": { |
| | | "d3-dsv": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-force": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz", |
| | | "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==", |
| | | "dependencies": { |
| | | "d3-dispatch": "1 - 3", |
| | | "d3-quadtree": "1 - 3", |
| | | "d3-timer": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-force-reuse": { |
| | | "version": "1.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-force-reuse/-/d3-force-reuse-1.0.1.tgz", |
| | | "integrity": "sha512-TyJfszB6JZmzOYr3oDayjm0LE1Fz0wsn9DkDcYopDOXY/M07rTTDGQ5wYQMZjmcobND3+Og53CATORFbFuQUqw==", |
| | | "dependencies": { |
| | | "d3-quadtree": "^1.0.3" |
| | | } |
| | | }, |
| | | "node_modules/d3-force-reuse/node_modules/d3-quadtree": { |
| | | "version": "1.0.7", |
| | | "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", |
| | | "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==" |
| | | }, |
| | | "node_modules/d3-format": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", |
| | | "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-geo": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz", |
| | | "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==", |
| | | "dependencies": { |
| | | "d3-array": "2.5.0 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-hierarchy": { |
| | | "version": "3.1.2", |
| | | "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz", |
| | | "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-interpolate": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", |
| | | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", |
| | | "dependencies": { |
| | | "d3-color": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-path": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", |
| | | "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-polygon": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-3.0.1.tgz", |
| | | "integrity": "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-quadtree": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz", |
| | | "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-random": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", |
| | | "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-scale": { |
| | | "version": "4.0.2", |
| | | "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", |
| | | "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", |
| | | "dependencies": { |
| | | "d3-array": "2.10.0 - 3", |
| | | "d3-format": "1 - 3", |
| | | "d3-interpolate": "1.2.0 - 3", |
| | | "d3-time": "2.1.1 - 3", |
| | | "d3-time-format": "2 - 4" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-scale-chromatic": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", |
| | | "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==", |
| | | "dependencies": { |
| | | "d3-color": "1 - 3", |
| | | "d3-interpolate": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-selection": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", |
| | | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-shape": { |
| | | "version": "3.2.0", |
| | | "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", |
| | | "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", |
| | | "dependencies": { |
| | | "d3-path": "^3.1.0" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-time": { |
| | | "version": "3.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", |
| | | "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", |
| | | "dependencies": { |
| | | "d3-array": "2 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-time-format": { |
| | | "version": "4.1.0", |
| | | "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", |
| | | "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", |
| | | "dependencies": { |
| | | "d3-time": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-timer": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", |
| | | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/d3-transition": { |
| | | "version": "3.0.1", |
| | | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", |
| | | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", |
| | | "dependencies": { |
| | | "d3-color": "1 - 3", |
| | | "d3-dispatch": "1 - 3", |
| | | "d3-ease": "1 - 3", |
| | | "d3-interpolate": "1 - 3", |
| | | "d3-timer": "1 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | }, |
| | | "peerDependencies": { |
| | | "d3-selection": "2 - 3" |
| | | } |
| | | }, |
| | | "node_modules/d3-zoom": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", |
| | | "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", |
| | | "dependencies": { |
| | | "d3-dispatch": "1 - 3", |
| | | "d3-drag": "2 - 3", |
| | | "d3-interpolate": "1 - 3", |
| | | "d3-selection": "2 - 3", |
| | | "d3-transition": "2 - 3" |
| | | }, |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/debug": { |
| | | "version": "4.3.4", |
| | | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", |
| | |
| | | "url": "https://github.com/sponsors/wooorm" |
| | | } |
| | | }, |
| | | "node_modules/delaunator": { |
| | | "version": "5.0.0", |
| | | "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz", |
| | | "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==", |
| | | "dependencies": { |
| | | "robust-predicates": "^3.0.0" |
| | | } |
| | | }, |
| | | "node_modules/dequal": { |
| | | "version": "2.0.3", |
| | | "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", |
| | |
| | | "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", |
| | | "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" |
| | | }, |
| | | "node_modules/internmap": { |
| | | "version": "2.0.3", |
| | | "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", |
| | | "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", |
| | | "engines": { |
| | | "node": ">=12" |
| | | } |
| | | }, |
| | | "node_modules/is-absolute-url": { |
| | | "version": "4.0.1", |
| | | "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", |
| | |
| | | "url": "https://github.com/sponsors/isaacs" |
| | | } |
| | | }, |
| | | "node_modules/robust-predicates": { |
| | | "version": "3.0.2", |
| | | "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", |
| | | "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==" |
| | | }, |
| | | "node_modules/run-async": { |
| | | "version": "3.0.0", |
| | | "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", |
| | |
| | | "queue-microtask": "^1.2.2" |
| | | } |
| | | }, |
| | | "node_modules/rw": { |
| | | "version": "1.3.3", |
| | | "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", |
| | | "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==" |
| | | }, |
| | | "node_modules/sade": { |
| | | "version": "1.8.1", |
| | | "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", |
| | |
| | | "@napi-rs/simple-git": "^0.1.8", |
| | | "chalk": "^4.1.2", |
| | | "cli-spinner": "^0.2.10", |
| | | "d3": "^7.8.5", |
| | | "esbuild-sass-plugin": "^2.9.0", |
| | | "github-slugger": "^2.0.0", |
| | | "globby": "^13.1.4", |
| | |
| | | }, |
| | | "devDependencies": { |
| | | "@types/cli-spinner": "^0.2.1", |
| | | "@types/d3": "^7.4.0", |
| | | "@types/hast": "^2.3.4", |
| | | "@types/node": "^20.1.2", |
| | | "@types/pretty-time": "^1.1.2", |
| | |
| | | |
| | | const config: QuartzConfig = { |
| | | configuration: { |
| | | siteTitle: "🪴 Quartz 4.0", |
| | | enableSPA: true, |
| | | ignorePatterns: ["private", "templates"], |
| | | theme: { |
| | |
| | | Plugin.AliasRedirects(), |
| | | Plugin.ContentPage({ |
| | | head: Component.Head(), |
| | | header: [Component.PageTitle(), Component.Spacer(), Component.Darkmode()], |
| | | header: [ |
| | | Component.PageTitle({ title: "🪴 Quartz 4.0" }), |
| | | Component.Spacer(), |
| | | Component.Darkmode() |
| | | ], |
| | | beforeBody: [ |
| | | Component.ArticleTitle(), |
| | | Component.ReadingTime(), |
| | |
| | | ], |
| | | content: Component.Content(), |
| | | left: [ |
| | | Component.TableOfContents(), |
| | | ], |
| | | right: [ |
| | | Component.Graph(), |
| | | Component.TableOfContents(), |
| | | ], |
| | | footer: [] |
| | | }), |
| | |
| | | import { Theme } from "./theme" |
| | | |
| | | export interface GlobalConfiguration { |
| | | siteTitle: string, |
| | | /** Whether to enable single-page-app style rendering. this prevents flashes of unstyled content and improves smoothness of Quartz */ |
| | | enableSPA: boolean, |
| | | /** Glob patterns to not search */ |
| | |
| | | const title = fileData.frontmatter?.title |
| | | const displayTitle = fileData.slug === "index" ? undefined : title |
| | | if (displayTitle) { |
| | | return <h1>{displayTitle}</h1> |
| | | return <h1 class="article-title">{displayTitle}</h1> |
| | | } else { |
| | | return null |
| | | } |
| | | } |
| | | ArticleTitle.css = ` |
| | | .article-title { |
| | | margin: 2rem 0 0 0; |
| | | } |
| | | ` |
| | | |
| | | export default (() => ArticleTitle) satisfies QuartzComponentConstructor |
| New file |
| | |
| | | import { QuartzComponentConstructor } from "./types" |
| | | // @ts-ignore |
| | | import script from "./scripts/graph.inline" |
| | | import style from "./styles/graph.scss" |
| | | |
| | | export interface D3Config { |
| | | drag: boolean, |
| | | zoom: boolean, |
| | | depth: number, |
| | | scale: number, |
| | | repelForce: number, |
| | | centerForce: number, |
| | | linkDistance: number, |
| | | fontSize: number, |
| | | opacityScale: number |
| | | } |
| | | |
| | | interface GraphOptions { |
| | | localGraph: Partial<D3Config>, |
| | | globalGraph: Partial<D3Config> | undefined |
| | | } |
| | | |
| | | const defaultOptions: GraphOptions = { |
| | | localGraph: { |
| | | drag: true, |
| | | zoom: true, |
| | | depth: 1, |
| | | scale: 1.2, |
| | | repelForce: 2, |
| | | centerForce: 1, |
| | | linkDistance: 30, |
| | | fontSize: 0.6, |
| | | opacityScale: 3 |
| | | }, |
| | | globalGraph: { |
| | | drag: true, |
| | | zoom: true, |
| | | depth: -1, |
| | | scale: 1.2, |
| | | repelForce: 1, |
| | | centerForce: 1, |
| | | linkDistance: 30, |
| | | fontSize: 0.5, |
| | | opacityScale: 3 |
| | | } |
| | | } |
| | | |
| | | export default ((opts?: GraphOptions) => { |
| | | function Graph() { |
| | | const localGraph = { ...opts?.localGraph, ...defaultOptions.localGraph } |
| | | const globalGraph = { ...opts?.globalGraph, ...defaultOptions.globalGraph } |
| | | return <div class="graph"> |
| | | <h3>Interactive Graph</h3> |
| | | <div class="graph-outer"> |
| | | <div id="graph-container" data-cfg={JSON.stringify(localGraph)}></div> |
| | | <svg version="1.1" id="global-graph-icon" xmlns="http://www.w3.org/2000/svg" xmlnsXlink="http://www.w3.org/1999/xlink" x="0px" y="0px" |
| | | viewBox="0 0 55 55" fill="currentColor" xmlSpace="preserve"> |
| | | <path d="M49,0c-3.309,0-6,2.691-6,6c0,1.035,0.263,2.009,0.726,2.86l-9.829,9.829C32.542,17.634,30.846,17,29,17 |
| | | s-3.542,0.634-4.898,1.688l-7.669-7.669C16.785,10.424,17,9.74,17,9c0-2.206-1.794-4-4-4S9,6.794,9,9s1.794,4,4,4 |
| | | c0.74,0,1.424-0.215,2.019-0.567l7.669,7.669C21.634,21.458,21,23.154,21,25s0.634,3.542,1.688,4.897L10.024,42.562 |
| | | C8.958,41.595,7.549,41,6,41c-3.309,0-6,2.691-6,6s2.691,6,6,6s6-2.691,6-6c0-1.035-0.263-2.009-0.726-2.86l12.829-12.829 |
| | | c1.106,0.86,2.44,1.436,3.898,1.619v10.16c-2.833,0.478-5,2.942-5,5.91c0,3.309,2.691,6,6,6s6-2.691,6-6c0-2.967-2.167-5.431-5-5.91 |
| | | v-10.16c1.458-0.183,2.792-0.759,3.898-1.619l7.669,7.669C41.215,39.576,41,40.26,41,41c0,2.206,1.794,4,4,4s4-1.794,4-4 |
| | | s-1.794-4-4-4c-0.74,0-1.424,0.215-2.019,0.567l-7.669-7.669C36.366,28.542,37,26.846,37,25s-0.634-3.542-1.688-4.897l9.665-9.665 |
| | | C46.042,11.405,47.451,12,49,12c3.309,0,6-2.691,6-6S52.309,0,49,0z M11,9c0-1.103,0.897-2,2-2s2,0.897,2,2s-0.897,2-2,2 |
| | | S11,10.103,11,9z M6,51c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S8.206,51,6,51z M33,49c0,2.206-1.794,4-4,4s-4-1.794-4-4 |
| | | s1.794-4,4-4S33,46.794,33,49z M29,31c-3.309,0-6-2.691-6-6s2.691-6,6-6s6,2.691,6,6S32.309,31,29,31z M47,41c0,1.103-0.897,2-2,2 |
| | | s-2-0.897-2-2s0.897-2,2-2S47,39.897,47,41z M49,10c-2.206,0-4-1.794-4-4s1.794-4,4-4s4,1.794,4,4S51.206,10,49,10z"/> |
| | | </svg> |
| | | </div> |
| | | <div id="global-graph-outer"> |
| | | <div id="global-graph-container" data-cfg={JSON.stringify(globalGraph)}></div> |
| | | </div> |
| | | </div> |
| | | } |
| | | |
| | | Graph.css = style |
| | | Graph.afterDOMLoaded = script |
| | | |
| | | return Graph |
| | | }) satisfies QuartzComponentConstructor |
| | |
| | | import { JSResourceToScriptElement } from "../resources" |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | |
| | | function Head({ fileData, externalResources }: QuartzComponentProps) { |
| | | const slug = fileData.slug! |
| | | const title = fileData.frontmatter?.title ?? "Untitled" |
| | | const description = fileData.description ?? "No description provided" |
| | | const { css, js } = externalResources |
| | | const baseDir = resolveToRoot(slug) |
| | | const iconPath = baseDir + "/static/icon.png" |
| | | const ogImagePath = baseDir + "/static/og-image.png" |
| | | |
| | | return <head> |
| | | <title>{title}</title> |
| | | <meta charSet="utf-8" /> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| | | <meta property="og:title" content={title} /> |
| | | <meta property="og:description" content={title} /> |
| | | <meta property="og:image" content={ogImagePath} /> |
| | | <meta property="og:width" content="1200" /> |
| | | <meta property="og:height" content="675" /> |
| | | <link rel="icon" href={iconPath} /> |
| | | <meta name="description" content={description} /> |
| | | <meta name="generator" content="Quartz" /> |
| | | <link rel="preconnect" href="https://fonts.googleapis.com" /> |
| | | <link rel="preconnect" href="https://fonts.gstatic.com" /> |
| | | {css.map(href => <link key={href} href={href} rel="stylesheet" type="text/css" spa-preserve />)} |
| | | {js.filter(resource => resource.loadTime === "beforeDOMReady").map(res => JSResourceToScriptElement(res, true))} |
| | | </head> |
| | | interface Options { |
| | | prefetchContentIndex: boolean |
| | | } |
| | | |
| | | export default (() => Head) satisfies QuartzComponentConstructor |
| | | const defaultOptions: Options = { |
| | | prefetchContentIndex: true |
| | | } |
| | | |
| | | export default ((opts?: Options) => { |
| | | function Head({ fileData, externalResources }: QuartzComponentProps) { |
| | | const slug = fileData.slug! |
| | | const title = fileData.frontmatter?.title ?? "Untitled" |
| | | const description = fileData.description ?? "No description provided" |
| | | const { css, js } = externalResources |
| | | const baseDir = resolveToRoot(slug) |
| | | const iconPath = baseDir + "/static/icon.png" |
| | | const ogImagePath = baseDir + "/static/og-image.png" |
| | | |
| | | const prefetchContentIndex = opts?.prefetchContentIndex ?? defaultOptions.prefetchContentIndex |
| | | const contentIndexPath = baseDir + "/static/contentIndex.json" |
| | | const contentIndexScript = `const fetchData = fetch(\`${contentIndexPath}\`).then(data => data.json())` |
| | | |
| | | return <head> |
| | | <title>{title}</title> |
| | | <meta charSet="utf-8" /> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| | | <meta property="og:title" content={title} /> |
| | | <meta property="og:description" content={title} /> |
| | | <meta property="og:image" content={ogImagePath} /> |
| | | <meta property="og:width" content="1200" /> |
| | | <meta property="og:height" content="675" /> |
| | | <link rel="icon" href={iconPath} /> |
| | | <meta name="description" content={description} /> |
| | | <meta name="generator" content="Quartz" /> |
| | | <link rel="preconnect" href="https://fonts.googleapis.com" /> |
| | | <link rel="preconnect" href="https://fonts.gstatic.com" /> |
| | | {prefetchContentIndex && <script spa-preserve>{contentIndexScript}</script>} |
| | | {css.map(href => <link key={href} href={href} rel="stylesheet" type="text/css" spa-preserve />)} |
| | | {js.filter(resource => resource.loadTime === "beforeDOMReady").map(res => JSResourceToScriptElement(res, true))} |
| | | </head> |
| | | } |
| | | |
| | | return Head |
| | | }) satisfies QuartzComponentConstructor |
| | |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | |
| | | function Header({ children }: QuartzComponentProps) { |
| | | return <header> |
| | | return (children.length > 0) ? <header> |
| | | {children} |
| | | </header> |
| | | </header> : null |
| | | } |
| | | |
| | | Header.css = ` |
| | |
| | | display: flex; |
| | | flex-direction: row; |
| | | align-items: center; |
| | | margin: 1em 0 2em 0; |
| | | & > h1 { |
| | | } |
| | | margin: 2em 0; |
| | | } |
| | | |
| | | header > h1 { |
| | | header h1 { |
| | | margin: 0; |
| | | flex: auto; |
| | | } |
| | |
| | | import { resolveToRoot } from "../path" |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "./types" |
| | | |
| | | function PageTitle({ cfg, fileData }: QuartzComponentProps) { |
| | | const title = cfg.siteTitle |
| | | const slug = fileData.slug! |
| | | const baseDir = resolveToRoot(slug) |
| | | return <h1><a href={baseDir}>{title}</a></h1> |
| | | interface Options { |
| | | title: string |
| | | } |
| | | |
| | | export default (() => PageTitle) satisfies QuartzComponentConstructor |
| | | export default ((opts?: Options) => { |
| | | const title = opts?.title ?? "Untitled Quartz" |
| | | function PageTitle({ fileData }: QuartzComponentProps) { |
| | | const slug = fileData.slug! |
| | | const baseDir = resolveToRoot(slug) |
| | | return <h1 class="page-title"><a href={baseDir}>{title}</a></h1> |
| | | } |
| | | PageTitle.css = ` |
| | | .page-title { |
| | | margin: 0; |
| | | } |
| | | ` |
| | | |
| | | return PageTitle |
| | | }) satisfies QuartzComponentConstructor |
| | |
| | | return null |
| | | } |
| | | |
| | | return <> |
| | | return <div> |
| | | <button type="button" id="toc"> |
| | | <h3>Table of Contents</h3> |
| | | <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="fold"> |
| | |
| | | </li>)} |
| | | </ul> |
| | | </div> |
| | | </> |
| | | </div> |
| | | } |
| | | TableOfContents.css = modernStyle |
| | | TableOfContents.afterDOMLoaded = script |
| | |
| | | import Spacer from "./Spacer" |
| | | import TableOfContents from "./TableOfContents" |
| | | import TagList from "./TagList" |
| | | import Graph from "./Graph" |
| | | |
| | | export { |
| | | ArticleTitle, |
| | |
| | | ReadingTime, |
| | | Spacer, |
| | | TableOfContents, |
| | | TagList |
| | | TagList, |
| | | Graph |
| | | } |
| New file |
| | |
| | | import { ContentDetails } from "../../plugins/emitters/contentIndex" |
| | | import * as d3 from 'd3' |
| | | |
| | | type NodeData = { |
| | | id: string, |
| | | text: string, |
| | | tags: string[] |
| | | } & d3.SimulationNodeDatum |
| | | |
| | | type LinkData = { |
| | | source: string, |
| | | target: string |
| | | } |
| | | |
| | | function relative(from: string, to: string) { |
| | | const pieces = [location.protocol, '//', location.host, location.pathname] |
| | | const url = pieces.join('').slice(0, -from.length) + to |
| | | return url |
| | | } |
| | | |
| | | function removeAllChildren(node: HTMLElement) { |
| | | while (node.firstChild) { |
| | | node.removeChild(node.firstChild) |
| | | } |
| | | } |
| | | |
| | | async function renderGraph(container: string, slug: string) { |
| | | const graph = document.getElementById(container)! |
| | | removeAllChildren(graph) |
| | | |
| | | let { |
| | | drag: enableDrag, |
| | | zoom: enableZoom, |
| | | depth, |
| | | scale, |
| | | repelForce, |
| | | centerForce, |
| | | linkDistance, |
| | | fontSize, |
| | | opacityScale |
| | | } = JSON.parse(graph.dataset["cfg"]!) |
| | | |
| | | const data = await fetchData |
| | | |
| | | const links: LinkData[] = [] |
| | | for (const [src, details] of Object.entries<ContentDetails>(data)) { |
| | | const outgoing = details.links ?? [] |
| | | for (const dest of outgoing) { |
| | | if (src in data && dest in data) { |
| | | links.push({ source: src, target: dest }) |
| | | } |
| | | } |
| | | } |
| | | |
| | | const neighbourhood = new Set() |
| | | |
| | | const wl = [slug, "__SENTINEL"] |
| | | if (depth >= 0) { |
| | | while (depth >= 0 && wl.length > 0) { |
| | | // compute neighbours |
| | | const cur = wl.shift() |
| | | if (cur === "__SENTINEL") { |
| | | depth-- |
| | | wl.push("__SENTINEL") |
| | | } else { |
| | | neighbourhood.add(cur) |
| | | const outgoing = links.filter(l => l.source === cur) |
| | | const incoming = links.filter(l => l.target === cur) |
| | | wl.push(...outgoing.map((l) => l.target), ...incoming.map((l) => l.source)) |
| | | } |
| | | } |
| | | } else { |
| | | links.flatMap(l => [l.source, l.target]).forEach((id) => neighbourhood.add(id)) |
| | | } |
| | | |
| | | const graphData: { nodes: NodeData[], links: LinkData[] } = { |
| | | nodes: Object.keys(data).filter(id => neighbourhood.has(id)).map(url => ({ id: url, text: data[url]?.title ?? url, tags: data[url]?.tags ?? [] })), |
| | | links: links.filter((l) => neighbourhood.has(l.source) && neighbourhood.has(l.target)) |
| | | } |
| | | |
| | | const simulation: d3.Simulation<NodeData, LinkData> = d3 |
| | | .forceSimulation(graphData.nodes) |
| | | .force("charge", d3.forceManyBody().strength(-100 * repelForce)) |
| | | .force( |
| | | "link", |
| | | d3 |
| | | .forceLink(graphData.links) |
| | | .id((d: any) => d.id) |
| | | .distance(linkDistance), |
| | | ) |
| | | .force("center", d3.forceCenter().strength(centerForce)) |
| | | |
| | | const height = Math.max(graph.offsetHeight, 250) |
| | | const width = graph.offsetWidth |
| | | |
| | | const svg = d3 |
| | | .select<HTMLElement, NodeData>('#' + container) |
| | | .append("svg") |
| | | .attr("width", width) |
| | | .attr("height", height) |
| | | .attr('viewBox', [-width / 2 / scale, -height / 2 / scale, width / scale, height / scale]) |
| | | |
| | | // draw links between nodes |
| | | const link = svg |
| | | .append("g") |
| | | .selectAll("line") |
| | | .data(graphData.links) |
| | | .join("line") |
| | | .attr("class", "link") |
| | | .attr("stroke", "var(--lightgray)") |
| | | .attr("stroke-width", 2) |
| | | |
| | | // svg groups |
| | | const graphNode = svg.append("g").selectAll("g").data(graphData.nodes).enter().append("g") |
| | | |
| | | // calculate radius |
| | | const color = (d: NodeData) => { |
| | | // TODO: does this handle the index page |
| | | const isCurrent = d.id === slug |
| | | return isCurrent ? "var(--secondary)" : "var(--gray)" |
| | | } |
| | | |
| | | const drag = (simulation: d3.Simulation<NodeData, LinkData>) => { |
| | | function dragstarted(event: any, d: NodeData) { |
| | | if (!event.active) simulation.alphaTarget(1).restart() |
| | | d.fx = d.x |
| | | d.fy = d.y |
| | | } |
| | | |
| | | function dragged(event: any, d: NodeData) { |
| | | d.fx = event.x |
| | | d.fy = event.y |
| | | } |
| | | |
| | | function dragended(event: any, d: NodeData) { |
| | | if (!event.active) simulation.alphaTarget(0) |
| | | d.fx = null |
| | | d.fy = null |
| | | } |
| | | |
| | | const noop = () => { } |
| | | return d3 |
| | | .drag<Element, NodeData>() |
| | | .on("start", enableDrag ? dragstarted : noop) |
| | | .on("drag", enableDrag ? dragged : noop) |
| | | .on("end", enableDrag ? dragended : noop) |
| | | } |
| | | |
| | | function nodeRadius(d: NodeData) { |
| | | const numLinks = links.filter((l: any) => l.source.id === d.id || l.target.id === d.id).length |
| | | return 2 + Math.sqrt(numLinks) |
| | | } |
| | | |
| | | // draw individual nodes |
| | | const node = graphNode |
| | | .append("circle") |
| | | .attr("class", "node") |
| | | .attr("id", (d) => d.id) |
| | | .attr("r", nodeRadius) |
| | | .attr("fill", color) |
| | | .style("cursor", "pointer") |
| | | .on("click", (_, d) => { |
| | | const targ = relative(slug, d.id) |
| | | window.spaNavigate(new URL(targ)) |
| | | }) |
| | | .on("mouseover", function(_, d) { |
| | | const neighbours: string[] = data[slug].links ?? [] |
| | | const neighbourNodes = d3.selectAll<HTMLElement, NodeData>(".node").filter((d) => neighbours.includes(d.id)) |
| | | const currentId = d.id |
| | | const linkNodes = d3 |
| | | .selectAll(".link") |
| | | .filter((d: any) => d.source.id === currentId || d.target.id === currentId) |
| | | |
| | | // highlight neighbour nodes |
| | | neighbourNodes.transition().duration(200).attr("fill", color) |
| | | |
| | | // highlight links |
| | | linkNodes.transition().duration(200).attr("stroke", "var(--gray)") |
| | | |
| | | const bigFont = fontSize * 1.5 |
| | | |
| | | // show text for self |
| | | const parent = this.parentNode as HTMLElement |
| | | d3.select<HTMLElement, NodeData>(parent) |
| | | .raise() |
| | | .select("text") |
| | | .transition() |
| | | .duration(200) |
| | | .attr('opacityOld', d3.select(parent).select('text').style("opacity")) |
| | | .style('opacity', 1) |
| | | .style('font-size', bigFont + 'em') |
| | | }) |
| | | .on("mouseleave", function(_, d) { |
| | | const currentId = d.id |
| | | const linkNodes = d3 |
| | | .selectAll(".link") |
| | | .filter((d: any) => d.source.id === currentId || d.target.id === currentId) |
| | | |
| | | linkNodes.transition().duration(200).attr("stroke", "var(--lightgray)") |
| | | |
| | | const parent = this.parentNode as HTMLElement |
| | | d3.select<HTMLElement, NodeData>(parent) |
| | | .select("text") |
| | | .transition() |
| | | .duration(200) |
| | | .style('opacity', d3.select(parent).select('text').attr("opacityOld")) |
| | | .style('font-size', fontSize + 'em') |
| | | }) |
| | | // @ts-ignore |
| | | .call(drag(simulation)) |
| | | |
| | | // draw labels |
| | | const labels = graphNode |
| | | .append("text") |
| | | .attr("dx", 0) |
| | | .attr("dy", (d) => nodeRadius(d) + 8 + "px") |
| | | .attr("text-anchor", "middle") |
| | | .text((d) => data[d.id]?.title || (d.id.charAt(1).toUpperCase() + d.id.slice(2)).replace("-", " ")) |
| | | .style('opacity', (opacityScale - 1) / 3.75) |
| | | .style("pointer-events", "none") |
| | | .style('font-size', fontSize + 'em') |
| | | .raise() |
| | | // @ts-ignore |
| | | .call(drag(simulation)) |
| | | |
| | | // set panning |
| | | if (enableZoom) { |
| | | svg.call( |
| | | d3 |
| | | .zoom<SVGSVGElement, NodeData>() |
| | | .extent([ |
| | | [0, 0], |
| | | [width, height], |
| | | ]) |
| | | .scaleExtent([0.25, 4]) |
| | | .on("zoom", ({ transform }) => { |
| | | link.attr("transform", transform) |
| | | node.attr("transform", transform) |
| | | const scale = transform.k * opacityScale; |
| | | const scaledOpacity = Math.max((scale - 1) / 3.75, 0) |
| | | labels.attr("transform", transform).style("opacity", scaledOpacity) |
| | | }), |
| | | ) |
| | | } |
| | | |
| | | // progress the simulation |
| | | simulation.on("tick", () => { |
| | | link |
| | | .attr("x1", (d: any) => d.source.x) |
| | | .attr("y1", (d: any) => d.source.y) |
| | | .attr("x2", (d: any) => d.target.x) |
| | | .attr("y2", (d: any) => d.target.y) |
| | | node |
| | | .attr("cx", (d: any) => d.x) |
| | | .attr("cy", (d: any) => d.y) |
| | | labels |
| | | .attr("x", (d: any) => d.x) |
| | | .attr("y", (d: any) => d.y) |
| | | }) |
| | | } |
| | | |
| | | function renderGlobalGraph() { |
| | | const slug = document.body.dataset["slug"]! |
| | | renderGraph("global-graph-container", slug) |
| | | const container = document.getElementById("global-graph-outer") |
| | | container?.classList.add("active") |
| | | |
| | | function hideGlobalGraph(this: HTMLElement, e: HTMLElementEventMap["click"]) { |
| | | if (e.target !== this) return |
| | | |
| | | container?.classList.remove("active") |
| | | const graph = document.getElementById("global-graph-container")! |
| | | removeAllChildren(graph) |
| | | } |
| | | |
| | | container?.removeEventListener("click", hideGlobalGraph) |
| | | container?.addEventListener("click", hideGlobalGraph) |
| | | } |
| | | |
| | | document.addEventListener("nav", async (e: unknown) => { |
| | | const slug = (e as CustomEventMap["nav"]).detail.url |
| | | await renderGraph("graph-container", slug) |
| | | |
| | | const containerIcon = document.getElementById("global-graph-icon") |
| | | containerIcon?.removeEventListener("click", renderGlobalGraph) |
| | | containerIcon?.addEventListener("click", renderGlobalGraph) |
| | | }) |
| | |
| | | import { computePosition, inline, shift, autoPlacement } from "@floating-ui/dom" |
| | | import { computePosition, flip, inline, shift } from "@floating-ui/dom" |
| | | |
| | | document.addEventListener("nav", () => { |
| | | const links = [...document.getElementsByClassName("internal")] as HTMLLinkElement[] |
| | | const p = new DOMParser() |
| | | for (const link of links) { |
| | | link.addEventListener("mouseenter", async ({ clientX, clientY }) => { |
| | | if (link.dataset.fetchedPopover === "true") return |
| | | async function setPosition(popoverElement: HTMLElement) { |
| | | const { x, y } = await computePosition(link, popoverElement, { |
| | | middleware: [inline({ |
| | | x: clientX, |
| | | y: clientY |
| | | }), shift(), flip()] |
| | | }) |
| | | Object.assign(popoverElement.style, { |
| | | left: `${x}px`, |
| | | top: `${y}px`, |
| | | }) |
| | | } |
| | | |
| | | if (link.dataset.fetchedPopover === "true") { |
| | | return setPosition(link.lastChild as HTMLElement) |
| | | } |
| | | |
| | | const url = link.href |
| | | const anchor = new URL(url).hash |
| | | if (anchor.startsWith("#")) return |
| | | |
| | | const contents = await fetch(`${url}`) |
| | | .then((res) => res.text()) |
| | | .catch((err) => { |
| | | console.error(err) |
| | | }) |
| | | |
| | | if (!contents) return |
| | | const html = p.parseFromString(contents, "text/html") |
| | | const elts = [...html.getElementsByClassName("popover-hint")] |
| | | if (elts.length === 0) return |
| | | |
| | | |
| | | const popoverElement = document.createElement("div") |
| | | popoverElement.classList.add("popover") |
| | | elts.forEach(elt => popoverElement.appendChild(elt)) |
| | | const popoverInner = document.createElement("div") |
| | | popoverInner.classList.add("popover-inner") |
| | | popoverElement.appendChild(popoverInner) |
| | | elts.forEach(elt => popoverInner.appendChild(elt)) |
| | | |
| | | const { x, y } = await computePosition(link, popoverElement, { |
| | | middleware: [inline({ |
| | | x: clientX, |
| | | y: clientY |
| | | }), shift(), autoPlacement()] |
| | | }) |
| | | |
| | | Object.assign(popoverElement.style, { |
| | | left: `${x}px`, |
| | | top: `${y}px`, |
| | | }) |
| | | |
| | | setPosition(popoverElement) |
| | | link.appendChild(popoverElement) |
| | | link.dataset.fetchedPopover = "true" |
| | | }) |
| | |
| | | return { url: new URL(href), scroll: 'routerNoscroll' in a.dataset ? false : undefined } |
| | | } |
| | | |
| | | function notifyNav(slug: string) { |
| | | const event = new CustomEvent("nav", { detail: { slug } }) |
| | | function notifyNav(url: string) { |
| | | const event: CustomEventMap["nav"] = new CustomEvent("nav", { detail: { url } }) |
| | | document.dispatchEvent(event) |
| | | } |
| | | |
| | |
| | | delete announcer.dataset.persist |
| | | } |
| | | |
| | | window.spaNavigate = navigate |
| | | |
| | | function createRouter() { |
| | | if (typeof window !== "undefined") { |
| | | window.addEventListener("click", async (event) => { |
| | |
| | | .darkmode { |
| | | float: right; |
| | | padding: 1rem; |
| | | min-width: 30px; |
| | | position: relative; |
| | | width: 20px; |
| | | height: 20px; |
| | | |
| | | & > .toggle { |
| | | display: none; |
| | |
| | | width: 20px; |
| | | height: 20px; |
| | | top: calc(50% - 10px); |
| | | margin: 0 7px; |
| | | fill: var(--darkgray); |
| | | transition: opacity 0.1s ease; |
| | | } |
| New file |
| | |
| | | .graph { |
| | | & > h3 { |
| | | font-size: 1rem; |
| | | margin: 0 |
| | | } |
| | | |
| | | & > .graph-outer { |
| | | border-radius: 5px; |
| | | border: 1px solid var(--lightgray); |
| | | box-sizing: border-box; |
| | | height: 250px; |
| | | width: 300px; |
| | | margin: 0.5em 0; |
| | | position: relative; |
| | | |
| | | & > #global-graph-icon { |
| | | color: var(--dark); |
| | | opacity: 0.5; |
| | | width: 18px; |
| | | height: 18px; |
| | | position: absolute; |
| | | padding: 0.2rem; |
| | | margin: 0.3rem; |
| | | top: 0; |
| | | right: 0; |
| | | border-radius: 4px; |
| | | background-color: transparent; |
| | | transition: background-color 0.5s ease; |
| | | cursor: pointer; |
| | | &:hover { |
| | | background-color: var(--lightgray); |
| | | } |
| | | } |
| | | |
| | | & > #graph-container > svg { |
| | | margin-bottom: -5px; |
| | | } |
| | | } |
| | | |
| | | & > #global-graph-outer { |
| | | position: fixed; |
| | | z-index: 9999; |
| | | left: 0; |
| | | top: 0; |
| | | width: 100vw; |
| | | height: 100%; |
| | | overflow: scroll; |
| | | backdrop-filter: blur(4px); |
| | | display: none; |
| | | |
| | | &.active { |
| | | display: inline-block; |
| | | } |
| | | |
| | | & > #global-graph-container { |
| | | border: 1px solid var(--lightgray); |
| | | background-color: var(--light); |
| | | border-radius: 5px; |
| | | box-sizing: border-box; |
| | | position: fixed; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | height: 60vh; |
| | | width: 50vw; |
| | | } |
| | | } |
| | | } |
| | |
| | | opacity: 0; |
| | | visibility: hidden; |
| | | } |
| | | 50% { |
| | | 1% { |
| | | opacity: 0; |
| | | } |
| | | 100% { |
| | |
| | | .popover { |
| | | z-index: 999; |
| | | position: absolute; |
| | | overflow: scroll; |
| | | width: 30rem; |
| | | height: 20rem; |
| | | padding: 0 1rem; |
| | | margin-top: -1rem; |
| | | border: 1px solid var(--lightgray); |
| | | background-color: var(--light); |
| | | border-radius: 5px; |
| | | box-shadow: 6px 6px 36px 0 rgba(0,0,0,0.25); |
| | | overflow: visible; |
| | | padding: 1rem; |
| | | |
| | | font-weight: initial; |
| | | & > .popover-inner { |
| | | width: 30rem; |
| | | height: 20rem; |
| | | padding: 0 1rem 1rem 1rem; |
| | | font-weight: initial; |
| | | border: 1px solid var(--gray); |
| | | background-color: var(--light); |
| | | border-radius: 5px; |
| | | box-shadow: 6px 6px 36px 0 rgba(0,0,0,0.25); |
| | | overflow: scroll; |
| | | } |
| | | |
| | | visibility: hidden; |
| | | opacity: 0; |
| | | transition: opacity 0.2s ease, visibility 0.2s ease; |
| | | transition: opacity 0.3s ease, visibility 0.3s ease; |
| | | |
| | | @media all and (max-width: 600px) { |
| | | display: none !important; |
| | |
| | | } |
| | | |
| | | a:hover .popover, .popover:hover { |
| | | animation: dropin 0.5s ease; |
| | | opacity: 1; |
| | | visibility: visible; |
| | | animation: dropin 0.3s ease; |
| | | animation-fill-mode: forwards; |
| | | animation-delay: 0.2s; |
| | | } |
| | |
| | | overflow: hidden; |
| | | max-height: none; |
| | | transition: max-height 0.3s ease; |
| | | font-size: 0.9rem; |
| | | |
| | | & ul { |
| | | list-style: none; |
| | |
| | | & > li > a { |
| | | color: var(--dark); |
| | | opacity: 0.35; |
| | | transition: 0.5s ease opacity; |
| | | transition: 0.5s ease opacity, 0.3s ease color; |
| | | &.in-view { |
| | | opacity: 0.75; |
| | | } |
| | |
| | | cleanPath = cleanPath.slice(0, -"index".length) |
| | | } |
| | | |
| | | if (cleanPath === "") { |
| | | cleanPath = "./" |
| | | } |
| | | |
| | | return cleanPath + anchor |
| | | } |
| | | |
| | |
| | | export function resolveToRoot(slug: string): string { |
| | | let fp = trimPathSuffix(slug) |
| | | |
| | | if (fp === "./") { |
| | | if (fp === "") { |
| | | return "." |
| | | } |
| | | |
| | |
| | | indexExternalLinks: false, |
| | | } |
| | | |
| | | type ContentIndex = Map<string, { |
| | | export type ContentIndex = Map<string, ContentDetails> |
| | | export type ContentDetails = { |
| | | title: string, |
| | | links?: string[], |
| | | tags?: string[], |
| | | content: string, |
| | | }> |
| | | } |
| | | |
| | | export const ContentIndex: QuartzEmitterPlugin<Options> = (userOpts) => { |
| | | const opts = { ...userOpts, ...defaultOptions } |
| | | return { |
| | | name: "ContentIndex", |
| | | async emit(_contentDir, _cfg, content, _resources, emit) { |
| | | const fp = "contentIndex" |
| | | const fp = path.join("static", "contentIndex") |
| | | const linkIndex: ContentIndex = new Map() |
| | | for (const [tree, file] of content) { |
| | | let slug = trimPathSuffix(file.data.slug!) |
| | |
| | | import { QuartzEmitterPlugin } from "../types" |
| | | import { render } from "preact-render-to-string" |
| | | import { QuartzComponent } from "../../components/types" |
| | | import { resolveToRoot } from "../../path" |
| | | import { resolveToRoot, trimPathSuffix } from "../../path" |
| | | import HeaderConstructor from "../../components/Header" |
| | | import { QuartzComponentProps } from "../../components/types" |
| | | import BodyConstructor from "../../components/Body" |
| | |
| | | const Content = opts.content |
| | | const doc = <html> |
| | | <Head {...componentData} /> |
| | | <body data-slug={file.data.slug}> |
| | | <body data-slug={trimPathSuffix(file.data.slug ?? "")}> |
| | | <div id="quartz-root" class="page"> |
| | | <Header {...componentData} > |
| | | {header.map(HeaderComponent => <HeaderComponent {...componentData} />)} |
| | |
| | | |
| | | body { |
| | | margin: 0; |
| | | height: 100vh; |
| | | width: 100vw; |
| | | max-width: 100%; |
| | | box-sizing: border-box; |
| | | background-color: var(--light); |
| | |
| | | } |
| | | |
| | | .page { |
| | | padding: 4rem 30vw; |
| | | margin: 0 auto; |
| | | margin: 6rem 35vw 6rem 20vw; |
| | | max-width: 1000px; |
| | | position: relative; |
| | | |
| | | & .left, & .right { |
| | | position: fixed; |
| | | padding: 0 4rem 0 6rem; |
| | | max-width: 30vw; |
| | | height: 100vh; |
| | | overflow-y: scroll; |
| | | box-sizing: border-box; |
| | | top: 10rem; |
| | | display: flex; |
| | | flex-direction: column; |
| | | top: 0; |
| | | gap: 2rem; |
| | | padding: 6rem; |
| | | } |
| | | |
| | | & .left { |
| | | left: 0; |
| | | padding-left: 10vw; |
| | | width: 20vw; |
| | | } |
| | | |
| | | & .right { |
| | | right: 0; |
| | | padding-right: 10vw; |
| | | width: 35vw; |
| | | } |
| | | |
| | | @media all and (max-width: 1200px) { |
| | | padding: 25px 5vw; |
| | | margin: 25px 5vw; |
| | | & .left, & .right { |
| | | padding: 0; |
| | | height: initial; |
| | | max-width: none; |
| | | position: initial; |
| | | } |
| | |
| | | width: 100%; |
| | | border-radius: 5px; |
| | | } |
| | | |
| | | .spacer { |
| | | flex: 1 1 auto; |
| | | } |