{"id":13716762,"url":"https://github.com/syntax-tree/hastscript","last_synced_at":"2025-06-29T22:03:51.086Z","repository":{"id":42188153,"uuid":"52467321","full_name":"syntax-tree/hastscript","owner":"syntax-tree","description":"utility to create hast trees","archived":false,"fork":false,"pushed_at":"2025-02-19T13:17:58.000Z","size":238,"stargazers_count":183,"open_issues_count":0,"forks_count":13,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-06-16T03:49:12.093Z","etag":null,"topics":["hast","hast-util","html","hyperscript","unist","util"],"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/syntax-tree.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"unifiedjs","open_collective":"unified","thanks_dev":"u/gh/syntax-tree"}},"created_at":"2016-02-24T19:07:56.000Z","updated_at":"2025-06-15T22:54:06.000Z","dependencies_parsed_at":"2024-01-12T23:43:05.790Z","dependency_job_id":"da61eeb7-b77e-4080-ba51-a39fd923be7a","html_url":"https://github.com/syntax-tree/hastscript","commit_stats":{"total_commits":148,"total_committers":6,"mean_commits":"24.666666666666668","dds":0.03378378378378377,"last_synced_commit":"2a7451dc1eb2adc6b07af6efed8a8bdcc8f13758"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/syntax-tree/hastscript","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syntax-tree%2Fhastscript","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syntax-tree%2Fhastscript/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syntax-tree%2Fhastscript/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syntax-tree%2Fhastscript/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/syntax-tree","download_url":"https://codeload.github.com/syntax-tree/hastscript/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/syntax-tree%2Fhastscript/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261446063,"owners_count":23159359,"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":["hast","hast-util","html","hyperscript","unist","util"],"created_at":"2024-08-03T00:01:14.102Z","updated_at":"2025-06-29T22:03:51.011Z","avatar_url":"https://github.com/syntax-tree.png","language":"JavaScript","readme":"# hastscript\n\n[![Build][badge-build-image]][badge-build-url]\n[![Coverage][badge-coverage-image]][badge-coverage-url]\n[![Downloads][badge-downloads-image]][badge-downloads-url]\n[![Size][badge-size-image]][badge-size-url]\n\n[hast][github-hast] utility to create trees with ease.\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  * [`h(selector?[, properties][, …children])`](#hselector-properties-children)\n  * [`s(selector?[, properties][, …children])`](#sselector-properties-children)\n  * [`Child`](#child)\n  * [`Properties`](#properties-1)\n  * [`Result`](#result)\n* [Syntax tree](#syntax-tree)\n* [JSX](#jsx)\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 hyperscript interface (like `createElement` from React and\n`h` from Vue and such) to help with creating hast trees.\n\n## When should I use this?\n\nYou can use this utility in your project when you generate hast syntax trees\nwith code.\nIt helps because it replaces most of the repetition otherwise needed in a syntax\ntree with function calls.\nIt also helps as it improves the attributes you pass by turning them into the\nform that is required by hast.\n\nYou can instead use [`unist-builder`][github-unist-builder]\nwhen creating any unist nodes and\n[`xastscript`][github-xastscript] when creating xast (XML) nodes.\n\n## Install\n\nThis package is [ESM only][github-gist-esm].\nIn Node.js (version 16+),\ninstall with [npm][npmjs-install]:\n\n```sh\nnpm install hastscript\n```\n\nIn Deno with [`esm.sh`][esmsh]:\n\n```js\nimport {h} from 'https://esm.sh/hastscript@9'\n```\n\nIn browsers with [`esm.sh`][esmsh]:\n\n```html\n\u003cscript type=\"module\"\u003e\n  import {h} from 'https://esm.sh/hastscript@9?bundle'\n\u003c/script\u003e\n```\n\n## Use\n\n```js\nimport {h, s} from 'hastscript'\n\nconsole.log(\n  h('.foo#some-id', [\n    h('span', 'some text'),\n    h('input', {type: 'text', value: 'foo'}),\n    h('a.alpha', {class: 'bravo charlie', download: 'download'}, [\n      'delta',\n      'echo'\n    ])\n  ])\n)\n\nconsole.log(\n  s('svg', {viewbox: '0 0 500 500', xmlns: 'http://www.w3.org/2000/svg'}, [\n    s('title', 'SVG `\u003ccircle\u003e` element'),\n    s('circle', {cx: 120, cy: 120, r: 100})\n  ])\n)\n```\n\nYields:\n\n```js\n{\n  type: 'element',\n  tagName: 'div',\n  properties: {className: ['foo'], id: 'some-id'},\n  children: [\n    {\n      type: 'element',\n      tagName: 'span',\n      properties: {},\n      children: [{type: 'text', value: 'some text'}]\n    },\n    {\n      type: 'element',\n      tagName: 'input',\n      properties: {type: 'text', value: 'foo'},\n      children: []\n    },\n    {\n      type: 'element',\n      tagName: 'a',\n      properties: {className: ['alpha', 'bravo', 'charlie'], download: true},\n      children: [{type: 'text', value: 'delta'}, {type: 'text', value: 'echo'}]\n    }\n  ]\n}\n{\n  type: 'element',\n  tagName: 'svg',\n  properties: {viewBox: '0 0 500 500', xmlns: 'http://www.w3.org/2000/svg'},\n  children: [\n    {\n      type: 'element',\n      tagName: 'title',\n      properties: {},\n      children: [{type: 'text', value: 'SVG `\u003ccircle\u003e` element'}]\n    },\n    {\n      type: 'element',\n      tagName: 'circle',\n      properties: {cx: 120, cy: 120, r: 100},\n      children: []\n    }\n  ]\n}\n```\n\n## API\n\nThis package exports the identifiers [`h`][api-h] and [`s`][api-s].\nThere is no default export.\nIt exports the additional [TypeScript][] types\n[`Child`][api-child],\n[`Properties`][api-properties],\nand\n[`Result`][api-result].\n\nThe export map supports the automatic JSX runtime.\nYou can pass `hastscript` or `hastscript/svg` to your build tool\n(TypeScript, Babel, SWC)\nwith an `importSource` option or similar.\n\n### `h(selector?[, properties][, …children])`\n\nCreate virtual **[hast][github-hast]** trees for HTML.\n\n##### Signatures\n\n* `h(): root`\n* `h(null[, …children]): root`\n* `h(selector[, properties][, …children]): element`\n\n##### Parameters\n\n###### `selector`\n\nSimple CSS selector\n(`string`, optional).\nWhen string, builds an [`Element`][github-hast-element].\nWhen nullish, builds a [`Root`][github-hast-root] instead.\nThe selector can contain a tag name (`foo`),\nIDs (`#bar`),\nand classes (`.baz`).\nIf the selector is a string but there is no tag name in it then `h` defaults to\nbuild a `div` element and `s` to a `g` element.\n`selector` is parsed by\n[`hast-util-parse-selector`][github-hast-util-parse-selector].\n\n###### `properties`\n\nProperties of the element\n([`Properties`][api-properties], optional).\n\n###### `children`\n\nChildren of the node ([`Child`][api-child] or `Array\u003cChild\u003e`, optional).\n\n##### Returns\n\nCreated tree ([`Result`][api-result]).\n\n[`Element`][github-hast-element] when a `selector` is passed,\notherwise [`Root`][github-hast-root].\n\n### `s(selector?[, properties][, …children])`\n\nCreate virtual **[hast][github-hast]** trees for SVG.\n\nSignatures, parameters, and return value are the same as `h` above.\nImportantly,\nthe `selector` and `properties` parameters are interpreted as SVG.\n\n### `Child`\n\n(Lists of) children (TypeScript type).\n\nWhen strings or numbers are encountered,\nthey are turned into [`Text`][github-hast-text]\nnodes.\n[`Root`][github-hast-root] nodes are treated as “fragments”,\nmeaning that their children are used instead.\n\n###### Type\n\n```ts\ntype Child =\n  | Array\u003cNode | number | string | null | undefined\u003e\n  | Node\n  | number\n  | string\n  | null\n  | undefined\n```\n\n### `Properties`\n\nMap of properties (TypeScript type).\nKeys should match either the HTML attribute name or the DOM property name,\nbut are case-insensitive.\n\n###### Type\n\n```ts\ntype Properties = Record\u003c\n  string,\n  | boolean\n  | number\n  | string\n  | null\n  | undefined\n  // For comma- and space-separated values such as `className`:\n  | Array\u003cnumber | string\u003e\n  // Accepts value for `style` prop as object.\n  | Record\u003cstring, number | string\u003e\n\u003e\n```\n\n### `Result`\n\nResult from a `h` (or `s`) call (TypeScript type).\n\n###### Type\n\n```ts\ntype Result = Element | Root\n```\n\n## Syntax tree\n\nThe syntax tree is [hast][github-hast].\n\n## JSX\n\nThis package can be used with JSX.\nYou should use the automatic JSX runtime set to `hastscript` or\n`hastscript/svg`.\n\n\u003e 👉 **Note**\n\u003e while `h` supports dots (`.`) for classes or number signs (`#`)\n\u003e for IDs in `selector`,\n\u003e those are not supported in JSX.\n\n\u003e 🪦 **Legacy**:\n\u003e you can also use the classic JSX runtime,\n\u003e but this is not recommended.\n\u003e To do so,\n\u003e import `h` (or `s`) yourself and define it as the pragma\n\u003e (plus set the fragment to `null`).\n\nThe Use example above can then be written like so,\nusing inline pragmas,\nso that SVG can be used too:\n\n`example-html.jsx`:\n\n```js\n/** @jsxImportSource hastscript */\nconsole.log(\n  \u003cdiv class=\"foo\" id=\"some-id\"\u003e\n    \u003cspan\u003esome text\u003c/span\u003e\n    \u003cinput type=\"text\" value=\"foo\" /\u003e\n    \u003ca class=\"alpha bravo charlie\" download\u003e\n      deltaecho\n    \u003c/a\u003e\n  \u003c/div\u003e\n)\n```\n\n`example-svg.jsx`:\n\n```js\n/** @jsxImportSource hastscript/svg */\nconsole.log(\n  \u003csvg xmlns=\"http://www.w3.org/2000/svg\" viewbox=\"0 0 500 500\"\u003e\n    \u003ctitle\u003eSVG `\u0026lt;circle\u0026gt;` element\u003c/title\u003e\n    \u003ccircle cx={120} cy={120} r={100} /\u003e\n  \u003c/svg\u003e\n)\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,\nwe drop support for unmaintained versions of Node.\nThis means we try to keep the current release line,\n`hastscript@9`,\ncompatible with Node.js 16.\n\n## Security\n\nUse of `hastscript` can open you up to a\n[cross-site scripting (XSS)][wikipedia-xss]\nwhen you pass user-provided input to it because values are injected into the\nsyntax tree.\n\nThe following example shows how an image is injected that fails loading and\ntherefore runs code in a browser.\n\n```js\nconst tree = h()\n\n// Somehow someone injected these properties instead of an expected `src` and\n// `alt`:\nconst otherProps = {onError: 'alert(1)', src: 'x'}\n\ntree.children.push(h('img', {src: 'default.png', ...otherProps}))\n```\n\nYields:\n\n```html\n\u003cimg onerror=\"alert(1)\" src=\"x\"\u003e\n```\n\nThe following example shows how code can run in a browser because someone stored\nan object in a database instead of the expected string.\n\n```js\nconst tree = h()\n\n// Somehow this isn’t the expected `'wooorm'`.\nconst username = {\n  type: 'element',\n  tagName: 'script',\n  children: [{type: 'text', value: 'alert(2)'}]\n}\n\ntree.children.push(h('span.handle', username))\n```\n\nYields:\n\n```html\n\u003cspan class=\"handle\"\u003e\u003cscript\u003ealert(2)\u003c/script\u003e\u003c/span\u003e\n```\n\nEither do not use user-provided input in `hastscript` or use\n[`hast-util-santize`][github-hast-util-sanitize].\n\n## Related\n\n* [`unist-builder`][github-unist-builder]\n  — create unist trees\n* [`xastscript`][github-xastscript]\n  — create xast trees\n* [`hast-to-hyperscript`](https://github.com/syntax-tree/hast-to-hyperscript)\n  — turn hast into React, Preact, Vue, etc\n* [`hast-util-to-html`](https://github.com/syntax-tree/hast-util-to-html)\n  — turn hast into HTML\n* [`hast-util-to-dom`](https://github.com/syntax-tree/hast-util-to-dom)\n  — turn hast into DOM trees\n* [`estree-util-build-jsx`](https://github.com/syntax-tree/estree-util-build-jsx)\n  — compile JSX away\n\n## Contribute\n\nSee\n[`contributing.md`][health-contributing]\nin\n[`syntax-tree/.github`][health]\nfor ways to get started.\nSee [`support.md`][health-support] for ways to get help.\n\nThis project has a [code of conduct][health-coc].\nBy interacting with this repository,\norganization,\nor community you agree to abide by its terms.\n\n## License\n\n[MIT][file-license] © [Titus Wormer][wooorm]\n\n\u003c!-- Definitions --\u003e\n\n[api-child]: #child\n\n[api-h]: #hselector-properties-children\n\n[api-properties]: #properties-1\n\n[api-result]: #result\n\n[api-s]: #sselector-properties-children\n\n[badge-build-image]: https://github.com/syntax-tree/hastscript/workflows/main/badge.svg\n\n[badge-build-url]: https://github.com/syntax-tree/hastscript/actions\n\n[badge-coverage-image]: https://img.shields.io/codecov/c/github/syntax-tree/hastscript.svg\n\n[badge-coverage-url]: https://codecov.io/github/syntax-tree/hastscript\n\n[badge-downloads-image]: https://img.shields.io/npm/dm/hastscript.svg\n\n[badge-downloads-url]: https://www.npmjs.com/package/hastscript\n\n[badge-size-image]: https://img.shields.io/bundlejs/size/hastscript\n\n[badge-size-url]: https://bundlejs.com/?q=hastscript\n\n[esmsh]: https://esm.sh\n\n[file-license]: license\n\n[github-gist-esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[github-hast]: https://github.com/syntax-tree/hast\n\n[github-hast-element]: https://github.com/syntax-tree/hast#element\n\n[github-hast-root]: https://github.com/syntax-tree/hast#root\n\n[github-hast-text]: https://github.com/syntax-tree/hast#text\n\n[github-hast-util-parse-selector]: https://github.com/syntax-tree/hast-util-parse-selector\n\n[github-hast-util-sanitize]: https://github.com/syntax-tree/hast-util-sanitize\n\n[github-unist-builder]: https://github.com/syntax-tree/unist-builder\n\n[github-xastscript]: https://github.com/syntax-tree/xastscript\n\n[health]: https://github.com/syntax-tree/.github\n\n[health-coc]: https://github.com/syntax-tree/.github/blob/main/code-of-conduct.md\n\n[health-contributing]: https://github.com/syntax-tree/.github/blob/main/contributing.md\n\n[health-support]: https://github.com/syntax-tree/.github/blob/main/support.md\n\n[npmjs-install]: https://docs.npmjs.com/cli/install\n\n[typescript]: https://www.typescriptlang.org\n\n[wikipedia-xss]: https://en.wikipedia.org/wiki/Cross-site_scripting\n\n[wooorm]: https://wooorm.com\n","funding_links":["https://github.com/sponsors/unifiedjs","https://opencollective.com/unified","https://thanks.dev/u/gh/syntax-tree"],"categories":["hast utilities","VDOM"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyntax-tree%2Fhastscript","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsyntax-tree%2Fhastscript","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsyntax-tree%2Fhastscript/lists"}