{"id":17925310,"url":"https://github.com/y21/tljs","last_synced_at":"2026-02-28T12:02:12.842Z","repository":{"id":44727728,"uuid":"430241790","full_name":"y21/tljs","owner":"y21","description":"Fast HTML5 parser for JavaScript","archived":false,"fork":false,"pushed_at":"2022-06-05T11:43:34.000Z","size":210,"stargazers_count":20,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-07-27T06:05:10.749Z","etag":null,"topics":["dom","html","javascript","parser","webassembly"],"latest_commit_sha":null,"homepage":"https://y21.github.io/tljs","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/y21.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-21T00:44:43.000Z","updated_at":"2025-07-07T19:54:05.000Z","dependencies_parsed_at":"2022-08-02T22:45:45.010Z","dependency_job_id":null,"html_url":"https://github.com/y21/tljs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/y21/tljs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/y21%2Ftljs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/y21%2Ftljs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/y21%2Ftljs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/y21%2Ftljs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/y21","download_url":"https://codeload.github.com/y21/tljs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/y21%2Ftljs/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29933021,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-28T09:58:13.507Z","status":"ssl_error","status_checked_at":"2026-02-28T09:57:57.047Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dom","html","javascript","parser","webassembly"],"created_at":"2024-10-28T20:53:24.245Z","updated_at":"2026-02-28T12:02:12.819Z","avatar_url":"https://github.com/y21.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tljs\nA [high performance](#benchmark) HTML5 parser for JavaScript.\n\nThis library wraps the Rust crate [tl](https://github.com/y21/tl) and exposes its interface to JavaScript.\n\n## When To Use\nThis library can *very quickly* parse *very large* HTML documents. However, this library is not suitable for every use case.\nIn particular, if you find yourself having to do lots of operations on the nodes, this may not be for you, due to the overhead of calling into WebAssembly.\nSo, use this library if:\n\n- Most of the time is likely spent parsing documents.\n- Not a lot of operations are done on the nodes.\n- You need to parse *large* documents (tens to hundreds of megabytes)\n\nIn any case, you should benchmark this library for your specific use case, and see if you benefit from the fast parsing speeds, or if the WebAssembly overhead is a bottleneck.\n\n## How To Use\n```js\nconst tljs = require('@y21/tljs');\nconst dom = await tljs.parse(`\n    \u003c!DOCTYPE html\u003e\n    \u003cdiv\u003e\n        \u003cp id=\"greeting\"\u003eHello World\u003c/p\u003e\n        \u003cimg id=\"img\" src=\"image.png\" /\u003e\n    \u003c/div\u003e\n`);\n\nconsole.log(dom.getElementById('img').asTag().attributes().get('src')); // image.png\nconsole.log(dom.getElementById('greeting').asTag().innerText()); // Hello World\nconsole.log(dom.querySelector('p#greeting').asTag().innerText()); // Hello World\nconsole.log(dom.version() === tljs.HTMLVersion.HTML5); // true\n```\n\n## Spec compliance\nThis parser does **not** fully follow the HTML standard, however it is expected to be able to parse most \"sane\" HTML.\nThis greatly impacts performance and should be taken into consideration when comparing performance of different HTML parsers.\nNot being bound to a spec enables a *lot* more optimization opportunities.\n\n## Using this library in the browser\nIt's possible to use this library in very \"restricted\" JavaScript environments (for example no access to the file system or network). By default, this library assumes it's running under Node.js and attempts to load the `.wasm` binary needed to call into Rust code using `require('fs').readFile`.\n\nIf you want to use this library in the browser or other environments, you need to override the default WebAssembly loading mechanism. This depends on your setup, but one way to achieve this would be to host the `.wasm` binary elsewhere (maybe serve it from your webserver) and use `fetch()` to get the binary.\n```js\nconst tljs = require('@y21/tljs');\n\n// override the wasm loading function\ntljs.setInitializerCallback(() =\u003e {\n  return fetch('/tl.wasm').then(x =\u003e x.arrayBuffer()); // assuming `/tl.wasm` serves the binary.\n});\n\ntljs.parse('\u003cp\u003eHello world\u003c/p\u003e');\n```\nIt doesn't matter *how* you obtain the WebAssembly binary, but you'll need to return an `ArrayBuffer` from the initializer callback (can also be a promise resolving to an `ArrayBuffer`).\n\n## Benchmark\n```\ntl                 : 0.863912 ms/file ± 0.528114\nhtmlparser2        : 2.02348 ms/file ± 3.05865\nhtml5parser        : 2.20736 ms/file ± 2.66850\nhtmlparser2-dom    : 2.70631 ms/file ± 3.40642\nhtml-dom-parser    : 2.72998 ms/file ± 3.56091\nneutron-html5parser: 2.74419 ms/file ± 1.52848\nnode-html-parser   : 2.89545 ms/file ± 1.80618\nlibxmljs           : 4.20240 ms/file ± 2.99146\nzeed-dom           : 4.82065 ms/file ± 2.86533\nhtmljs-parser      : 5.97658 ms/file ± 6.65908\nparse5             : 6.85238 ms/file ± 7.75122\narijs-stream       : 18.7410 ms/file ± 18.6447\narijs-tree         : 20.6841 ms/file ± 19.4813\nhtmlparser         : 21.8427 ms/file ± 154.758\nhtml-parser        : 27.3543 ms/file ± 20.7064\nsaxes              : 58.8234 ms/file ± 167.164\nhtml5              : 109.685 ms/file ± 146.399\n```\nBenchmarked against real world data using [AndreasMadsen/htmlparser-benchmark](https://github.com/AndreasMadsen/htmlparser-benchmark).\n\n*Note: This benchmark only measures raw HTML parsing, not DOM interaction.*\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fy21%2Ftljs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fy21%2Ftljs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fy21%2Ftljs/lists"}