{"id":28487187,"url":"https://github.com/rehypejs/rehype-infer-description-meta","last_synced_at":"2025-07-01T17:30:33.213Z","repository":{"id":44807212,"uuid":"404990010","full_name":"rehypejs/rehype-infer-description-meta","owner":"rehypejs","description":"rehype plugin to infer file metadata from the contents of the document","archived":false,"fork":false,"pushed_at":"2023-09-02T08:42:46.000Z","size":55,"stargazers_count":13,"open_issues_count":0,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-06-16T17:23:01.798Z","etag":null,"topics":["description","excerpt","file","hast","meta","rehype","rehype-plugin","summary","truncate"],"latest_commit_sha":null,"homepage":"https://unifiedjs.com","language":"JavaScript","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/rehypejs.png","metadata":{"funding":{"github":"unifiedjs","open_collective":"unified"},"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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-10T07:14:01.000Z","updated_at":"2025-06-13T08:41:04.000Z","dependencies_parsed_at":"2024-06-19T00:20:52.453Z","dependency_job_id":"766f5531-bcc1-42a4-902d-712872f58861","html_url":"https://github.com/rehypejs/rehype-infer-description-meta","commit_stats":{"total_commits":24,"total_committers":1,"mean_commits":24.0,"dds":0.0,"last_synced_commit":"88b25781a7c5ff50f4191c1afd18eac13e3a32ce"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/rehypejs/rehype-infer-description-meta","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehypejs%2Frehype-infer-description-meta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehypejs%2Frehype-infer-description-meta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehypejs%2Frehype-infer-description-meta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehypejs%2Frehype-infer-description-meta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rehypejs","download_url":"https://codeload.github.com/rehypejs/rehype-infer-description-meta/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rehypejs%2Frehype-infer-description-meta/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262301458,"owners_count":23290075,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["description","excerpt","file","hast","meta","rehype","rehype-plugin","summary","truncate"],"created_at":"2025-06-08T04:12:10.067Z","updated_at":"2025-07-01T17:30:33.195Z","avatar_url":"https://github.com/rehypejs.png","language":"JavaScript","funding_links":["https://github.com/sponsors/unifiedjs","https://opencollective.com/unified"],"categories":[],"sub_categories":[],"readme":"# rehype-infer-description-meta\n\n[![Build][build-badge]][build]\n[![Coverage][coverage-badge]][coverage]\n[![Downloads][downloads-badge]][downloads]\n[![Size][size-badge]][size]\n[![Sponsors][sponsors-badge]][collective]\n[![Backers][backers-badge]][collective]\n[![Chat][chat-badge]][chat]\n\n**[rehype][]** plugin to infer the description of a document.\n\n## Contents\n\n*   [What is this?](#what-is-this)\n*   [When should I use this?](#when-should-i-use-this)\n*   [Install](#install)\n*   [Use](#use)\n*   [API](#api)\n    *   [`unified().use(rehypeInferDescriptionMeta[, options])`](#unifieduserehypeinferdescriptionmeta-options)\n    *   [`Options`](#options)\n*   [Types](#types)\n*   [Compatibility](#compatibility)\n*   [Security](#security)\n*   [Related](#related)\n*   [Contribute](#contribute)\n*   [License](#license)\n\n## What is this?\n\nThis package is a [unified][] ([rehype][]) plugin to infer the description of a\ndocument.\nIt supports different methods: a specific element, everything up to a comment,\nor up to a certain number of characters.\n\n**unified** is a project that transforms content with abstract syntax trees\n(ASTs).\n**rehype** adds support for HTML to unified.\n**vfile** is the virtual file interface used in unified.\n**hast** is the HTML AST that rehype uses.\nThis is a rehype plugin that inspects hast and adds metadata to vfiles.\n\n## When should I use this?\n\nThis plugin is particularly useful in combination with\n[`rehype-meta`][rehype-meta].\nWhen both are used together, a `\u003cmeta name=description\u003e` is populated with the\ndocument’s description.\n\n## Install\n\nThis package is [ESM only][esm].\nIn Node.js (version 16+), install with [npm][]:\n\n```sh\nnpm install rehype-infer-description-meta\n```\n\nIn Deno with [`esm.sh`][esmsh]:\n\n```js\nimport rehypeInferDescriptionMeta from 'https://esm.sh/rehype-infer-description-meta@2'\n```\n\nIn browsers with [`esm.sh`][esmsh]:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import rehypeInferDescriptionMeta from 'https://esm.sh/rehype-infer-description-meta@2?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\nSay our module `example.js` contains:\n\n```js\nimport rehypeDocument from 'rehype-document'\nimport rehypeFormat from 'rehype-format'\nimport rehypeInferDescriptionMeta from 'rehype-infer-description-meta'\nimport rehypeMeta from 'rehype-meta'\nimport rehypeParse from 'rehype-parse'\nimport rehypeStringify from 'rehype-stringify'\nimport {unified} from 'unified'\n\nconst examples = [\n  // 1. Example where the description is in a certain element.\n  `\u003ch1\u003eHello, world!\u003c/h1\u003e\n  \u003cp class=\"byline\"\u003eLorem ipsum\u003c/p\u003e\n  \u003cp\u003eDolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e`,\n  // 2. Example where the description runs from the start to a comment.\n  `\u003ch1\u003eHello, world!\u003c/h1\u003e\n  \u003cp\u003eLorem ipsum\u003c!--more--\u003e dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e`,\n  // 3. Example where the description runs from the start to a certain number of characters.\n  `\u003ch1\u003eHello, world!\u003c/h1\u003e\n    \u003cp\u003eLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e`\n]\n\nconst promises = examples.map(function (example) {\n  return (async function () {\n    const file = await unified()\n      .use(rehypeParse, {fragment: true})\n      .use(rehypeInferDescriptionMeta, {selector: '.byline'})\n      .use(rehypeDocument)\n      .use(rehypeMeta)\n      .use(rehypeFormat)\n      .use(rehypeStringify)\n      .process(example)\n\n    console.log(String(file))\n  })()\n})\n\nawait Promise.all(promises)\n```\n\n…then running `node example.js` yields:\n\n\u003e 👉 **Note**: `meta[name=\"description\"]` is derived from `.byline`:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta content=\"width=device-width, initial-scale=1\" name=\"viewport\"\u003e\n    \u003cmeta name=\"description\" content=\"Lorem ipsum\"\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eHello, world!\u003c/h1\u003e\n    \u003cp class=\"byline\"\u003eLorem ipsum\u003c/p\u003e\n    \u003cp\u003eDolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003e 👉 **Note**: `meta[name=\"description\"]` is derived from content before `\u003c!--more--\u003e`:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta content=\"width=device-width, initial-scale=1\" name=\"viewport\"\u003e\n    \u003cmeta name=\"description\" content=\"Lorem ipsum\"\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eHello, world!\u003c/h1\u003e\n    \u003cp\u003eLorem ipsum\u003c!--more--\u003e dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003e 👉 **Note**: `meta[name=\"description\"]` is truncated from the document:\n\n```html\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta content=\"width=device-width, initial-scale=1\" name=\"viewport\"\u003e\n    \u003cmeta name=\"description\" content=\"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad…\"\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eHello, world!\u003c/h1\u003e\n    \u003cp\u003eLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\u003c/p\u003e\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n## API\n\nThis package exports no identifiers.\nThe default export is\n[`rehypeInferDescriptionMeta`][api-rehype-infer-description-meta].\n\n### `unified().use(rehypeInferDescriptionMeta[, options])`\n\nInfer file metadata from the main title of a document.\n\nThe result is stored on `file.data.meta.description` (and\n`file.data.meta.descriptionHast`).\n\n###### Parameters\n\n*   `options` ([`Options`][api-options], optional)\n    — configuration\n\n###### Returns\n\nTransform ([`Transformer`][unified-transformer]).\n\n###### Notes\n\nThe description is inferred through three strategies:\n\n1.  If `options.selector` is set and an element for that found, then the\n    description is the text of that element\n2.  Otherwise, if a comment is found with the text of `options.comment`, then\n    the description is the text up to that comment\n3.  Otherwise, the description is the text up to `options.truncateSize`\n\n### `Options`\n\nConfiguration (TypeScript type).\n\n###### Fields\n\n*   `comment` (`string`, default: `'more'`)\n    — string to look for in a comment; one of the strategies is to look for\n    this comment, everything before it is the description\n*   `ignoreSelector` (`string`, default: `'h1, script, style, noscript,\n    template'`)\n    — CSS selector of nodes to ignore; used when looking for an excerpt comment\n    or truncating the document\n*   `inferDescriptionHast` (`boolean`, default: `false`)\n    — whether to expose `file.data.meta.descriptionHast`; this is not used by\n    `rehype-meta`, but could be useful to other plugins; the value contains the\n    rich HTML elements rather than the plain text content\n*   `mainSelector` (`string`, optional)\n    — CSS selector to body of content; useful to exclude other things, such as\n    the head, ads, styles, scripts, and other random stuff, by focussing all\n    strategies in one element\n*   `maxExcerptSearchSize` (`number`, default: `2048`)\n    — how far to search for the excerpt comment before bailing; the goal of\n    explicit excerpts is that they are assumed to be somewhat reasonably\n    placed; this option prevents searching giant documents for some comment\n    that probably won’t be found at the end\n*   `selector` (`string`, optional)\n    — CSS selector to the description; one of the strategies is to look for a\n    certain element, useful if the description is nicely encoded in one element\n*   `truncateSize` (`number`, default: `140`)\n    — number of characters to truncate to; one of the strategies is to truncate\n    the document to a certain number of characters\n\n## Types\n\nThis package is fully typed with [TypeScript][].\nIt exports the additional type [`Options`][api-options].\n\nIt also registers `file.data.meta` with `vfile`.\nIf you’re working with the file, make sure to import this plugin somewhere in\nyour types, as that registers the new fields on the file.\n\n```js\n/**\n * @typedef {import('rehype-infer-description-meta')}\n */\n\nimport {VFile} from 'vfile'\n\nconst file = new VFile()\n\nconsole.log(file.data.meta.description) //=\u003e TS now knows that this is a `string?`.\n```\n\n## Compatibility\n\nProjects maintained by the unified collective are compatible with maintained\nversions of Node.js.\n\nWhen we cut a new major release, we drop support for unmaintained versions of\nNode.\nThis means we try to keep the current release line,\n`rehype-infer-description-meta@^2`, compatible with Node.js 16.\n\nThis plugin works with `rehype-parse` version 3+, `rehype-stringify` version 3+,\n`rehype` version 4+, and `unified` version 6+.\n\n## Security\n\nUse of `rehype-infer-description-meta` is safe.\n\n## Related\n\n*   [`rehype-document`](https://github.com/rehypejs/rehype-document)\n    — wrap a fragment in a document\n*   [`rehype-meta`](https://github.com/rehypejs/rehype-meta)\n    — add metadata to the head of a document\n*   [`unified-infer-git-meta`](https://github.com/unifiedjs/unified-infer-git-meta)\n    — infer file metadata from Git\n*   [`rehype-infer-title-meta`](https://github.com/rehypejs/rehype-infer-title-meta)\n    — infer file metadata from the title of a document\n*   [`rehype-infer-reading-time-meta`](https://github.com/rehypejs/rehype-infer-reading-time-meta)\n    — infer file metadata from the reading time of a document\n\n## Contribute\n\nSee [`contributing.md`][contributing] in [`rehypejs/.github`][health] for ways\nto get started.\nSee [`support.md`][support] for ways to get help.\n\nThis project has a [code of conduct][coc].\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.\n\n## License\n\n[MIT][license] © [Titus Wormer][author]\n\n\u003c!-- Definitions --\u003e\n\n[build-badge]: https://github.com/rehypejs/rehype-infer-description-meta/workflows/main/badge.svg\n\n[build]: https://github.com/rehypejs/rehype-infer-description-meta/actions\n\n[coverage-badge]: https://img.shields.io/codecov/c/github/rehypejs/rehype-infer-description-meta.svg\n\n[coverage]: https://codecov.io/github/rehypejs/rehype-infer-description-meta\n\n[downloads-badge]: https://img.shields.io/npm/dm/rehype-infer-description-meta.svg\n\n[downloads]: https://www.npmjs.com/package/rehype-infer-description-meta\n\n[size-badge]: https://img.shields.io/bundlejs/size/rehype-infer-description-meta\n\n[size]: https://bundlejs.com/?q=rehype-infer-description-meta\n\n[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg\n\n[backers-badge]: https://opencollective.com/unified/backers/badge.svg\n\n[collective]: https://opencollective.com/unified\n\n[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg\n\n[chat]: https://github.com/rehypejs/rehype/discussions\n\n[npm]: https://docs.npmjs.com/cli/install\n\n[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[esmsh]: https://esm.sh\n\n[health]: https://github.com/rehypejs/.github\n\n[contributing]: https://github.com/rehypejs/.github/blob/main/contributing.md\n\n[support]: https://github.com/rehypejs/.github/blob/main/support.md\n\n[coc]: https://github.com/rehypejs/.github/blob/main/code-of-conduct.md\n\n[license]: license\n\n[author]: https://wooorm.com\n\n[rehype]: https://github.com/rehypejs/rehype\n\n[rehype-meta]: https://github.com/rehypejs/rehype-meta\n\n[typescript]: https://www.typescriptlang.org\n\n[unified]: https://github.com/unifiedjs/unified\n\n[unified-transformer]: https://github.com/unifiedjs/unified#transformer\n\n[api-rehype-infer-description-meta]: #unifieduserehypeinferdescriptionmeta-options\n\n[api-options]: #options\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frehypejs%2Frehype-infer-description-meta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frehypejs%2Frehype-infer-description-meta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frehypejs%2Frehype-infer-description-meta/lists"}