├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── LICENSE.md ├── config.toml ├── main.ts ├── package.json ├── pnpm-lock.yaml ├── readme.md └── tsconfig.json /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Publish Book Daily 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | schedule: 7 | - cron: "0 0 1 * *" 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | 12 | strategy: 13 | matrix: 14 | node-version: [20.x] 15 | steps: 16 | - name: Get current date 17 | id: date 18 | run: echo "::set-output name=date::$(date +'%Y-%m-%d')" 19 | - uses: actions/checkout@v2 20 | - name: Use Node.js ${{ matrix.node-version }} 21 | uses: actions/setup-node@v2 22 | with: 23 | node-version: ${{ matrix.node-version }} 24 | - run: npm install -g yarn 25 | - run: yarn 26 | - run: yarn playwright install --with-deps 27 | - run: yarn start 28 | 29 | - uses: "marvinpinto/action-automatic-releases@latest" 30 | with: 31 | repo_token: "${{ secrets.GITHUB_TOKEN }}" 32 | automatic_release_tag: release-${{ steps.date.outputs.date }} 33 | prerelease: false 34 | title: Release ${{ steps.date.outputs.date }} 35 | files: | 36 | *.pdf 37 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.pdf 3 | .vscode -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Shirshak 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config.toml: -------------------------------------------------------------------------------- 1 | [Books.The_Rust_Programming_Language] 2 | print_url="https://doc.rust-lang.org/book/print.html" 3 | file_name="the_rust_programming_language.pdf" 4 | 5 | [Books.High_Assurance_Rust] 6 | print_url="https://highassurance.rs/print.html" 7 | file_name="high_assurance_rust.pdf" 8 | 9 | [Books.Nomicon] 10 | print_url="https://doc.rust-lang.org/nomicon/print.html" 11 | file_name="nomicon.pdf" 12 | 13 | [Books.Rust_Cookbook] 14 | print_url="https://rust-lang-nursery.github.io/rust-cookbook/print.html" 15 | file_name="cookbook.pdf" 16 | 17 | [Books.RustWasm] 18 | print_url="https://rustwasm.github.io/docs/book/print.html" 19 | file_name="rust_wasm.pdf" 20 | 21 | [Books.EasyRust] 22 | print_url="https://dhghomon.github.io/easy_rust/print.html" 23 | file_name="easy_rust.pdf" 24 | 25 | [Books.EmbeddedRust] 26 | print_url="https://docs.rust-embedded.org/book/print.html" 27 | file_name="embedded_rust_book.pdf" 28 | 29 | [Books.RustReference] 30 | print_url="https://doc.rust-lang.org/reference/print.html" 31 | file_name="rust_reference.pdf" 32 | 33 | [Books.ClI] 34 | print_url="https://rust-cli.github.io/book/print.html" 35 | file_name="rust_cli.pdf" 36 | 37 | [Books.RustByExample] 38 | print_url="https://doc.rust-lang.org/rust-by-example/print.html" 39 | file_name="rust_by_example.pdf" 40 | 41 | [Books.RustFuzzBook] 42 | print_url="https://rust-fuzz.github.io/book/print.html" 43 | file_name="rust_fuzz.pdf" 44 | 45 | [Books.RustPerformanceBook] 46 | print_url="https://nnethercote.github.io/perf-book/print.html" 47 | file_name="rust_performance.pdf" 48 | 49 | [Books.RustDesignPatterns] 50 | print_url="https://rust-unofficial.github.io/patterns/print.html" 51 | file_name="rust_design_patterns.pdf" 52 | 53 | [Books.LearnWithLinkedList] 54 | print_url="https://rust-unofficial.github.io/too-many-lists/print.html" 55 | file_name="rust_linked_list.pdf" 56 | 57 | 58 | [Books.RustPractiseQuestions] 59 | print_url="https://rust-unofficial.github.io/rust-practise-questions/print.html" 60 | file_name="rust_practise_questions.pdf" 61 | 62 | [Books.The_Rust_Discovery-microbit] 63 | print_url="https://docs.rust-embedded.org/discovery/microbit/print.html" 64 | file_name="microbit_beginner_rust.pdf" 65 | 66 | [Books.The_Rust_DiscoverySTM] 67 | print_url="https://docs.rust-embedded.org/discovery/f3discovery/print.html" 68 | file_name="stm32f3discovery_beginner_rust.pdf" -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { Browser, chromium } from "playwright" 2 | import path from "path" 3 | import process from "process" 4 | import toml from "toml" 5 | import fs from "fs" 6 | import pLimit from 'p-limit' 7 | import { setTimeout as delay } from "node:timers/promises" 8 | 9 | declare const document: any 10 | 11 | let config = toml.parse(fs.readFileSync("./config.toml").toString()) 12 | 13 | 14 | async function main() { 15 | console.log("Starting", { debugFirstPageOnly: process.env.DEBUG_ONLY_FRIST === "true" }) 16 | let browser = await chromium.launch({ headless: true }) 17 | 18 | // concurrency of 5 19 | let limit = pLimit(10) 20 | let proms = [] 21 | 22 | for (let book_key in config.Books) { 23 | for (let mode of ["dark", "light"] as const) { 24 | proms.push(limit((...args) => fetchBook(...args), book_key, browser, mode)) 25 | } 26 | 27 | if (process.env.DEBUG_ONLY_FRIST === "true") { 28 | break 29 | } 30 | } 31 | 32 | await Promise.all(proms) 33 | console.log("Completed") 34 | await browser.close() 35 | process.exit(0) 36 | } 37 | 38 | async function fetchBook(book_key: string, browser: Browser, mode: "dark" | "light") { 39 | let context = await browser.newContext({ colorScheme: mode }) 40 | let page = await context.newPage() 41 | let book = config.Books[book_key] 42 | 43 | console.log("Download from", book_key) 44 | 45 | await page.goto(book.print_url) 46 | await page.evaluate(() => { 47 | // workaround for working with tsx 48 | window.__name = () => { } 49 | let head = document.querySelector("head") 50 | let link = document.createElement("link") 51 | link.href = "https://fonts.googleapis.com/css2?family=Nunito:wght@200;300;900&display=swap" 52 | link.rel = "stylesheet" 53 | head.appendChild(link) 54 | 55 | let link2 = document.createElement("link2") 56 | link2.href = " https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&display=swap" 57 | link2.rel = "stylesheet" 58 | head.appendChild(link2) 59 | 60 | var styles = ` 61 | html { 62 | font-family: Nunito 63 | } 64 | 65 | body{ 66 | margin: 40px 25px 40ox 25px !important; 67 | } 68 | 69 | pre, code { 70 | font-family: 'Fira Code', monospace; 71 | } 72 | 73 | .fa.fa-copy clip-button { 74 | display:none 75 | } 76 | 77 | h1 { 78 | page-break-before: always; 79 | } 80 | ` 81 | var styleSheet = document.createElement("style") 82 | styleSheet.type = "text/css" 83 | styleSheet.innerText = styles 84 | document.head.appendChild(styleSheet) 85 | }) 86 | 87 | // Add table of contents 88 | await page.evaluate(() => { 89 | // Create the table of contents container 90 | const toc = document.createElement('div') 91 | toc.id = 'table-of-contents' 92 | toc.innerHTML = '

Table of Contents

' 93 | toc.style.margin = '40px' 94 | // Find all headings 95 | const headings = document.querySelectorAll('h1, h2, h3, h4, h5, h6') 96 | const tocList = document.createElement('ul') 97 | 98 | // Calculate page height (assuming A4 page size) 99 | const pageHeight = 1122 // A4 height in pixels at 96 DPI 100 | 101 | headings.forEach((heading: any, index: any) => { 102 | const listItem = document.createElement('li') 103 | const link = document.createElement('a') 104 | 105 | // Set the link text and href 106 | link.textContent = heading.textContent 107 | link.href = `#heading-${index}` 108 | 109 | // Add a class based on the heading level 110 | listItem.className = `toc-${heading.tagName.toLowerCase()}` 111 | 112 | // Create a span for the dotted line 113 | const dots = document.createElement('span') 114 | dots.className = 'dots' 115 | 116 | // Append elements 117 | listItem.appendChild(link) 118 | listItem.appendChild(dots) 119 | tocList.appendChild(listItem) 120 | 121 | // Add an id to the heading 122 | heading.id = `heading-${index}` 123 | }) 124 | 125 | toc.appendChild(tocList) 126 | 127 | // Insert the table of contents at the beginning of the body 128 | document.body.insertBefore(toc, document.body.firstChild) 129 | }) 130 | 131 | if (book.file_name.includes("high_assurance_rust")) { 132 | await page.click("#sidebar-toggle") 133 | } 134 | 135 | 136 | if (process.env.DEBUG_ONLY_FRIST === "true") { 137 | console.log("Waiting for 5 seconds") 138 | await delay(5 * 1000) 139 | } else { 140 | console.log("Waiting for 20 seconds") 141 | await delay(20 * 1000) 142 | } 143 | 144 | let dest = path.resolve(book.file_name.replace(".pdf", `_${mode}.pdf`)) 145 | await page.pdf({ 146 | path: dest, 147 | format: "A4", 148 | printBackground: true, 149 | margin: { 150 | top: 0, 151 | bottom: 0, 152 | left: 0, 153 | right: 0, 154 | }, 155 | displayHeaderFooter: true, 156 | headerTemplate: ` 157 |
158 | `, 159 | }) 160 | 161 | console.log(`Successfully printed? ${dest}`) 162 | } 163 | 164 | main().catch((e) => { 165 | console.log("Error on main", e) 166 | process.exit(0) 167 | }) 168 | 169 | export { } 170 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rust-books", 3 | "type": "module", 4 | "version": "1.0.0", 5 | "main": "main.ts", 6 | "license": "MIT", 7 | "scripts": { 8 | "start": "tsx main.ts" 9 | }, 10 | "dependencies": { 11 | "meow": "^13.2.0", 12 | "p-limit": "^6.1.0", 13 | "playwright": "1.47.0", 14 | "toml": "^3.0.0", 15 | "tsx": "^4.19.0" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^22.5.4" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '9.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | importers: 8 | 9 | .: 10 | dependencies: 11 | meow: 12 | specifier: ^13.2.0 13 | version: 13.2.0 14 | p-limit: 15 | specifier: ^6.1.0 16 | version: 6.1.0 17 | playwright: 18 | specifier: 1.47.0 19 | version: 1.47.0 20 | toml: 21 | specifier: ^3.0.0 22 | version: 3.0.0 23 | tsx: 24 | specifier: ^4.19.0 25 | version: 4.19.1 26 | devDependencies: 27 | '@types/node': 28 | specifier: ^22.5.4 29 | version: 22.7.6 30 | 31 | packages: 32 | 33 | '@esbuild/aix-ppc64@0.23.1': 34 | resolution: {integrity: sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==} 35 | engines: {node: '>=18'} 36 | cpu: [ppc64] 37 | os: [aix] 38 | 39 | '@esbuild/android-arm64@0.23.1': 40 | resolution: {integrity: sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==} 41 | engines: {node: '>=18'} 42 | cpu: [arm64] 43 | os: [android] 44 | 45 | '@esbuild/android-arm@0.23.1': 46 | resolution: {integrity: sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==} 47 | engines: {node: '>=18'} 48 | cpu: [arm] 49 | os: [android] 50 | 51 | '@esbuild/android-x64@0.23.1': 52 | resolution: {integrity: sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==} 53 | engines: {node: '>=18'} 54 | cpu: [x64] 55 | os: [android] 56 | 57 | '@esbuild/darwin-arm64@0.23.1': 58 | resolution: {integrity: sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==} 59 | engines: {node: '>=18'} 60 | cpu: [arm64] 61 | os: [darwin] 62 | 63 | '@esbuild/darwin-x64@0.23.1': 64 | resolution: {integrity: sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==} 65 | engines: {node: '>=18'} 66 | cpu: [x64] 67 | os: [darwin] 68 | 69 | '@esbuild/freebsd-arm64@0.23.1': 70 | resolution: {integrity: sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==} 71 | engines: {node: '>=18'} 72 | cpu: [arm64] 73 | os: [freebsd] 74 | 75 | '@esbuild/freebsd-x64@0.23.1': 76 | resolution: {integrity: sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==} 77 | engines: {node: '>=18'} 78 | cpu: [x64] 79 | os: [freebsd] 80 | 81 | '@esbuild/linux-arm64@0.23.1': 82 | resolution: {integrity: sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==} 83 | engines: {node: '>=18'} 84 | cpu: [arm64] 85 | os: [linux] 86 | 87 | '@esbuild/linux-arm@0.23.1': 88 | resolution: {integrity: sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==} 89 | engines: {node: '>=18'} 90 | cpu: [arm] 91 | os: [linux] 92 | 93 | '@esbuild/linux-ia32@0.23.1': 94 | resolution: {integrity: sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==} 95 | engines: {node: '>=18'} 96 | cpu: [ia32] 97 | os: [linux] 98 | 99 | '@esbuild/linux-loong64@0.23.1': 100 | resolution: {integrity: sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==} 101 | engines: {node: '>=18'} 102 | cpu: [loong64] 103 | os: [linux] 104 | 105 | '@esbuild/linux-mips64el@0.23.1': 106 | resolution: {integrity: sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==} 107 | engines: {node: '>=18'} 108 | cpu: [mips64el] 109 | os: [linux] 110 | 111 | '@esbuild/linux-ppc64@0.23.1': 112 | resolution: {integrity: sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==} 113 | engines: {node: '>=18'} 114 | cpu: [ppc64] 115 | os: [linux] 116 | 117 | '@esbuild/linux-riscv64@0.23.1': 118 | resolution: {integrity: sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==} 119 | engines: {node: '>=18'} 120 | cpu: [riscv64] 121 | os: [linux] 122 | 123 | '@esbuild/linux-s390x@0.23.1': 124 | resolution: {integrity: sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==} 125 | engines: {node: '>=18'} 126 | cpu: [s390x] 127 | os: [linux] 128 | 129 | '@esbuild/linux-x64@0.23.1': 130 | resolution: {integrity: sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==} 131 | engines: {node: '>=18'} 132 | cpu: [x64] 133 | os: [linux] 134 | 135 | '@esbuild/netbsd-x64@0.23.1': 136 | resolution: {integrity: sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==} 137 | engines: {node: '>=18'} 138 | cpu: [x64] 139 | os: [netbsd] 140 | 141 | '@esbuild/openbsd-arm64@0.23.1': 142 | resolution: {integrity: sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==} 143 | engines: {node: '>=18'} 144 | cpu: [arm64] 145 | os: [openbsd] 146 | 147 | '@esbuild/openbsd-x64@0.23.1': 148 | resolution: {integrity: sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==} 149 | engines: {node: '>=18'} 150 | cpu: [x64] 151 | os: [openbsd] 152 | 153 | '@esbuild/sunos-x64@0.23.1': 154 | resolution: {integrity: sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==} 155 | engines: {node: '>=18'} 156 | cpu: [x64] 157 | os: [sunos] 158 | 159 | '@esbuild/win32-arm64@0.23.1': 160 | resolution: {integrity: sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==} 161 | engines: {node: '>=18'} 162 | cpu: [arm64] 163 | os: [win32] 164 | 165 | '@esbuild/win32-ia32@0.23.1': 166 | resolution: {integrity: sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==} 167 | engines: {node: '>=18'} 168 | cpu: [ia32] 169 | os: [win32] 170 | 171 | '@esbuild/win32-x64@0.23.1': 172 | resolution: {integrity: sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==} 173 | engines: {node: '>=18'} 174 | cpu: [x64] 175 | os: [win32] 176 | 177 | '@types/node@22.7.6': 178 | resolution: {integrity: sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==} 179 | 180 | esbuild@0.23.1: 181 | resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} 182 | engines: {node: '>=18'} 183 | hasBin: true 184 | 185 | fsevents@2.3.2: 186 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 187 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 188 | os: [darwin] 189 | 190 | fsevents@2.3.3: 191 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 192 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 193 | os: [darwin] 194 | 195 | get-tsconfig@4.8.1: 196 | resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} 197 | 198 | meow@13.2.0: 199 | resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} 200 | engines: {node: '>=18'} 201 | 202 | p-limit@6.1.0: 203 | resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} 204 | engines: {node: '>=18'} 205 | 206 | playwright-core@1.47.0: 207 | resolution: {integrity: sha512-1DyHT8OqkcfCkYUD9zzUTfg7EfTd+6a8MkD/NWOvjo0u/SCNd5YmY/lJwFvUZOxJbWNds+ei7ic2+R/cRz/PDg==} 208 | engines: {node: '>=18'} 209 | hasBin: true 210 | 211 | playwright@1.47.0: 212 | resolution: {integrity: sha512-jOWiRq2pdNAX/mwLiwFYnPHpEZ4rM+fRSQpRHwEwZlP2PUANvL3+aJOF/bvISMhFD30rqMxUB4RJx9aQbfh4Ww==} 213 | engines: {node: '>=18'} 214 | hasBin: true 215 | 216 | resolve-pkg-maps@1.0.0: 217 | resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} 218 | 219 | toml@3.0.0: 220 | resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} 221 | 222 | tsx@4.19.1: 223 | resolution: {integrity: sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==} 224 | engines: {node: '>=18.0.0'} 225 | hasBin: true 226 | 227 | undici-types@6.19.8: 228 | resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} 229 | 230 | yocto-queue@1.1.1: 231 | resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} 232 | engines: {node: '>=12.20'} 233 | 234 | snapshots: 235 | 236 | '@esbuild/aix-ppc64@0.23.1': 237 | optional: true 238 | 239 | '@esbuild/android-arm64@0.23.1': 240 | optional: true 241 | 242 | '@esbuild/android-arm@0.23.1': 243 | optional: true 244 | 245 | '@esbuild/android-x64@0.23.1': 246 | optional: true 247 | 248 | '@esbuild/darwin-arm64@0.23.1': 249 | optional: true 250 | 251 | '@esbuild/darwin-x64@0.23.1': 252 | optional: true 253 | 254 | '@esbuild/freebsd-arm64@0.23.1': 255 | optional: true 256 | 257 | '@esbuild/freebsd-x64@0.23.1': 258 | optional: true 259 | 260 | '@esbuild/linux-arm64@0.23.1': 261 | optional: true 262 | 263 | '@esbuild/linux-arm@0.23.1': 264 | optional: true 265 | 266 | '@esbuild/linux-ia32@0.23.1': 267 | optional: true 268 | 269 | '@esbuild/linux-loong64@0.23.1': 270 | optional: true 271 | 272 | '@esbuild/linux-mips64el@0.23.1': 273 | optional: true 274 | 275 | '@esbuild/linux-ppc64@0.23.1': 276 | optional: true 277 | 278 | '@esbuild/linux-riscv64@0.23.1': 279 | optional: true 280 | 281 | '@esbuild/linux-s390x@0.23.1': 282 | optional: true 283 | 284 | '@esbuild/linux-x64@0.23.1': 285 | optional: true 286 | 287 | '@esbuild/netbsd-x64@0.23.1': 288 | optional: true 289 | 290 | '@esbuild/openbsd-arm64@0.23.1': 291 | optional: true 292 | 293 | '@esbuild/openbsd-x64@0.23.1': 294 | optional: true 295 | 296 | '@esbuild/sunos-x64@0.23.1': 297 | optional: true 298 | 299 | '@esbuild/win32-arm64@0.23.1': 300 | optional: true 301 | 302 | '@esbuild/win32-ia32@0.23.1': 303 | optional: true 304 | 305 | '@esbuild/win32-x64@0.23.1': 306 | optional: true 307 | 308 | '@types/node@22.7.6': 309 | dependencies: 310 | undici-types: 6.19.8 311 | 312 | esbuild@0.23.1: 313 | optionalDependencies: 314 | '@esbuild/aix-ppc64': 0.23.1 315 | '@esbuild/android-arm': 0.23.1 316 | '@esbuild/android-arm64': 0.23.1 317 | '@esbuild/android-x64': 0.23.1 318 | '@esbuild/darwin-arm64': 0.23.1 319 | '@esbuild/darwin-x64': 0.23.1 320 | '@esbuild/freebsd-arm64': 0.23.1 321 | '@esbuild/freebsd-x64': 0.23.1 322 | '@esbuild/linux-arm': 0.23.1 323 | '@esbuild/linux-arm64': 0.23.1 324 | '@esbuild/linux-ia32': 0.23.1 325 | '@esbuild/linux-loong64': 0.23.1 326 | '@esbuild/linux-mips64el': 0.23.1 327 | '@esbuild/linux-ppc64': 0.23.1 328 | '@esbuild/linux-riscv64': 0.23.1 329 | '@esbuild/linux-s390x': 0.23.1 330 | '@esbuild/linux-x64': 0.23.1 331 | '@esbuild/netbsd-x64': 0.23.1 332 | '@esbuild/openbsd-arm64': 0.23.1 333 | '@esbuild/openbsd-x64': 0.23.1 334 | '@esbuild/sunos-x64': 0.23.1 335 | '@esbuild/win32-arm64': 0.23.1 336 | '@esbuild/win32-ia32': 0.23.1 337 | '@esbuild/win32-x64': 0.23.1 338 | 339 | fsevents@2.3.2: 340 | optional: true 341 | 342 | fsevents@2.3.3: 343 | optional: true 344 | 345 | get-tsconfig@4.8.1: 346 | dependencies: 347 | resolve-pkg-maps: 1.0.0 348 | 349 | meow@13.2.0: {} 350 | 351 | p-limit@6.1.0: 352 | dependencies: 353 | yocto-queue: 1.1.1 354 | 355 | playwright-core@1.47.0: {} 356 | 357 | playwright@1.47.0: 358 | dependencies: 359 | playwright-core: 1.47.0 360 | optionalDependencies: 361 | fsevents: 2.3.2 362 | 363 | resolve-pkg-maps@1.0.0: {} 364 | 365 | toml@3.0.0: {} 366 | 367 | tsx@4.19.1: 368 | dependencies: 369 | esbuild: 0.23.1 370 | get-tsconfig: 4.8.1 371 | optionalDependencies: 372 | fsevents: 2.3.3 373 | 374 | undici-types@6.19.8: {} 375 | 376 | yocto-queue@1.1.1: {} 377 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## Rust Books PDF 2 | 3 | Please find the latest version of the pdf in the [release tab](https://github.com/shirshak55/Rust-Book-In-PDF/releases/). Look at the Assets section and download the pdf from there. 4 | 5 | ### Contributing 6 | 7 | Feel free to send a pull request. We follow the Rust Code of Conduct. 8 | 9 | 10 | ### Development 11 | To run this project, please install Node JS V20 or above. You can use any package manager like npm, yarn, pnpm etc. 12 | 13 | ```bash 14 | git clone https://github.com/shirshak55/Rust-Book-In-PDF.git 15 | pnpm install 16 | pnpm start 17 | ``` 18 | 19 | This will run the project and download all the books in the config.toml file. You can also run `yarn start` with `DEBUG_ONLY_FRIST=true` to only download the first page of the book for easier debugging. 20 | 21 | ### Support us 22 | 23 | You can support us by starring the repo. As the book is written by other people, I can't take any financial support. 24 | 25 | ### Thanks, 26 | 27 | - Shirshak 28 | - TRPL team 29 | - Rustaceans 30 | - Contributors 31 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "strict": true, 5 | "module": "esnext", 6 | "moduleResolution": "node", 7 | "isolatedModules": true, 8 | "esModuleInterop": true, 9 | "inlineSourceMap": true, 10 | "skipLibCheck": true, 11 | "lib": ["esnext", "dom"], 12 | "outDir": "./dist", 13 | "rootDir": "./src" 14 | }, 15 | "exclude": ["node_modules"], 16 | "files": ["main.ts"] 17 | } 18 | --------------------------------------------------------------------------------