{"id":15641345,"url":"https://github.com/joseluisq/printd","last_synced_at":"2026-03-10T11:04:20.286Z","repository":{"id":24707023,"uuid":"200593700","full_name":"joseluisq/printd","owner":"joseluisq","description":"Print HTML elements or pages in modern browsers.","archived":false,"fork":false,"pushed_at":"2023-02-11T03:02:27.000Z","size":883,"stargazers_count":83,"open_issues_count":4,"forks_count":5,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-14T05:22:07.898Z","etag":null,"topics":["browser","html-elements","javascript","modern-browsers","print","print-dialog","print-dom","print-html-pages","typescript"],"latest_commit_sha":null,"homepage":"","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/joseluisq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null},"funding":{"github":"joseluisq","custom":"paypal.me/joseluisqs"}},"created_at":"2019-08-05T06:16:58.000Z","updated_at":"2025-04-18T04:44:58.000Z","dependencies_parsed_at":"2022-08-07T11:01:16.338Z","dependency_job_id":"9fbef36a-06be-42e7-b0ed-ee03f7c93cf6","html_url":"https://github.com/joseluisq/printd","commit_stats":{"total_commits":138,"total_committers":8,"mean_commits":17.25,"dds":"0.28260869565217395","last_synced_commit":"d8b8e1c9917a05fa76122de2fe95a2c6dbd8fd90"},"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/joseluisq/printd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseluisq%2Fprintd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseluisq%2Fprintd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseluisq%2Fprintd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseluisq%2Fprintd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joseluisq","download_url":"https://codeload.github.com/joseluisq/printd/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joseluisq%2Fprintd/sbom","scorecard":{"id":533367,"data":{"date":"2025-08-11","repo":{"name":"github.com/joseluisq/printd","commit":"d8b8e1c9917a05fa76122de2fe95a2c6dbd8fd90"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.8,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/ci.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/27 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/joseluisq/printd/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/joseluisq/printd/ci.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.md:0","Info: FSF or OSI recognized license: MIT License: LICENSE.md:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 6 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T06:17:03.762Z","repository_id":24707023,"created_at":"2025-08-20T06:17:03.762Z","updated_at":"2025-08-20T06:17:03.762Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30331644,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: 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":["browser","html-elements","javascript","modern-browsers","print","print-dialog","print-dom","print-html-pages","typescript"],"created_at":"2024-10-03T11:42:15.800Z","updated_at":"2026-03-10T11:04:20.246Z","avatar_url":"https://github.com/joseluisq.png","language":"TypeScript","funding_links":["https://github.com/sponsors/joseluisq","paypal.me/joseluisqs"],"categories":[],"sub_categories":[],"readme":"# Printd ![CI](https://github.com/joseluisq/printd/workflows/CI/badge.svg?branch=master) [![npm](https://img.shields.io/npm/v/printd.svg)](https://www.npmjs.com/package/printd) [![npm](https://img.shields.io/npm/dt/printd.svg)](https://www.npmjs.com/package/printd) [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)\n\n\u003e [Print](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) HTML elements or pages in modern browsers. :printer:\n\nPrintd opens your [Browser Print Dialog](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) to print HTML elements inside a blank document or pages by URL.\n\n## Features\n\n- Written and tested entirely in [Typescript](./src/index.ts).\n- Tiny script (around `1KB` gzipped with no dependencies).\n- Print any element **_without_** opening a new window.\n- Print only when assets such as images or fonts are ready (loaded).\n- Print pages by URL.\n- Add styles and scripts on demand using text or URL.\n\n## Demos\n\n- 🚀 [Live Demo](https://codepen.io/joseluisq/full/VzRpGb/)\n- 📘 [Simple Code Example](./sample) - Clone this repository and just run `npm run sample`\n- 📗 [Vue Code example](https://github.com/joseluisq/printd-vue-component-example)\n\n## Install\n\n[Yarn](https://github.com/yarnpkg/)\n\n```sh\nyarn add printd\n```\n\n[NPM](https://www.npmjs.com/)\n\n```sh\nnpm install printd --save\n```\n\n[UMD](https://github.com/umdjs/umd/) file is also available on [unpkg](https://unpkg.com):\n\n```html\n\u003cscript src=\"https://unpkg.com/printd/printd.umd.min.js\"\u003e\u003c/script\u003e\n```\n\nYou can use the library via `window.printd`.\n\n## Usage\n\n```ts\nimport { Printd } from 'printd'\n\nconst cssText = `\n  h1 {\n    color: black;\n    font-family: sans-serif;\n  }\n`\n\nconst d = new Printd()\nd.print( document.getElementById('myelement'), [ cssText ] )\n```\n\n## API\n\n### options\n\n- __parent__: Optional parent element where the printable element will be appended. Default `window.document.body`\n- __headElements__: Optional custom document `head` elements array.\n- __bodyElements__: Optional custom document `body` elements array.\n\nExample:\n\n```ts\n// custom base element example\nconst base = document.createElement('base')\nbase.setAttribute('href', 'https://your-cdn.dev')\n\n// define options to use\nconst options = {\n  parent: document.getElementById('myparent'),\n  headElements: [ base ]\n}\n\nconst d = new Printd(options)\n```\n\n### print\n\nFunction to print an `HTMLElement`.\n\n```ts\nd.print (element, styles, scripts, callback)\n```\n\n__Print parameters:__\n\n- __element:__ Some `HTMLElement` object to print.\n- __styles:__ Optional styles (array of texts or urls) that will add to iframe (`document.head`)\n- __scripts:__ Optional scripts (array of texts or urls) that will add to iframe (`document.body`)\n- __callback:__ Optional callback that will be triggered when content is ready to print.\n  - __callback arguments:__\n  - __iframe__: An `HTMLIFrameElement` reference. It already contains `contentWindow` and `contentDocument` references.\n  - __element__: An `HTMLElement` copy (cloned node) reference of current element to print.\n  - __launchPrint__: Function to launch the print dialog after assets (images, fonts, etc) was loaded.\n\n#### 1. Basic example\n\n```ts\nconst d = new Printd()\n\nd.print( document.getElementById('h1'), [`h1 { font-family: serif; }`] )\n```\n\n#### 2. Callback example\n\nCallback option is suitable when you plan to print elements or pages with assets (images, fonts, etc) but you need to wait for them. Your callback will be triggered only when your assets are loaded.\n\n```ts\nconst d = new Printd()\n\n// Tip: texts \u0026 urls are supported\n\nconst styles = [\n  'https://your-cdn.dev/style.css',\n  `.code { font-family: monospace; }`\n]\n\nconst scripts = [\n  'https://your-cdn.dev/script.js',\n  `(() =\u003e console.log('Hello from IFrame!'))()`\n]\n\n// Get an HTMLElement reference\nconst el = document.getElementById('mycode-block')\n// Trigger the print dialog on demand\nconst printCallback = ({ launchPrint }) =\u003e launchPrint()\n\nd.print(el, styles, scripts, printCallback)\n```\n\n### printURL\n\nFunction to print an URL.\n\n__PrintURL parameters:__\n\n- __url:__ URL to print.\n- __callback:__ Optional callback that will be triggered when content is ready to print.\n\n```ts\nconst d = new Printd()\n\nd.printURL('http://127.0.0.1/', ({ launchPrint }) =\u003e {\n  console.log('Content loaded!')\n\n  // fire printing!\n  launchPrint()\n})\n```\n\n### Built-in print events\n\nPrintd provides convenient print event methods on top of the Browser `beforeprint` and `afterprint` events.\nHowever note that they *only* work when printing custom HTML elements via the `print()` method.\n\n```ts\nconst d = new Printd()\n\nd.onBeforePrint((event) =\u003e console.log(event, \"called before printing!\"))\nd.onAfterPrint((event) =\u003e console.log(event, \"called after printing!\"))\n\nd.print(document.getElementById('myelement'))\n```\n\n### getIFrame\n\nGets the current `HTMLIFrameElement` reference.\n\nExamples:\n\n```ts\nconst d = new Printd()\nconst iframe = d.getIFrame()\n\n// a) Subscribe to IFrame load event\niframe.addEventListener('load', () =\u003e console.log('iframe loaded!'))\n\n// b) Subscribe to Window `beforeprint` or `afterprint` events\nconst { contentWindow } = iframe\ncontentWindow.addEventListener('beforeprint', () =\u003e console.log('before print!'))\ncontentWindow.addEventListener('afterprint', () =\u003e console.log('after print!'))\n```\n\n## Browser compatibility\n\n- Chrome Desktop 63+\n- Chrome for Android 63+\n- Firefox 6+\n- Edge\n- Internet Explorer 11\n- Opera Desktop 50+\n- Opera for Android 50+\n\n__References:__\n\n- [Chrome Platform Status - beforeprint and afterprint events](https://www.chromestatus.com/features/5700595042222080)\n- https://caniuse.com/#feat=beforeafterprint\n- [PR: Update support for before/after print event handlers (Blink)](https://github.com/Fyrd/caniuse/pull/4086)\n- https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeprint\n\n### beforeprint \u0026 afterprint workaround (Webkit-based and old browsers)\n\nFor Webkit-based browsers, it can create an equivalent result using `window.matchMedia('print')`.\n\n```ts\nif (contentWindow.matchMedia) {\n  const mediaQueryList = contentWindow.matchMedia('print')\n\n  mediaQueryList.addListener((mql) =\u003e {\n    if (mql.matches) {\n      console.log('before print!')\n    } else {\n      console.log('after print!')\n    }\n  })\n}\n```\n\n__References:__\n- https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeprint\n- https://www.tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/\n\n\n## Security\n\nSince Printd uses an underlying iframe it's highly recommended to ensure that only your content will be displayed.\nAs a fallback you could remove the hidden iframe after some printing.\n\nHere some interesting security advices that you want to take at look:\n\n- [Why are iframes considered dangerous and a security risk?](https://stackoverflow.com/a/9428051/2510591)\n- [MDN: X-Frame-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options)\n- [Play safely in sandboxed IFrames](https://www.html5rocks.com/en/tutorials/security/sandboxed-iframes/)\n\n## Contributions\n\nFeel free to send some [Pull request](https://github.com/joseluisq/printd/pulls) or [issue](https://github.com/joseluisq/printd/issues).\n\n## License\nMIT license\n\n© 2017-present [Jose Quintana](https://github.com/joseluisq)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseluisq%2Fprintd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoseluisq%2Fprintd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoseluisq%2Fprintd/lists"}