├── sample-ts-use ├── .gitignore ├── index.ts ├── package.json ├── package-lock.json └── tsconfig.json ├── .prettierignore ├── .gitignore ├── tsconfig.eslint.json ├── justfile ├── .github ├── dependabot.yml └── workflows │ ├── sample-use.yml │ └── tests.yml ├── sample-cjs-use ├── package.json ├── index.js └── package-lock.json ├── sample-esm-use ├── package.json ├── index.js └── package-lock.json ├── example.mjs ├── LICENSE ├── test ├── end-to-end.ts ├── unit.ts └── fixtures │ ├── automated-content-page.html │ └── verifying-your-email-address.html ├── README.md ├── tsconfig.json ├── package.json ├── src └── index.ts └── eslint.config.mjs /sample-ts-use/.gitignore: -------------------------------------------------------------------------------- 1 | index.js 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | sample-ts-use/tsconfig.json 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | node_modules/ 3 | coverage/ 4 | lib/ 5 | junit.xml 6 | .nvmrc 7 | -------------------------------------------------------------------------------- /tsconfig.eslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["src", "test"], 4 | "exclude": [] 5 | } 6 | -------------------------------------------------------------------------------- /justfile: -------------------------------------------------------------------------------- 1 | # https://github.com/casey/just 2 | # https://just.systems/ 3 | 4 | install: 5 | npm install 6 | 7 | format: 8 | npm run format 9 | 10 | lint: 11 | npm run lint 12 | 13 | upgrade: 14 | npx npm-check-updates --interactive 15 | 16 | outdated: 17 | npm outdated 18 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" 5 | schedule: 6 | interval: monthly 7 | open-pull-requests-limit: 10 # default is 5 8 | - package-ecosystem: "github-actions" 9 | directory: "/" 10 | schedule: 11 | interval: monthly 12 | -------------------------------------------------------------------------------- /sample-cjs-use/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-cjs-use", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "node index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cheerio": "1.0.0-rc.12", 14 | "cheerio-to-text": "file:.." 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sample-esm-use/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-esm-use", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "node index.js" 9 | }, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "dependencies": { 14 | "cheerio": "1.0.0-rc.12", 15 | "cheerio-to-text": "file:.." 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /sample-esm-use/index.js: -------------------------------------------------------------------------------- 1 | import cheerio from "cheerio" 2 | import { render } from "cheerio-to-text" 3 | 4 | const HTML = ` 5 | 6 | 7 |
8 |

Paragraph.

9 |

Heading

10 |
11 | 12 | `.trim() 13 | 14 | const $ = cheerio.load(HTML) 15 | console.assert(render($("#main")).includes("Paragraph.")) 16 | -------------------------------------------------------------------------------- /sample-ts-use/index.ts: -------------------------------------------------------------------------------- 1 | import cheerio from "cheerio" 2 | import { render } from "cheerio-to-text" 3 | 4 | const HTML = ` 5 | 6 | 7 |
8 |

Paragraph.

9 |

Heading

10 |
11 | 12 | `.trim() 13 | 14 | const $ = cheerio.load(HTML) 15 | console.assert(render($("#main")).includes("Paragraph.")) 16 | -------------------------------------------------------------------------------- /sample-cjs-use/index.js: -------------------------------------------------------------------------------- 1 | const cheerio = require("cheerio") 2 | const { render } = require("cheerio-to-text") 3 | 4 | const HTML = ` 5 | 6 | 7 |
8 |

Paragraph.

9 |

Heading

10 |
11 | 12 | `.trim() 13 | 14 | const $ = cheerio.load(HTML) 15 | console.assert(render($("#main")).includes("Paragraph.")) 16 | -------------------------------------------------------------------------------- /sample-ts-use/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-ts-use", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "tsc index.ts && node index.js" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "cheerio": "1.0.0-rc.12", 14 | "cheerio-to-text": "file:.." 15 | }, 16 | "devDependencies": { 17 | "typescript": "5.2.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example.mjs: -------------------------------------------------------------------------------- 1 | import cheerio from "cheerio" 2 | import { render } from "./lib/index.js" 3 | 4 | main() 5 | function main() { 6 | const html = ` 7 | 8 | 9 | Example 10 | 11 | 12 | 13 |

Header

14 | 15 |
16 | Sample text 17 |
18 |
19 |

Sample text

20 |
21 | 22 |

Stuff bold

23 |
Code

Paragrap

Stuff

24 | 25 | 26 | 27 | ` 28 | // console.log(render(html)); 29 | // console.log(render(cheerio.load(html).root())); 30 | // console.log(render(cheerio.load(html).root()[0])); 31 | var text = render(cheerio.load(html)("body")[0]) 32 | console.log({ text }) 33 | } 34 | -------------------------------------------------------------------------------- /.github/workflows/sample-use.yml: -------------------------------------------------------------------------------- 1 | name: Sample use 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | merge_group: 9 | 10 | jobs: 11 | use: 12 | name: Use in ${{ matrix.dir }} 13 | runs-on: ubuntu-latest 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | dir: 18 | - "sample-cjs-use" 19 | - "sample-esm-use" 20 | - "sample-ts-use" 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Use Node.js 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: 24 28 | cache: npm 29 | - name: Install for self 30 | run: npm ci 31 | - name: Build 32 | run: npm run build 33 | 34 | - name: Install 35 | working-directory: ${{ matrix.dir }} 36 | run: npm install 37 | - name: Run 38 | working-directory: ${{ matrix.dir }} 39 | run: npm run test 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2022 Peter Bengtsson 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | merge_group: 9 | 10 | env: 11 | FORCE_COLOR: 2 12 | 13 | jobs: 14 | lint: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - uses: actions/setup-node@v4 19 | with: 20 | node-version: 24 21 | cache: npm 22 | - run: npm ci 23 | - run: npm run lint 24 | 25 | tests: 26 | name: Node ${{ matrix.node }} 27 | runs-on: ubuntu-latest 28 | 29 | strategy: 30 | fail-fast: false 31 | matrix: 32 | node: 33 | - 20 34 | - 22 35 | - 24 36 | 37 | steps: 38 | - uses: actions/checkout@v4 39 | - name: Use Node.js ${{ matrix.node }} 40 | uses: actions/setup-node@v4 41 | with: 42 | node-version: ${{ matrix.node }} 43 | cache: npm 44 | - run: npm ci 45 | - run: npm run build --if-present 46 | 47 | - name: Run tests (${{ matrix.node }}) 48 | run: npm run test:test 49 | -------------------------------------------------------------------------------- /test/end-to-end.ts: -------------------------------------------------------------------------------- 1 | import assert from "node:assert" 2 | import { describe, it } from "node:test" 3 | import fs from "fs" 4 | import path from "path" 5 | 6 | import { render } from "../src" 7 | 8 | describe("End-to-ends", () => { 9 | const rt = "test/fixtures" 10 | const fixtures = fs 11 | .readdirSync(rt) 12 | .map((name) => path.join(rt, name)) 13 | .filter((x) => x.endsWith(".html")) 14 | 15 | for (const fixture of fixtures) { 16 | it(`should cope with <${path.basename(fixture)}>`, () => { 17 | const html = fs.readFileSync(fixture, "utf-8") 18 | const text = render(html) 19 | assert(text.length > 1_000) 20 | if (path.basename(fixture) === "code-security-guides.html") { 21 | // Highlight a few specific examples which have caused bugs before. 22 | assert(/Show 3 more guides/.test(text)) 23 | assert(!/Show 3more guides/.test(text)) 24 | assert(/ities are reported\.\nStart learning path/.test(text)) 25 | } 26 | }) 27 | } 28 | }) 29 | 30 | describe("spot check some large fixtures", () => { 31 | it("should not lump certain words together", () => { 32 | const html = fs.readFileSync( 33 | "test/fixtures/_en_actions_using-workflows_workflow-syntax-for-github-actions.html", 34 | "utf-8", 35 | ) 36 | const text = render(html) 37 | assert(/irectory of your repository.\nname/.test(text)) 38 | assert(/github and inputs contexts.\nExample\nrun-name/.test(text)) 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cheerio-to-text 2 | 3 | Explained by an example: 4 | 5 | ```js 6 | import fs from "fs" 7 | import cheerio from "cheerio" 8 | import { render } from "cheerio-to-text" 9 | 10 | const html = fs.readFileSync("page.html", "utf-8") 11 | console.log(html) 12 | // 13 | // 14 | // 15 | //
16 | //

Paragraph.

17 | //

Heading

18 | //
19 | // 20 | // 21 | 22 | const $ = cheerio.load(html) 23 | console.log($("div#main").text()) 24 | // 25 | // Paragraph. 26 | // FooBarHeading 27 | // 28 | 29 | console.log(render($("div#main"))) 30 | // 31 | // Paragraph. 32 | // Foo 33 | // Bar 34 | // Heading 35 | // 36 | ``` 37 | 38 | Much of the origin of this that [GitHub Docs](https://docs.github.com) scrapes 39 | every page with `got` and `cheerio` and then needs to convert that into an 40 | appropriate string of plain text that it can use for searching 41 | with Elasticsearch. Using `myCheerioObject.text()` isn't good enough 42 | because it lumps together HTML blocking tags that have no whitespace 43 | between the `>` and the next `<`. 44 | 45 | ## License 46 | 47 | MIT 48 | 49 | ## How to hack 50 | 51 | Run `npm run build:watch` in one terminal the look at 52 | `example.mjs` (which you run with `node example.mjs`) 53 | 54 | ## How to run tests 55 | 56 | ```sh 57 | npm run test:test 58 | ``` 59 | 60 | Or 61 | 62 | ```sh 63 | npm run test:test -- --watch 64 | ``` 65 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */, 5 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */, 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | "declaration": true /* Generates corresponding '.d.ts' file. */, 8 | "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */, 9 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 10 | "outDir": "lib" /* Redirect output structure to the directory. */, 11 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 12 | 13 | "downlevelIteration": true, 14 | 15 | /* Strict Type-Checking Options */ 16 | "strict": true /* Enable all strict type-checking options. */, 17 | 18 | /* Additional Checks */ 19 | "noUnusedLocals": true /* Report errors on unused locals. */, 20 | // "noUnusedLocals": false /* TEMP. */, 21 | "noUnusedParameters": true /* Report errors on unused parameters. */, 22 | // "noUnusedParameters": false /* TEMP */, 23 | "noImplicitReturns": true /* Report error when not all code paths in function return a value. */, 24 | "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */, 25 | 26 | /* Module Resolution Options */ 27 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 28 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, 29 | "moduleResolution": "node" 30 | }, 31 | "include": ["src"], 32 | "exclude": [ 33 | "**/*.spec.ts", 34 | "**/__fixtures__/*", 35 | "**/__tests__/*", 36 | "**/__snapshots__/*" 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cheerio-to-text", 3 | "version": "0.2.5", 4 | "description": "Turn a Cheerio object into plain text", 5 | "repository": { 6 | "type": "git", 7 | "url": "git://github.com/peterbe/cheerio-to-text.git" 8 | }, 9 | "bugs": { 10 | "url": "https://github.com/peterbe/cheerio-to-text/issues" 11 | }, 12 | "main": "lib/index.js", 13 | "types": "lib/index.d.ts", 14 | "module": "lib/esm/index.js", 15 | "files": [ 16 | "lib" 17 | ], 18 | "exports": { 19 | "require": "./lib/index.js", 20 | "import": "./lib/esm/index.js" 21 | }, 22 | "scripts": { 23 | "test": "npm run test:test && npm run lint", 24 | "test:test": "node --import tsx --test test/*.ts", 25 | "lint": "npm run lint:es && npm run lint:prettier", 26 | "lint:es": "eslint src", 27 | "lint:prettier": "npm run prettier -- --check", 28 | "format": "npm run format:es && npm run format:prettier", 29 | "format:es": "npm run lint:es -- --fix", 30 | "format:prettier": "npm run prettier -- --write", 31 | "prettier": "prettier '**/*.{ts,md,json,yml,mjs}'", 32 | "build:watch": "tsc --watch", 33 | "build": "npm run build:cjs && npm run build:esm", 34 | "build:cjs": "tsc", 35 | "build:esm": "npm run build:cjs -- --module esnext --target es2019 --outDir lib/esm && echo '{\"type\":\"module\"}' > lib/esm/package.json", 36 | "prepare": "npm run build", 37 | "release": "npm run prepare && np" 38 | }, 39 | "keywords": [ 40 | "cheerio", 41 | "html", 42 | "text" 43 | ], 44 | "author": "Peter Bengtsson", 45 | "license": "MIT", 46 | "devDependencies": { 47 | "@types/node": "24.10.1", 48 | "@typescript-eslint/eslint-plugin": "8.49.0", 49 | "@typescript-eslint/parser": "8.49.0", 50 | "eslint": "9.39.1", 51 | "eslint-config-prettier": "10.1.8", 52 | "np": "10.2.0", 53 | "prettier": "3.7.4", 54 | "tsx": "4.21.0", 55 | "typescript": "5.9.3" 56 | }, 57 | "peerDependencies": { 58 | "cheerio": "1.0.0-rc.12" 59 | }, 60 | "prettier": { 61 | "semi": false 62 | }, 63 | "engines": { 64 | "node": ">=18" 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import type { Element, CheerioAPI, Document, AnyNode, Cheerio } from "cheerio" 2 | import cheerio from "cheerio" 3 | 4 | const inlineElements = new Set( 5 | `a,abbr,acronym,audio,b,bdi,bdo,big,br,button,canvas,cite,code,data, 6 | datalist,del,dfn,em,embed,i,iframe,img,input,ins,kbd,label,map,mark, 7 | meter,noscript,object,output,picture,progress,q,ruby,s,samp,script, 8 | select,slot,small,span,strong,sub,sup,svg,template,textarea,time, 9 | tt,u,var,video,wbr` 10 | .split(",") 11 | .map((s) => s.trim()), 12 | ) 13 | const isBlockTag = (tagName: string) => !inlineElements.has(tagName) 14 | 15 | export function render( 16 | node: CheerioAPI | Document | string | Element | Cheerio, 17 | ): string { 18 | let root: Document | Element | null = null 19 | if (typeof node === "string") { 20 | root = cheerio.load(node)("body")[0] 21 | } else if (typeof node === "object" && "0" in node) { 22 | root = node[0] 23 | } else if (typeof node === "object" && "children" in node && "type" in node) { 24 | root = node 25 | } 26 | 27 | if (!root) { 28 | throw new Error( 29 | "node was not a string, cheerio loaded document, or a cheerio node", 30 | ) 31 | } 32 | 33 | let text = "" 34 | 35 | function enter(element: AnyNode) { 36 | if (element.type === "text") { 37 | text += element.data 38 | } 39 | } 40 | 41 | function leave(element: AnyNode) { 42 | if (element.type === "tag") { 43 | // console.log({ LEAVING: element.type, tagName: element.tagName }) 44 | if (isBlockTag(element.tagName)) { 45 | text += "\n" 46 | } 47 | } 48 | } 49 | 50 | walk(root, enter, leave) 51 | 52 | return text 53 | .trim() 54 | .split(/\n+/g) 55 | .map((line) => line.trim()) 56 | .filter(Boolean) 57 | .join("\n") 58 | } 59 | 60 | function walk( 61 | root: AnyNode, 62 | enter: (element: AnyNode) => void, 63 | leave: (element: AnyNode) => void, 64 | ) { 65 | enter(root) 66 | if (root.type === "tag") { 67 | for (const child of root.children) { 68 | walk(child, enter, leave) 69 | } 70 | } 71 | leave(root) 72 | } 73 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "eslint/config" 2 | import globals from "globals" 3 | import path from "node:path" 4 | import { fileURLToPath } from "node:url" 5 | import js from "@eslint/js" 6 | import { FlatCompat } from "@eslint/eslintrc" 7 | 8 | const __filename = fileURLToPath(import.meta.url) 9 | const __dirname = path.dirname(__filename) 10 | const compat = new FlatCompat({ 11 | baseDirectory: __dirname, 12 | recommendedConfig: js.configs.recommended, 13 | allConfig: js.configs.all, 14 | }) 15 | 16 | export default defineConfig([ 17 | { 18 | extends: compat.extends("eslint:recommended", "prettier"), 19 | 20 | languageOptions: { 21 | globals: { 22 | ...globals.node, 23 | }, 24 | }, 25 | 26 | rules: { 27 | eqeqeq: [2, "smart"], 28 | "no-caller": 2, 29 | "dot-notation": 2, 30 | "no-var": 2, 31 | "prefer-const": 2, 32 | 33 | "prefer-arrow-callback": [ 34 | 2, 35 | { 36 | allowNamedFunctions: true, 37 | }, 38 | ], 39 | 40 | "arrow-body-style": [2, "as-needed"], 41 | "object-shorthand": 2, 42 | "prefer-template": 2, 43 | "one-var": [2, "never"], 44 | 45 | "prefer-destructuring": [ 46 | 2, 47 | { 48 | object: true, 49 | }, 50 | ], 51 | 52 | "spaced-comment": 2, 53 | yoda: [2, "never"], 54 | curly: [2, "multi-line"], 55 | "no-else-return": 2, 56 | }, 57 | }, 58 | { 59 | files: ["**/*.ts"], 60 | 61 | extends: compat.extends( 62 | "plugin:@typescript-eslint/eslint-recommended", 63 | "plugin:@typescript-eslint/recommended", 64 | "prettier", 65 | ), 66 | 67 | languageOptions: { 68 | ecmaVersion: 5, 69 | sourceType: "module", 70 | 71 | parserOptions: { 72 | project: "./tsconfig.eslint.json", 73 | }, 74 | }, 75 | 76 | rules: { 77 | "@typescript-eslint/prefer-for-of": 0, 78 | "@typescript-eslint/member-ordering": 0, 79 | "@typescript-eslint/explicit-function-return-type": 0, 80 | "@typescript-eslint/no-unused-vars": 0, 81 | 82 | "@typescript-eslint/no-use-before-define": [ 83 | 2, 84 | { 85 | functions: false, 86 | }, 87 | ], 88 | 89 | "@typescript-eslint/consistent-type-definitions": [2, "interface"], 90 | "@typescript-eslint/prefer-function-type": 2, 91 | "@typescript-eslint/no-unnecessary-type-arguments": 2, 92 | "@typescript-eslint/prefer-string-starts-ends-with": 2, 93 | "@typescript-eslint/prefer-readonly": 2, 94 | "@typescript-eslint/prefer-includes": 2, 95 | "@typescript-eslint/no-unnecessary-condition": 2, 96 | "@typescript-eslint/switch-exhaustiveness-check": 2, 97 | "@typescript-eslint/prefer-nullish-coalescing": 2, 98 | }, 99 | }, 100 | ]) 101 | -------------------------------------------------------------------------------- /test/unit.ts: -------------------------------------------------------------------------------- 1 | import assert from "node:assert" 2 | import { describe, it } from "node:test" 3 | 4 | import cheerio from "cheerio" 5 | 6 | import { render } from "../src" 7 | 8 | describe("Unit tests", () => { 9 | const TEMPLATE = ` 10 | 11 | 12 | BODY 13 | 14 | 15 | ` 16 | 17 | it("should keep inlines together", () => { 18 | const html = TEMPLATE.replace( 19 | "BODY", 20 | ` 21 |

Paragraph.

22 | `, 23 | ) 24 | const text = render(html) 25 | assert(/Paragraph\./.test(text)) 26 | assert(text === text.trim()) 27 | }) 28 | 29 | it("should be possible to send in a cheerio object", () => { 30 | const html = TEMPLATE.replace( 31 | "BODY", 32 | ` 33 |

Paragraph.

34 | `, 35 | ) 36 | const $ = cheerio.load(html) 37 | const text = render($("body")) 38 | assert(/Paragraph\./.test(text)) 39 | }) 40 | 41 | it("should be possible to send in a cheerio element", () => { 42 | const html = TEMPLATE.replace( 43 | "BODY", 44 | ` 45 |

Paragraph.

46 | `, 47 | ) 48 | const $ = cheerio.load(html) 49 | const text = render($("body")[0]) 50 | assert(/Paragraph\./.test(text)) 51 | }) 52 | 53 | it("should keep block elements apart", () => { 54 | const html = TEMPLATE.replace( 55 | "BODY", 56 | ` 57 |

Foo

Bar.

58 | `, 59 | ) 60 | const text = render(html) 61 | assert(/Foo\nBar\./.test(text)) 62 | }) 63 | 64 | it("should keep block elements apart even if they're already apart", () => { 65 | const html = TEMPLATE.replace( 66 | "BODY", 67 | ` 68 |

Foo

69 | 70 | 71 | 72 |

Bar.

73 | `, 74 | ) 75 | const text = render(html) 76 | assert(/Foo\nBar\./.test(text)) 77 | }) 78 | 79 | it("should respect newlines inside pre blocks", () => { 80 | const html = TEMPLATE.replace( 81 | "BODY", 82 | ` 83 |
 84 |         one
 85 |         two
 86 |         three
 87 |         
88 | `, 89 | ) 90 | const text = render(html) 91 | assert(/one\ntwo\nthree/.test(text)) 92 | }) 93 | 94 | it("should separate a h1 from a following span", () => { 95 | const html = TEMPLATE.replace( 96 | "BODY", 97 | ` 98 |

Heading

Text 99 | `, 100 | ) 101 | const text = render(html) 102 | assert(/Heading\nText/.test(text)) 103 | }) 104 | 105 | it("should separate a h2 followed by two inlines", () => { 106 | const html = TEMPLATE.replace( 107 | "BODY", 108 | ` 109 |

Heading

ItalicStrong 110 | `, 111 | ) 112 | const text = render(html) 113 | assert(/Heading\nItalicStrong/.test(text)) 114 | }) 115 | 116 | it("should work with the example code in the README", () => { 117 | const html = TEMPLATE.replace( 118 | "BODY", 119 | ` 120 |

Paragraph.

121 |

Heading

122 | `, 123 | ) 124 | const text = render(html) 125 | assert(text === "Paragraph.\nFoo\nBar\nHeading") 126 | }) 127 | 128 | it("should respect whitespace between two inline tags", () => { 129 | const html = TEMPLATE.replace( 130 | "BODY", 131 | `
accept string
`, 132 | ) 133 | const text = render(html) 134 | assert(text === "accept string") 135 | }) 136 | 137 | it("should not add whitespace between two inline tags next to each other", () => { 138 | const html = TEMPLATE.replace( 139 | "BODY", 140 | `
acceptstring
`, 141 | ) 142 | const text = render(html) 143 | assert(text === "acceptstring") 144 | }) 145 | }) 146 | -------------------------------------------------------------------------------- /test/fixtures/automated-content-page.html: -------------------------------------------------------------------------------- 1 |
2 | 7 |
8 | 9 |

I am the page title

10 | 11 |
12 |

This is an introduction to the article.

13 |
14 | 15 |
16 |

Heading

17 | 18 | 20 |
21 |
22 |

23 | AuditEntry 24 |

25 |

An entry in the audit log.

26 |
27 |
28 |

Implemented by

29 | 33 |

Fields

34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 49 | 50 | 51 | 53 | 54 | 55 | 57 | 58 | 59 | 61 | 62 | 63 | 65 | 66 | 67 | 69 | 70 | 71 | 73 | 74 | 75 | 77 | 78 | 79 | 81 | 82 | 83 | 85 | 86 | 87 | 89 | 90 | 91 | 93 | 94 |
NameDescription

action (String!)

The action name.

44 |

actor (AuditEntryActor)

The user who initiated the action.

48 |

actorIp (String)

The IP address of the actor.

52 |

actorLocation (ActorLocation)

A readable representation of the actor's location.

56 |

actorLogin (String)

The username of the user who initiated the action.

60 |

actorResourcePath (URI)

The HTTP path for the actor.

64 |

actorUrl (URI)

The HTTP URL for the actor.

68 |

createdAt (PreciseDateTime!)

The time the action was initiated.

72 |

operationType (OperationType)

The corresponding operation type for the action.

76 |

user (User)

The user affected by the action.

80 |

userLogin (String)

For actions involving two users, the actor is the initiator and the user is the affected user.

84 |

userResourcePath (URI)

The HTTP path for the user.

88 |

userUrl (URI)

The HTTP URL for the user.

92 |
95 |
96 |
97 |
98 | 99 |
-------------------------------------------------------------------------------- /sample-cjs-use/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-cjs-use", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sample-cjs-use", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cheerio": "1.0.0-rc.12", 13 | "cheerio-to-text": "file:.." 14 | } 15 | }, 16 | "..": { 17 | "version": "0.2.4", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "@types/node": "20.8.10", 21 | "@typescript-eslint/eslint-plugin": "6.9.1", 22 | "@typescript-eslint/parser": "6.9.1", 23 | "eslint": "8.52.0", 24 | "eslint-config-prettier": "9.0.0", 25 | "np": "8.0.4", 26 | "prettier": "3.0.3", 27 | "tsx": "3.14.0", 28 | "typescript": "5.2.2" 29 | }, 30 | "engines": { 31 | "node": ">=18" 32 | }, 33 | "peerDependencies": { 34 | "cheerio": "1.0.0-rc.12" 35 | } 36 | }, 37 | "node_modules/boolbase": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 40 | "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" 41 | }, 42 | "node_modules/cheerio": { 43 | "version": "1.0.0-rc.12", 44 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", 45 | "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", 46 | "dependencies": { 47 | "cheerio-select": "^2.1.0", 48 | "dom-serializer": "^2.0.0", 49 | "domhandler": "^5.0.3", 50 | "domutils": "^3.0.1", 51 | "htmlparser2": "^8.0.1", 52 | "parse5": "^7.0.0", 53 | "parse5-htmlparser2-tree-adapter": "^7.0.0" 54 | }, 55 | "engines": { 56 | "node": ">= 6" 57 | }, 58 | "funding": { 59 | "url": "https://github.com/cheeriojs/cheerio?sponsor=1" 60 | } 61 | }, 62 | "node_modules/cheerio-select": { 63 | "version": "2.1.0", 64 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", 65 | "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", 66 | "dependencies": { 67 | "boolbase": "^1.0.0", 68 | "css-select": "^5.1.0", 69 | "css-what": "^6.1.0", 70 | "domelementtype": "^2.3.0", 71 | "domhandler": "^5.0.3", 72 | "domutils": "^3.0.1" 73 | }, 74 | "funding": { 75 | "url": "https://github.com/sponsors/fb55" 76 | } 77 | }, 78 | "node_modules/cheerio-to-text": { 79 | "resolved": "..", 80 | "link": true 81 | }, 82 | "node_modules/css-select": { 83 | "version": "5.1.0", 84 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", 85 | "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", 86 | "dependencies": { 87 | "boolbase": "^1.0.0", 88 | "css-what": "^6.1.0", 89 | "domhandler": "^5.0.2", 90 | "domutils": "^3.0.1", 91 | "nth-check": "^2.0.1" 92 | }, 93 | "funding": { 94 | "url": "https://github.com/sponsors/fb55" 95 | } 96 | }, 97 | "node_modules/css-what": { 98 | "version": "6.1.0", 99 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", 100 | "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", 101 | "engines": { 102 | "node": ">= 6" 103 | }, 104 | "funding": { 105 | "url": "https://github.com/sponsors/fb55" 106 | } 107 | }, 108 | "node_modules/dom-serializer": { 109 | "version": "2.0.0", 110 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 111 | "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 112 | "dependencies": { 113 | "domelementtype": "^2.3.0", 114 | "domhandler": "^5.0.2", 115 | "entities": "^4.2.0" 116 | }, 117 | "funding": { 118 | "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" 119 | } 120 | }, 121 | "node_modules/domelementtype": { 122 | "version": "2.3.0", 123 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 124 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", 125 | "funding": [ 126 | { 127 | "type": "github", 128 | "url": "https://github.com/sponsors/fb55" 129 | } 130 | ] 131 | }, 132 | "node_modules/domhandler": { 133 | "version": "5.0.3", 134 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 135 | "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 136 | "dependencies": { 137 | "domelementtype": "^2.3.0" 138 | }, 139 | "engines": { 140 | "node": ">= 4" 141 | }, 142 | "funding": { 143 | "url": "https://github.com/fb55/domhandler?sponsor=1" 144 | } 145 | }, 146 | "node_modules/domutils": { 147 | "version": "3.1.0", 148 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", 149 | "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", 150 | "dependencies": { 151 | "dom-serializer": "^2.0.0", 152 | "domelementtype": "^2.3.0", 153 | "domhandler": "^5.0.3" 154 | }, 155 | "funding": { 156 | "url": "https://github.com/fb55/domutils?sponsor=1" 157 | } 158 | }, 159 | "node_modules/entities": { 160 | "version": "4.5.0", 161 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 162 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 163 | "engines": { 164 | "node": ">=0.12" 165 | }, 166 | "funding": { 167 | "url": "https://github.com/fb55/entities?sponsor=1" 168 | } 169 | }, 170 | "node_modules/htmlparser2": { 171 | "version": "8.0.2", 172 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", 173 | "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", 174 | "funding": [ 175 | "https://github.com/fb55/htmlparser2?sponsor=1", 176 | { 177 | "type": "github", 178 | "url": "https://github.com/sponsors/fb55" 179 | } 180 | ], 181 | "dependencies": { 182 | "domelementtype": "^2.3.0", 183 | "domhandler": "^5.0.3", 184 | "domutils": "^3.0.1", 185 | "entities": "^4.4.0" 186 | } 187 | }, 188 | "node_modules/nth-check": { 189 | "version": "2.1.1", 190 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 191 | "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 192 | "dependencies": { 193 | "boolbase": "^1.0.0" 194 | }, 195 | "funding": { 196 | "url": "https://github.com/fb55/nth-check?sponsor=1" 197 | } 198 | }, 199 | "node_modules/parse5": { 200 | "version": "7.1.2", 201 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", 202 | "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", 203 | "dependencies": { 204 | "entities": "^4.4.0" 205 | }, 206 | "funding": { 207 | "url": "https://github.com/inikulin/parse5?sponsor=1" 208 | } 209 | }, 210 | "node_modules/parse5-htmlparser2-tree-adapter": { 211 | "version": "7.0.0", 212 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", 213 | "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", 214 | "dependencies": { 215 | "domhandler": "^5.0.2", 216 | "parse5": "^7.0.0" 217 | }, 218 | "funding": { 219 | "url": "https://github.com/inikulin/parse5?sponsor=1" 220 | } 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /sample-esm-use/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-esm-use", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sample-esm-use", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cheerio": "1.0.0-rc.12", 13 | "cheerio-to-text": "file:.." 14 | } 15 | }, 16 | "..": { 17 | "version": "0.2.4", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "@types/node": "20.8.10", 21 | "@typescript-eslint/eslint-plugin": "6.9.1", 22 | "@typescript-eslint/parser": "6.9.1", 23 | "eslint": "8.52.0", 24 | "eslint-config-prettier": "9.0.0", 25 | "np": "8.0.4", 26 | "prettier": "3.0.3", 27 | "tsx": "3.14.0", 28 | "typescript": "5.2.2" 29 | }, 30 | "engines": { 31 | "node": ">=18" 32 | }, 33 | "peerDependencies": { 34 | "cheerio": "1.0.0-rc.12" 35 | } 36 | }, 37 | "node_modules/boolbase": { 38 | "version": "1.0.0", 39 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 40 | "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" 41 | }, 42 | "node_modules/cheerio": { 43 | "version": "1.0.0-rc.12", 44 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", 45 | "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", 46 | "dependencies": { 47 | "cheerio-select": "^2.1.0", 48 | "dom-serializer": "^2.0.0", 49 | "domhandler": "^5.0.3", 50 | "domutils": "^3.0.1", 51 | "htmlparser2": "^8.0.1", 52 | "parse5": "^7.0.0", 53 | "parse5-htmlparser2-tree-adapter": "^7.0.0" 54 | }, 55 | "engines": { 56 | "node": ">= 6" 57 | }, 58 | "funding": { 59 | "url": "https://github.com/cheeriojs/cheerio?sponsor=1" 60 | } 61 | }, 62 | "node_modules/cheerio-select": { 63 | "version": "2.1.0", 64 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", 65 | "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", 66 | "dependencies": { 67 | "boolbase": "^1.0.0", 68 | "css-select": "^5.1.0", 69 | "css-what": "^6.1.0", 70 | "domelementtype": "^2.3.0", 71 | "domhandler": "^5.0.3", 72 | "domutils": "^3.0.1" 73 | }, 74 | "funding": { 75 | "url": "https://github.com/sponsors/fb55" 76 | } 77 | }, 78 | "node_modules/cheerio-to-text": { 79 | "resolved": "..", 80 | "link": true 81 | }, 82 | "node_modules/css-select": { 83 | "version": "5.1.0", 84 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", 85 | "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", 86 | "dependencies": { 87 | "boolbase": "^1.0.0", 88 | "css-what": "^6.1.0", 89 | "domhandler": "^5.0.2", 90 | "domutils": "^3.0.1", 91 | "nth-check": "^2.0.1" 92 | }, 93 | "funding": { 94 | "url": "https://github.com/sponsors/fb55" 95 | } 96 | }, 97 | "node_modules/css-what": { 98 | "version": "6.1.0", 99 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", 100 | "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", 101 | "engines": { 102 | "node": ">= 6" 103 | }, 104 | "funding": { 105 | "url": "https://github.com/sponsors/fb55" 106 | } 107 | }, 108 | "node_modules/dom-serializer": { 109 | "version": "2.0.0", 110 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 111 | "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 112 | "dependencies": { 113 | "domelementtype": "^2.3.0", 114 | "domhandler": "^5.0.2", 115 | "entities": "^4.2.0" 116 | }, 117 | "funding": { 118 | "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" 119 | } 120 | }, 121 | "node_modules/domelementtype": { 122 | "version": "2.3.0", 123 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 124 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", 125 | "funding": [ 126 | { 127 | "type": "github", 128 | "url": "https://github.com/sponsors/fb55" 129 | } 130 | ] 131 | }, 132 | "node_modules/domhandler": { 133 | "version": "5.0.3", 134 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 135 | "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 136 | "dependencies": { 137 | "domelementtype": "^2.3.0" 138 | }, 139 | "engines": { 140 | "node": ">= 4" 141 | }, 142 | "funding": { 143 | "url": "https://github.com/fb55/domhandler?sponsor=1" 144 | } 145 | }, 146 | "node_modules/domutils": { 147 | "version": "3.1.0", 148 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", 149 | "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", 150 | "dependencies": { 151 | "dom-serializer": "^2.0.0", 152 | "domelementtype": "^2.3.0", 153 | "domhandler": "^5.0.3" 154 | }, 155 | "funding": { 156 | "url": "https://github.com/fb55/domutils?sponsor=1" 157 | } 158 | }, 159 | "node_modules/entities": { 160 | "version": "4.5.0", 161 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 162 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 163 | "engines": { 164 | "node": ">=0.12" 165 | }, 166 | "funding": { 167 | "url": "https://github.com/fb55/entities?sponsor=1" 168 | } 169 | }, 170 | "node_modules/htmlparser2": { 171 | "version": "8.0.2", 172 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", 173 | "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", 174 | "funding": [ 175 | "https://github.com/fb55/htmlparser2?sponsor=1", 176 | { 177 | "type": "github", 178 | "url": "https://github.com/sponsors/fb55" 179 | } 180 | ], 181 | "dependencies": { 182 | "domelementtype": "^2.3.0", 183 | "domhandler": "^5.0.3", 184 | "domutils": "^3.0.1", 185 | "entities": "^4.4.0" 186 | } 187 | }, 188 | "node_modules/nth-check": { 189 | "version": "2.1.1", 190 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 191 | "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 192 | "dependencies": { 193 | "boolbase": "^1.0.0" 194 | }, 195 | "funding": { 196 | "url": "https://github.com/fb55/nth-check?sponsor=1" 197 | } 198 | }, 199 | "node_modules/parse5": { 200 | "version": "7.1.2", 201 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", 202 | "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", 203 | "dependencies": { 204 | "entities": "^4.4.0" 205 | }, 206 | "funding": { 207 | "url": "https://github.com/inikulin/parse5?sponsor=1" 208 | } 209 | }, 210 | "node_modules/parse5-htmlparser2-tree-adapter": { 211 | "version": "7.0.0", 212 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", 213 | "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", 214 | "dependencies": { 215 | "domhandler": "^5.0.2", 216 | "parse5": "^7.0.0" 217 | }, 218 | "funding": { 219 | "url": "https://github.com/inikulin/parse5?sponsor=1" 220 | } 221 | } 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /sample-ts-use/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-ts-use", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sample-ts-use", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cheerio": "1.0.0-rc.12", 13 | "cheerio-to-text": "file:.." 14 | }, 15 | "devDependencies": { 16 | "typescript": "5.2.2" 17 | } 18 | }, 19 | "..": { 20 | "version": "0.2.4", 21 | "license": "MIT", 22 | "devDependencies": { 23 | "@types/node": "20.8.10", 24 | "@typescript-eslint/eslint-plugin": "6.9.1", 25 | "@typescript-eslint/parser": "6.9.1", 26 | "eslint": "8.52.0", 27 | "eslint-config-prettier": "9.0.0", 28 | "np": "8.0.4", 29 | "prettier": "3.0.3", 30 | "tsx": "3.14.0", 31 | "typescript": "5.2.2" 32 | }, 33 | "engines": { 34 | "node": ">=18" 35 | }, 36 | "peerDependencies": { 37 | "cheerio": "1.0.0-rc.12" 38 | } 39 | }, 40 | "node_modules/boolbase": { 41 | "version": "1.0.0", 42 | "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", 43 | "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" 44 | }, 45 | "node_modules/cheerio": { 46 | "version": "1.0.0-rc.12", 47 | "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", 48 | "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", 49 | "dependencies": { 50 | "cheerio-select": "^2.1.0", 51 | "dom-serializer": "^2.0.0", 52 | "domhandler": "^5.0.3", 53 | "domutils": "^3.0.1", 54 | "htmlparser2": "^8.0.1", 55 | "parse5": "^7.0.0", 56 | "parse5-htmlparser2-tree-adapter": "^7.0.0" 57 | }, 58 | "engines": { 59 | "node": ">= 6" 60 | }, 61 | "funding": { 62 | "url": "https://github.com/cheeriojs/cheerio?sponsor=1" 63 | } 64 | }, 65 | "node_modules/cheerio-select": { 66 | "version": "2.1.0", 67 | "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", 68 | "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", 69 | "dependencies": { 70 | "boolbase": "^1.0.0", 71 | "css-select": "^5.1.0", 72 | "css-what": "^6.1.0", 73 | "domelementtype": "^2.3.0", 74 | "domhandler": "^5.0.3", 75 | "domutils": "^3.0.1" 76 | }, 77 | "funding": { 78 | "url": "https://github.com/sponsors/fb55" 79 | } 80 | }, 81 | "node_modules/cheerio-to-text": { 82 | "resolved": "..", 83 | "link": true 84 | }, 85 | "node_modules/css-select": { 86 | "version": "5.1.0", 87 | "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", 88 | "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", 89 | "dependencies": { 90 | "boolbase": "^1.0.0", 91 | "css-what": "^6.1.0", 92 | "domhandler": "^5.0.2", 93 | "domutils": "^3.0.1", 94 | "nth-check": "^2.0.1" 95 | }, 96 | "funding": { 97 | "url": "https://github.com/sponsors/fb55" 98 | } 99 | }, 100 | "node_modules/css-what": { 101 | "version": "6.1.0", 102 | "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", 103 | "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", 104 | "engines": { 105 | "node": ">= 6" 106 | }, 107 | "funding": { 108 | "url": "https://github.com/sponsors/fb55" 109 | } 110 | }, 111 | "node_modules/dom-serializer": { 112 | "version": "2.0.0", 113 | "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", 114 | "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", 115 | "dependencies": { 116 | "domelementtype": "^2.3.0", 117 | "domhandler": "^5.0.2", 118 | "entities": "^4.2.0" 119 | }, 120 | "funding": { 121 | "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" 122 | } 123 | }, 124 | "node_modules/domelementtype": { 125 | "version": "2.3.0", 126 | "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", 127 | "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", 128 | "funding": [ 129 | { 130 | "type": "github", 131 | "url": "https://github.com/sponsors/fb55" 132 | } 133 | ] 134 | }, 135 | "node_modules/domhandler": { 136 | "version": "5.0.3", 137 | "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", 138 | "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", 139 | "dependencies": { 140 | "domelementtype": "^2.3.0" 141 | }, 142 | "engines": { 143 | "node": ">= 4" 144 | }, 145 | "funding": { 146 | "url": "https://github.com/fb55/domhandler?sponsor=1" 147 | } 148 | }, 149 | "node_modules/domutils": { 150 | "version": "3.1.0", 151 | "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", 152 | "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", 153 | "dependencies": { 154 | "dom-serializer": "^2.0.0", 155 | "domelementtype": "^2.3.0", 156 | "domhandler": "^5.0.3" 157 | }, 158 | "funding": { 159 | "url": "https://github.com/fb55/domutils?sponsor=1" 160 | } 161 | }, 162 | "node_modules/entities": { 163 | "version": "4.5.0", 164 | "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", 165 | "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", 166 | "engines": { 167 | "node": ">=0.12" 168 | }, 169 | "funding": { 170 | "url": "https://github.com/fb55/entities?sponsor=1" 171 | } 172 | }, 173 | "node_modules/htmlparser2": { 174 | "version": "8.0.2", 175 | "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", 176 | "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", 177 | "funding": [ 178 | "https://github.com/fb55/htmlparser2?sponsor=1", 179 | { 180 | "type": "github", 181 | "url": "https://github.com/sponsors/fb55" 182 | } 183 | ], 184 | "dependencies": { 185 | "domelementtype": "^2.3.0", 186 | "domhandler": "^5.0.3", 187 | "domutils": "^3.0.1", 188 | "entities": "^4.4.0" 189 | } 190 | }, 191 | "node_modules/nth-check": { 192 | "version": "2.1.1", 193 | "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", 194 | "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", 195 | "dependencies": { 196 | "boolbase": "^1.0.0" 197 | }, 198 | "funding": { 199 | "url": "https://github.com/fb55/nth-check?sponsor=1" 200 | } 201 | }, 202 | "node_modules/parse5": { 203 | "version": "7.1.2", 204 | "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", 205 | "integrity": "sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==", 206 | "dependencies": { 207 | "entities": "^4.4.0" 208 | }, 209 | "funding": { 210 | "url": "https://github.com/inikulin/parse5?sponsor=1" 211 | } 212 | }, 213 | "node_modules/parse5-htmlparser2-tree-adapter": { 214 | "version": "7.0.0", 215 | "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz", 216 | "integrity": "sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==", 217 | "dependencies": { 218 | "domhandler": "^5.0.2", 219 | "parse5": "^7.0.0" 220 | }, 221 | "funding": { 222 | "url": "https://github.com/inikulin/parse5?sponsor=1" 223 | } 224 | }, 225 | "node_modules/typescript": { 226 | "version": "5.2.2", 227 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", 228 | "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", 229 | "dev": true, 230 | "bin": { 231 | "tsc": "bin/tsc", 232 | "tsserver": "bin/tsserver" 233 | }, 234 | "engines": { 235 | "node": ">=14.17" 236 | } 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /sample-ts-use/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ 22 | // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ 26 | 27 | /* Modules */ 28 | "module": "commonjs", /* Specify what module code is generated. */ 29 | // "rootDir": "./", /* Specify the root folder within your source files. */ 30 | // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ 31 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 32 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 33 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 34 | // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ 35 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 36 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 37 | // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ 38 | // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ 39 | // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ 40 | // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ 41 | // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ 42 | // "resolveJsonModule": true, /* Enable importing .json files. */ 43 | // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ 44 | // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ 45 | 46 | /* JavaScript Support */ 47 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ 48 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 49 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ 50 | 51 | /* Emit */ 52 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 53 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 54 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 55 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 56 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 57 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ 58 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 59 | // "removeComments": true, /* Disable emitting comments. */ 60 | // "noEmit": true, /* Disable emitting files from a compilation. */ 61 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 62 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ 63 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 64 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 65 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 66 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 67 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 68 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 69 | // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ 70 | // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ 71 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 72 | // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ 73 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 74 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 75 | 76 | /* Interop Constraints */ 77 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 78 | // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ 79 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 80 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ 81 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 82 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 83 | 84 | /* Type Checking */ 85 | "strict": true, /* Enable all strict type-checking options. */ 86 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ 87 | // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ 88 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 89 | // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ 90 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 91 | // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ 92 | // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ 93 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 94 | // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ 95 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ 96 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 97 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 98 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 99 | // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ 100 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 101 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ 102 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 103 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 104 | 105 | /* Completeness */ 106 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 107 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /test/fixtures/verifying-your-email-address.html: -------------------------------------------------------------------------------- 1 | Verifying your email address - GitHub Docs 2 |
Skip to main content

Verifying your email address

Verifying your primary email address ensures strengthened security, allows GitHub staff to better assist you if you forget your password, and gives you access to more features on GitHub.

About email verification

3 |

You can verify your email address after signing up for a new account, or when you add a new email address. If an email address is undeliverable or bouncing, it will be unverified.

4 |

If you do not verify your email address, you will not be able to:

5 |
    6 |
  • Create or fork repositories
  • 7 |
  • Create issues or pull requests
  • 8 |
  • Comment on issues, pull requests, or commits
  • 9 |
  • Authorize OAuth App applications
  • 10 |
  • Generate personal access tokens
  • 11 |
  • Receive email notifications
  • 12 |
  • Star repositories
  • 13 |
  • Create or update project boards, including adding cards
  • 14 |
  • Create or update gists
  • 15 |
  • Create or use GitHub Actions
  • 16 |
  • Sponsor developers with GitHub Sponsors
  • 17 |
18 |
19 |

Warnings:

20 |
    21 |
  • You cannot verify email addresses from disposable email address services (services that allow you to receive email at a temporary address that expires after a certain time). If you'd like to keep your email address private, you can use a GitHub-provided noreply email address. For more information, see "Setting your commit email address on GitHub."
  • 22 |
  • If an organization you're a member of restricts email notifications to an approved email domain, you'll need to verify an email address in that domain to receive email notifications about activity in the organization. For more information, see "Restricting email notifications to an approved domain."
  • 23 |
24 |
25 |

Verifying your email address

26 |
    27 |
  1. 28 |

    In the upper-right corner of any page, click your profile photo, then click Settings.

    29 |

    Settings icon in the user bar

    30 |
  2. 31 |
  3. 32 |

    In the "Access" section of the sidebar, click Emails.

    33 |
  4. 34 |
  5. 35 |

    Under your email address, click Resend verification email. 36 | Resend verification email link

    37 |
  6. 38 |
  7. 39 |

    GitHub will send you an email with a link in it. After you click that link, you'll be taken to your GitHub dashboard and see a confirmation banner. 40 | Banner confirming that your email was verified

    41 |
  8. 42 |
43 |

Troubleshooting email verification

44 |

Unable to send verification email

45 |

You cannot verify email addresses from disposable email address services (services that allow you to receive email at a temporary address that expires after a certain time). If you'd like to keep your email address private, you can use a GitHub-provided noreply email address. For more information, see "Setting your commit email address on GitHub."

46 | 47 |

The verification link expires after 24 hours. If you don't verify your email within 24 hours, you can request another email verification link. For more information, see "Verifying your email address."

48 |

If you click on the link in the confirmation email within 24 hours and you are directed to an error page, you should ensure that you're signed into the correct account on GitHub.com.

49 |
    50 |
  1. Sign out of your personal account on GitHub.com.
  2. 51 |
  3. Quit and restart your browser.
  4. 52 |
  5. Sign in to your personal account on GitHub.com.
  6. 53 |
  7. Click on the verification link in the email we sent you.
  8. 54 |
55 |

Further reading

56 |
59 |
60 | 61 | --------------------------------------------------------------------------------