{"_id":"@clc-blind/hast-util-from-daisy","_rev":"3-d8673083ef6f849afe6f7af04d400669","name":"@clc-blind/hast-util-from-daisy","dist-tags":{"latest":"1.0.2"},"versions":{"1.0.0":{"name":"@clc-blind/hast-util-from-daisy","version":"1.0.0","author":{"name":"clc-blind"},"_id":"@clc-blind/hast-util-from-daisy@1.0.0","maintainers":[{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"}],"homepage":"https://github.com/clc-blind/hast-util-from-daisy#readme","bugs":{"url":"https://github.com/clc-blind/hast-util-from-daisy/issues"},"dist":{"shasum":"ec1ce81338c1badedbe9eb314dc0508ffb7aef9b","tarball":"https://registry.npmjs.org/@clc-blind/hast-util-from-daisy/-/hast-util-from-daisy-1.0.0.tgz","fileCount":9,"integrity":"sha512-xLvq0s3xHT6s5KKYAZcrCjZq1DHH9mGHFxfTvDHCWjH3UgFXfT6dtdjdXuKedRINToVtkywtQxGoMoyXMddRCg==","signatures":[{"sig":"MEQCIGXe+O6OZ7Sq+zVmdIUyXDD/5oWm3CMTC1k1B6jEFj4aAiBkcJ0vITlisfHH27w1l4zi8CLCiWCxT8X3EzxjMtkzyA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":113462},"main":"./dist/index.js","type":"module","_from":"file:clc-blind-hast-util-from-daisy-1.0.0.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"lint":"tsc","test":"vitest run","build":"tsup","prepublish":"pnpm run build && pnpm run check-exports && pnpm run lint","check-exports":"attw --pack . --ignore-rules=cjs-resolves-to-esm"},"_npmUser":{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"},"_resolved":"/tmp/2a09adc84735b99535faac260b11fcee/clc-blind-hast-util-from-daisy-1.0.0.tgz","_integrity":"sha512-xLvq0s3xHT6s5KKYAZcrCjZq1DHH9mGHFxfTvDHCWjH3UgFXfT6dtdjdXuKedRINToVtkywtQxGoMoyXMddRCg==","repository":{"url":"git+https://github.com/clc-blind/hast-util-from-daisy.git","type":"git"},"_npmVersion":"11.6.0","description":"hast utility to transform DAISY v3 documents to semantic HTML with metadata preservation","directories":{},"_nodeVersion":"24.8.0","dependencies":{"xast-util-from-xml":"4.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.5.0","husky":"9.1.7","eslint":"8.57.1","vitest":"3.2.4","prettier":"3.6.2","@vitest/ui":"3.2.4","typescript":"5.9.2","@babel/core":"7.28.4","@types/hast":"3.0.4","@types/node":"22.18.0","@types/xast":"2.0.4","lint-staged":"16.1.6","@commitlint/cli":"19.8.1","@types/showdown":"2.0.6","eslint-plugin-import":"2.31.0","@arethetypeswrong/cli":"0.18.2","eslint-config-prettier":"9.1.0","eslint-plugin-prettier":"5.2.1","@typescript-eslint/parser":"8.17.0","eslint-config-airbnb-base":"15.0.0","@commitlint/config-conventional":"19.8.1","@typescript-eslint/eslint-plugin":"8.17.0","eslint-import-resolver-typescript":"3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/hast-util-from-daisy_1.0.0_1757953494835_0.6841133934279895","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@clc-blind/hast-util-from-daisy","version":"1.0.1","author":{"name":"clc-blind"},"_id":"@clc-blind/hast-util-from-daisy@1.0.1","maintainers":[{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"}],"homepage":"https://github.com/clc-blind/hast-util-from-daisy#readme","bugs":{"url":"https://github.com/clc-blind/hast-util-from-daisy/issues"},"dist":{"shasum":"1ef2856d1ddf3ef06759f4a0521466d54e15977e","tarball":"https://registry.npmjs.org/@clc-blind/hast-util-from-daisy/-/hast-util-from-daisy-1.0.1.tgz","fileCount":9,"integrity":"sha512-q27M+APIIEoe7YBlI7E759aqDVaNyVhgif9qNecBUUem0Fkt+XtxKSqj7IT2JfKolawp8U+WtKM9SQuCJqonJg==","signatures":[{"sig":"MEQCIB75/ocXCl6GfLwLgyuX568pOrAWh/rHDBtH4iQdL0CuAiBq2zdB9V93sZne9ez5IPA7SaWM93K3JQY8R8ODqIrDaQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117353},"main":"./dist/index.js","type":"module","_from":"file:clc-blind-hast-util-from-daisy-1.0.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.mjs","exports":{".":{"import":"./dist/index.js","default":"./dist/index.cjs"},"./package.json":"./package.json"},"scripts":{"lint":"tsc","test":"vitest run","build":"tsup","prepublish":"pnpm run build && pnpm run check-exports && pnpm run lint","check-exports":"attw --pack . --ignore-rules=cjs-resolves-to-esm"},"_npmUser":{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"},"_resolved":"/tmp/ff3d8ac3b23fcd6d9cbc52bbf77a4ea7/clc-blind-hast-util-from-daisy-1.0.1.tgz","_integrity":"sha512-q27M+APIIEoe7YBlI7E759aqDVaNyVhgif9qNecBUUem0Fkt+XtxKSqj7IT2JfKolawp8U+WtKM9SQuCJqonJg==","repository":{"url":"git+https://github.com/clc-blind/hast-util-from-daisy.git","type":"git"},"_npmVersion":"11.6.0","description":"hast utility to transform DAISY v3 documents to semantic HTML with metadata preservation","directories":{},"_nodeVersion":"24.8.0","dependencies":{"xast-util-from-xml":"4.0.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.5.0","husky":"9.1.7","eslint":"8.57.1","vitest":"3.2.4","prettier":"3.6.2","@vitest/ui":"3.2.4","typescript":"5.9.2","@babel/core":"7.28.4","@types/hast":"3.0.4","@types/node":"22.18.0","@types/xast":"2.0.4","lint-staged":"16.1.6","@commitlint/cli":"19.8.1","@types/showdown":"2.0.6","eslint-plugin-import":"2.31.0","@arethetypeswrong/cli":"0.18.2","eslint-config-prettier":"9.1.0","eslint-plugin-prettier":"5.2.1","@typescript-eslint/parser":"8.17.0","eslint-config-airbnb-base":"15.0.0","@commitlint/config-conventional":"19.8.1","@typescript-eslint/eslint-plugin":"8.17.0","eslint-import-resolver-typescript":"3.7.0"},"_npmOperationalInternal":{"tmp":"tmp/hast-util-from-daisy_1.0.1_1758075103796_0.4427571924982674","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@clc-blind/hast-util-from-daisy","version":"1.0.2","author":{"name":"clc-blind"},"description":"hast utility to transform DAISY v3 documents to semantic HTML with metadata preservation","repository":{"type":"git","url":"git+https://github.com/clc-blind/hast-util-from-daisy.git"},"type":"module","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{"./package.json":"./package.json",".":{"import":"./dist/index.js","default":"./dist/index.cjs"}},"dependencies":{"xast-util-from-xml":"4.0.0"},"devDependencies":{"@arethetypeswrong/cli":"0.18.2","@babel/core":"7.28.4","@commitlint/cli":"19.8.1","@commitlint/config-conventional":"19.8.1","@types/hast":"3.0.4","@types/node":"22.18.0","@types/showdown":"2.0.6","@types/xast":"2.0.4","@typescript-eslint/eslint-plugin":"8.17.0","@typescript-eslint/parser":"8.17.0","@vitest/ui":"3.2.4","eslint":"8.57.1","eslint-config-airbnb-base":"15.0.0","eslint-config-prettier":"9.1.0","eslint-import-resolver-typescript":"3.7.0","eslint-plugin-import":"2.31.0","eslint-plugin-prettier":"5.2.1","husky":"9.1.7","lint-staged":"16.1.6","prettier":"3.6.2","tsup":"8.5.0","typescript":"5.9.2","vitest":"3.2.4"},"scripts":{"lint":"tsc","build":"tsup","test":"vitest run","check-exports":"attw --pack . --ignore-rules=cjs-resolves-to-esm","prepublish":"pnpm run build && pnpm run check-exports && pnpm run lint"},"_id":"@clc-blind/hast-util-from-daisy@1.0.2","bugs":{"url":"https://github.com/clc-blind/hast-util-from-daisy/issues"},"homepage":"https://github.com/clc-blind/hast-util-from-daisy#readme","_integrity":"sha512-H9i3yL9HlsAh8EKeyqx7SLTKIedr+1zg8yKuqimo4Ck//XUtAObTv2ntBAE4mOa0CmBq5mCrbGHe+tlxPozFNQ==","_resolved":"/tmp/f4f6afe9337bdd6a115a5487cee15350/clc-blind-hast-util-from-daisy-1.0.2.tgz","_from":"file:clc-blind-hast-util-from-daisy-1.0.2.tgz","_nodeVersion":"24.9.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-H9i3yL9HlsAh8EKeyqx7SLTKIedr+1zg8yKuqimo4Ck//XUtAObTv2ntBAE4mOa0CmBq5mCrbGHe+tlxPozFNQ==","shasum":"0d2af2c03133774f3293b4ffb5d7c9e1db56aecf","tarball":"https://registry.npmjs.org/@clc-blind/hast-util-from-daisy/-/hast-util-from-daisy-1.0.2.tgz","fileCount":9,"unpackedSize":117149,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHBR90LEH2zwQ+pVwqDjdiyp+cUdK2kglojzk5ch1DQBAiAW51YZYJlTUX1BlvG0ardRe2PFsliHGpYGbeTVwdetJg=="}]},"_npmUser":{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"},"directories":{},"maintainers":[{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hast-util-from-daisy_1.0.2_1758890211581_0.35489363889601155"},"_hasShrinkwrap":false}},"time":{"created":"2025-09-15T16:24:54.763Z","modified":"2025-09-26T12:36:52.024Z","1.0.0":"2025-09-15T16:24:55.040Z","1.0.1":"2025-09-17T02:11:43.990Z","1.0.2":"2025-09-26T12:36:51.822Z"},"bugs":{"url":"https://github.com/clc-blind/hast-util-from-daisy/issues"},"author":{"name":"clc-blind"},"homepage":"https://github.com/clc-blind/hast-util-from-daisy#readme","repository":{"type":"git","url":"git+https://github.com/clc-blind/hast-util-from-daisy.git"},"description":"hast utility to transform DAISY v3 documents to semantic HTML with metadata preservation","maintainers":[{"name":"duckymomo20012","email":"tienvinh.duong4@gmail.com"}],"readme":"# hast-util-from-daisy\n\n[hast](https://github.com/syntax-tree/hast) utility to transform complete DAISY v3 XML documents to semantic HTML with metadata preservation.\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  - [`fromDaisyXml(xmlString[, options])`](#fromdaisyxmlxmlstring-options)\n  - [`fromDaisy(tree[, options])`](#fromdaisytree-options)\n  - [`fromDaisyClone(tree[, options])`](#fromdaisyclonetree-options)\n  - [`extractDaisyMetadata(tree)`](#extractdaisymetadatatree)\n  - [`isDaisyElement(tagName)`](#isdaisyelementtagname)\n  - [`getDaisyMapping(tagName)`](#getdaisymappingtagname)\n  - [`Options`](#options)\n- [Examples](#examples)\n  - [Complete DAISY document conversion](#complete-daisy-document-conversion)\n  - [Working with metadata](#working-with-metadata)\n  - [XAST tree conversion](#xast-tree-conversion)\n  - [Custom mappings](#custom-mappings)\n- [DAISY to HTML Mapping](#daisy-to-html-mapping)\n  - [Element Conversion Philosophy](#element-conversion-philosophy)\n  - [Document Structure Elements](#document-structure-elements)\n  - [Navigation and Hierarchy Elements](#navigation-and-hierarchy-elements)\n  - [Text Structure Elements](#text-structure-elements)\n  - [Notes and Annotations](#notes-and-annotations)\n  - [Specialized Content Elements](#specialized-content-elements)\n  - [List Elements](#list-elements)\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 utility that transforms complete DAISY v3 XML documents to semantic HTML elements in HAST (HTML AST), with full metadata preservation and comprehensive attribute handling. It intelligently converts DAISY-specific elements while preserving standard HTML elements as-is.\n\nThe utility handles the complete DAISY v3 specification including:\n\n- **Complete document parsing**: XML declaration, DOCTYPE, and full document structure\n- **Metadata extraction**: Preserves Dublin Core and DAISY-specific metadata from document head\n- **Element mapping**: Only converts DAISY-specific elements, leaving standard HTML unchanged\n- **Comprehensive attribute preservation**: Maintains 25+ standard HTML attributes (ARIA, IDs, classes, table attributes, form attributes, etc.)\n- **Attribute conversion**: DAISY-specific attributes automatically converted to `data-daisy-*` format\n- **Accessibility preservation**: Maintains semantic meaning and accessibility features throughout transformation\n\n## When should I use this?\n\nThis utility is ideal when you need to:\n\n- Convert complete DAISY v3 XML documents to web-ready HTML\n- Preserve document metadata alongside transformed content\n- Build accessibility-focused web applications from DAISY content\n- Transform DAISY audiobooks for web presentation while maintaining semantic structure\n- Create tools that bridge DAISY and modern web standards\n\nThis is particularly valuable for digital publishing platforms, educational technology, accessibility tools, and any application that needs to work with both DAISY and HTML content standards.\n\n## Install\n\nIn Node.js (version 16+), install with [npm](https://docs.npmjs.com/cli/install):\n\n```sh\nnpm install @clc-blind/hast-util-from-daisy\n```\n\nIn Deno with [esm.sh](https://esm.sh/):\n\n```js\nimport { fromDaisy } from 'https://esm.sh/@clc-blind/hast-util-from-daisy@1';\n```\n\nIn browsers with [esm.sh](https://esm.sh/):\n\n```html\n<script type=\"module\">\n  import { fromDaisy } from 'https://esm.sh/@clc-blind/hast-util-from-daisy@1?bundle';\n</script>\n```\n\n## Use\n\nSay we have the following complete DAISY v3 XML document `example.xml`:\n\n```xml\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE dtbook PUBLIC \"-//NISO//DTD dtbook 2005-1//EN\"\n  \"http://www.daisy.org/z3986/2005/dtbook-2005-1.dtd\">\n<dtbook version=\"2005-1\" xml:lang=\"en\" xmlns=\"http://www.daisy.org/z3986/2005/dtbook/\">\n  <head>\n    <meta name=\"dtb:uid\" content=\"example-123\" />\n    <meta name=\"dc:Title\" content=\"Example DAISY Book\" />\n    <meta name=\"dc:Creator\" content=\"Jane Doe\" />\n    <meta name=\"dtb:totalTime\" content=\"01:23:45\" />\n  </head>\n  <book>\n    <frontmatter>\n      <level1>\n        <hd>Table of Contents</hd>\n        <list type=\"ol\">\n          <li><a href=\"#ch1\">Chapter 1: Introduction</a></li>\n          <li><a href=\"#ch2\">Chapter 2: Methods</a></li>\n        </list>\n      </level1>\n    </frontmatter>\n    <bodymatter>\n      <level1 id=\"ch1\">\n        <pagenum id=\"page1\">1</pagenum>\n        <hd>Chapter 1: Introduction</hd>\n        <p>This is the <strong>introduction</strong> chapter with <em>emphasis</em>.</p>\n        <prodnote render=\"optional\">\n          This chapter contains technical diagrams.\n        </prodnote>\n      </level1>\n    </bodymatter>\n  </book>\n</dtbook>\n```\n\n…and our module `example.js` looks as follows:\n\n```js\nimport { fromDaisyXml } from '@clc-blind/hast-util-from-daisy';\nimport { toHtml } from 'hast-util-to-html';\nimport { readFileSync } from 'node:fs';\n\nconst xml = readFileSync('example.xml', 'utf8');\nconst { tree, metadata } = fromDaisyXml(xml);\n\nconsole.log('Metadata:', metadata);\nconsole.log('HTML:', toHtml(tree));\n```\n\n…then running `node example.js` yields:\n\n```js\n// Metadata output:\n{\n  'dtb:uid': 'example-123',\n  'dc:Title': 'Example DAISY Book',\n  'dc:Creator': 'Jane Doe',\n  'dtb:totalTime': '01:23:45'\n}\n```\n\n```html\n<!-- HTML output: -->\n<section data-daisy-type=\"frontmatter\">\n  <section data-daisy-type=\"level-1\">\n    <h1>Table of Contents</h1>\n    <ol>\n      <li><a href=\"#ch1\">Chapter 1: Introduction</a></li>\n      <li><a href=\"#ch2\">Chapter 2: Methods</a></li>\n    </ol>\n  </section>\n</section>\n<main data-daisy-type=\"bodymatter\">\n  <section data-daisy-type=\"level-1\" id=\"ch1\">\n    <span id=\"page1\" data-daisy-type=\"page-number\">1</span>\n    <h1>Chapter 1: Introduction</h1>\n    <p\n      >This is the <strong>introduction</strong> chapter with\n      <em>emphasis</em>.</p\n    >\n    <aside data-daisy-type=\"production-note\" data-daisy-render=\"optional\">\n      This chapter contains technical diagrams.\n    </aside>\n  </section>\n</main>\n```\n\n## API\n\nThis package exports the identifiers [`fromDaisyXml`](#fromdaisyxmlxmlstring-options), [`fromDaisy`](#fromdaisytree-options), [`fromDaisyClone`](#fromdaisyclonetree-options), [`extractDaisyMetadata`](#extractdaisymetadatatree), [`isDaisyElement`](#isdaisyelementtagname), and [`getDaisyMapping`](#getdaisymappingtagname).\nThere is no default export.\n\n### `fromDaisyXml(xmlString[, options])`\n\nConvert a complete DAISY v3 XML document string to HTML semantic elements in HAST with metadata extraction.\n\nThis is the **recommended approach** for working with complete DAISY documents.\n\n###### Parameters\n\n- `xmlString` (`string`) — Complete DAISY XML document as string\n- `options` ([`Options`](#options), optional) — configuration\n\n###### Returns\n\nObject with the following properties:\n\n- `tree` ([`Root`](https://github.com/syntax-tree/hast#root)) — the transformed HAST tree\n- `metadata` (`Record<string, string>`) — extracted metadata from the DAISY document\n\n###### Example\n\n```js\nimport { fromDaisyXml } from '@clc-blind/hast-util-from-daisy';\n\nconst daisyXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE dtbook PUBLIC \"-//NISO//DTD dtbook 2005-1//EN\"\n  \"http://www.daisy.org/z3986/2005/dtbook-2005-1.dtd\">\n<dtbook version=\"2005-1\" xml:lang=\"en\" xmlns=\"http://www.daisy.org/z3986/2005/dtbook/\">\n  <head>\n    <meta name=\"dtb:uid\" content=\"example-123\" />\n    <meta name=\"dc:Title\" content=\"Example Book\" />\n  </head>\n  <book>\n    <bodymatter>\n      <level1>\n        <hd>Chapter 1</hd>\n        <p>Content here</p>\n      </level1>\n    </bodymatter>\n  </book>\n</dtbook>`;\n\nconst { tree, metadata } = fromDaisyXml(daisyXml);\n\nconsole.log(metadata['dtb:uid']); // => 'example-123'\nconsole.log(metadata['dc:Title']); // => 'Example Book'\n// tree contains the transformed HAST tree\n```\n\n### `fromDaisy(tree[, options])`\n\nConvert DAISY elements to HTML semantic elements in a HAST tree.\n\nUse this when you already have an XAST tree (from `xast-util-from-xml`) and want to transform just the content portion.\n\n###### Parameters\n\n- `tree` ([`Root`](https://github.com/syntax-tree/xast#root)) — XAST tree to transform\n- `options` ([`Options`](#options), optional) — configuration\n\n###### Returns\n\nTransform result ([`Root`](https://github.com/syntax-tree/hast#root)).\n\n###### Example\n\n```js\nimport { fromXml } from 'xast-util-from-xml';\nimport { fromDaisy } from '@clc-blind/hast-util-from-daisy';\n\nconst xml = '<level1><hd>Chapter 1</hd><p>Content</p></level1>';\nconst xast = fromXml(xml);\nconst hast = fromDaisy(xast);\n\nconsole.log(hast);\n// {\n//   type: 'root',\n//   children: [{\n//     type: 'element',\n//     tagName: 'section',\n//     properties: {'data-daisy-type': 'level-1'},\n//     children: [\n//       {\n//         type: 'element',\n//         tagName: 'h1',\n//         properties: {},\n//         children: [{type: 'text', value: 'Chapter 1'}]\n//       },\n//       {\n//         type: 'element',\n//         tagName: 'p',\n//         properties: {},\n//         children: [{type: 'text', value: 'Content'}]\n//       }\n//     ]\n//   }]\n// }\n```\n\n### `fromDaisyClone(tree[, options])`\n\nConvert DAISY elements to HTML semantic elements in a cloned XAST tree (non-mutating version).\n\n###### Parameters\n\n- `tree` ([`Root`](https://github.com/syntax-tree/xast#root)) — XAST tree to transform (will not be modified)\n- `options` ([`Options`](#options), optional) — configuration\n\n###### Returns\n\nTransform result ([`Root`](https://github.com/syntax-tree/hast#root)).\n\nThis function deep clones the input tree before transformation, ensuring the original XAST remains unchanged.\n\n### `extractDaisyMetadata(tree)`\n\nExtract metadata from a DAISY XAST tree.\n\nUse this when you need to extract metadata from a DAISY document that's already been parsed to XAST.\n\n###### Parameters\n\n- `tree` ([`Root`](https://github.com/syntax-tree/xast#root)) — XAST tree to extract metadata from\n\n###### Returns\n\nMetadata as key-value pairs (`Record<string, string>`).\n\n###### Example\n\n```js\nimport { fromXml } from 'xast-util-from-xml';\nimport { extractDaisyMetadata } from '@clc-blind/hast-util-from-daisy';\n\nconst daisyXml = `<?xml version=\"1.0\"?>\n<dtbook xmlns=\"http://www.daisy.org/z3986/2005/dtbook/\">\n  <head>\n    <meta name=\"dtb:uid\" content=\"book-123\" />\n    <meta name=\"dc:Title\" content=\"My Book\" />\n    <meta name=\"dc:Creator\" content=\"Author Name\" />\n  </head>\n  <book>\n    <!-- content -->\n  </book>\n</dtbook>`;\n\nconst xast = fromXml(daisyXml);\nconst metadata = extractDaisyMetadata(xast);\n\nconsole.log(metadata);\n// {\n//   'dtb:uid': 'book-123',\n//   'dc:Title': 'My Book',\n//   'dc:Creator': 'Author Name'\n// }\n```\n\n### `isDaisyElement(tagName)`\n\nCheck if an element is a DAISY-specific element that needs conversion.\n\n###### Parameters\n\n- `tagName` (`string`) — element name to check\n\n###### Returns\n\nWhether the element is a DAISY element (`boolean`).\n\n###### Example\n\n```js\nimport { isDaisyElement } from '@clc-blind/hast-util-from-daisy';\n\nconsole.log(isDaisyElement('level1')); // => true\nconsole.log(isDaisyElement('prodnote')); // => true\nconsole.log(isDaisyElement('p')); // => false\n```\n\n### `getDaisyMapping(tagName)`\n\nGet the HTML equivalent tag name for a DAISY element.\n\n###### Parameters\n\n- `tagName` (`string`) — DAISY element name\n\n###### Returns\n\nHTML tag name (`string`) or `undefined` if not a DAISY element.\n\n###### Example\n\n```js\nimport { getDaisyMapping } from '@clc-blind/hast-util-from-daisy';\n\nconsole.log(getDaisyMapping('level1')); // => 'section'\nconsole.log(getDaisyMapping('prodnote')); // => 'aside'\nconsole.log(getDaisyMapping('hd')); // => 'h1'\n```\n\n### `Options`\n\nConfiguration for the transformation (TypeScript type).\n\n###### Fields\n\n- `preserveDataAttributes` (`boolean`, default: `false`) — whether to preserve data attributes from source\n- `customMappings` (`Record<string, DaisyElementMapping>`, optional) — custom element mappings to override defaults\n\nThe `DaisyElementMapping` type has these fields:\n\n- `tagName` (`string`) — target HTML element name\n- `dataType` (`string`, optional) — value for `data-daisy-type` attribute\n- `preserveAttributes` (`Array<string>`, optional) — attributes to preserve from source\n- `roleAttribute` (`string`, optional) — ARIA role to add\n\n###### Example\n\n```js\nimport { fromDaisy } from '@clc-blind/hast-util-from-daisy';\n\nconst options = {\n  customMappings: {\n    'special-element': {\n      tagName: 'article',\n      dataType: 'special',\n      preserveAttributes: ['id', 'class'],\n      roleAttribute: 'region',\n    },\n  },\n};\n\nconst result = fromDaisy(tree, options);\n```\n\n## Examples\n\n### Complete DAISY document conversion\n\nTransform a complete DAISY v3 XML document with metadata:\n\n```js\nimport { fromDaisyXml } from '@clc-blind/hast-util-from-daisy';\nimport { toHtml } from 'hast-util-to-html';\nimport { readFileSync } from 'node:fs';\n\nconst daisyXml = readFileSync('book.xml', 'utf8');\nconst { tree, metadata } = fromDaisyXml(daisyXml);\n\n// Access metadata\nconsole.log('Book ID:', metadata['dtb:uid']);\nconsole.log('Title:', metadata['dc:Title']);\nconsole.log('Author:', metadata['dc:Creator']);\nconsole.log('Duration:', metadata['dtb:totalTime']);\n\n// Convert to HTML\nconst html = toHtml(tree);\nconsole.log(html);\n```\n\n### Working with metadata\n\nExtract and use metadata separately:\n\n```js\nimport {\n  fromDaisyXml,\n  extractDaisyMetadata,\n} from '@clc-blind/hast-util-from-daisy';\nimport { fromXml } from 'xast-util-from-xml';\n\nconst daisyXml = `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE dtbook PUBLIC \"-//NISO//DTD dtbook 2005-1//EN\"\n  \"http://www.daisy.org/z3986/2005/dtbook-2005-1.dtd\">\n<dtbook xmlns=\"http://www.daisy.org/z3986/2005/dtbook/\">\n  <head>\n    <meta name=\"dtb:uid\" content=\"unique-book-id\" />\n    <meta name=\"dc:Title\" content=\"Advanced Topics\" />\n    <meta name=\"dc:Language\" content=\"en\" />\n    <meta name=\"dtb:totalTime\" content=\"02:15:30\" />\n  </head>\n  <book>\n    <bodymatter>\n      <level1>\n        <hd>Introduction</hd>\n        <p>Welcome to this comprehensive guide.</p>\n      </level1>\n    </bodymatter>\n  </book>\n</dtbook>`;\n\n// Method 1: Using fromDaisyXml (recommended for complete documents)\nconst { tree, metadata } = fromDaisyXml(daisyXml);\nconsole.log('Complete transformation:', {\n  metadata,\n  hasContent: tree.children.length > 0,\n});\n\n// Method 2: Extract metadata separately\nconst xast = fromXml(daisyXml);\nconst metadata = extractDaisyMetadata(xast);\nconsole.log('Metadata only:', metadata);\n```\n\n### XAST tree conversion\n\nWork with pre-parsed XAST trees:\n\n```js\nimport { fromXml } from 'xast-util-from-xml';\nimport { fromDaisy, fromDaisyClone } from '@clc-blind/hast-util-from-daisy';\n\nconst daisyFragment = `\n  <level1>\n    <hd>Chapter Title</hd>\n    <p>This is a <strong>paragraph</strong> with <pagenum>42</pagenum> content.</p>\n    <prodnote render=\"optional\">Producer note here.</prodnote>\n    <level2>\n      <hd>Subsection</hd>\n      <p>More content here.</p>\n    </level2>\n  </level1>\n`;\n\nconst xast = fromXml(daisyFragment);\n\n// Mutating conversion\nconst hast1 = fromDaisy(xast);\n\n// Non-mutating conversion (original xast preserved)\nconst hast2 = fromDaisyClone(xast);\n\nconsole.log(\n  'Both results are equivalent:',\n  JSON.stringify(hast1) === JSON.stringify(hast2),\n);\n```\n\n### Custom mappings\n\nOverride default mappings for specific elements:\n\n```js\nimport { fromDaisy } from '@clc-blind/hast-util-from-daisy';\n\nconst customMappings = {\n  // Convert custom DAISY elements\n  'special-note': {\n    tagName: 'aside',\n    dataType: 'special-note',\n    roleAttribute: 'note',\n  },\n  // Override default mapping for production notes\n  prodnote: {\n    tagName: 'div',\n    dataType: 'producer-note',\n    preserveAttributes: ['render', 'id'],\n  },\n};\n\nconst result = fromDaisy(xast, { customMappings });\n```\n\n## DAISY to HTML Mapping\n\nThis section provides a comprehensive reference for how DAISY v3 elements are\ntransformed to semantic HTML. The library follows a **smart conversion philosophy**:\nonly DAISY-specific elements are converted, while standard HTML elements are preserved as-is.\n\n### Element Conversion Philosophy\n\nThe transformation strategy prioritizes semantic preservation and web standards compliance:\n\n- **HTML elements preserved**: Standard HTML elements (`<p>`, `<div>`, `<span>`, `<strong>`, `<em>`, `<blockquote>`, `<table>`, etc.) are left unchanged\n- **DAISY elements converted**: Only DAISY-specific elements that don't exist in HTML are transformed\n- **Deprecated elements modernized**: Deprecated HTML elements like `<acronym>` are converted to modern equivalents (`<abbr>`)\n- **Comprehensive attribute handling**: Standard HTML attributes (25+ types) preserved, DAISY attributes converted to `data-daisy-*`\n- **Data attributes added**: DAISY-specific information is preserved via `data-daisy-*` attributes\n\n**Example of mixed content and attribute handling:**\n\n```xml\n<!-- Input DAISY with mixed attributes -->\n<level1>\n  <hd>Chapter Title</hd>\n  <p class=\"intro\" id=\"p1\" render=\"optional\">Regular <strong>HTML</strong> content.</p>\n  <blockquote cite=\"http://example.com\" render=\"required\" depth=\"2\">\n    Quote with mixed HTML and DAISY attributes.\n  </blockquote>\n  <pagenum page=\"special\">42</pagenum>\n  <prodnote render=\"optional\" smilref=\"audio.mp3\">DAISY-specific note</prodnote>\n</level1>\n```\n\n```html\n<!-- Output HTML with attribute handling -->\n<section data-daisy-type=\"level-1\">\n  <h1>Chapter Title</h1>\n  <!-- HTML attributes preserved, DAISY attributes converted -->\n  <p class=\"intro\" id=\"p1\" data-daisy-render=\"optional\"\n    >Regular <strong>HTML</strong> content.</p\n  >\n  <!-- Standard HTML cite preserved, DAISY attributes converted -->\n  <blockquote\n    cite=\"http://example.com\"\n    data-daisy-render=\"required\"\n    data-daisy-depth=\"2\"\n  >\n    Quote with mixed HTML and DAISY attributes.\n  </blockquote>\n  <!-- DAISY element converted with attributes -->\n  <span data-daisy-type=\"page-number\" data-daisy-page=\"special\">42</span>\n  <!-- DAISY element and attributes converted -->\n  <aside\n    data-daisy-type=\"production-note\"\n    data-daisy-render=\"optional\"\n    data-daisy-smilref=\"audio.mp3\"\n    >DAISY-specific note</aside\n  >\n</section>\n```\n\n### Document Structure Elements\n\n| DAISY Element   | HTML Mapping | Semantic Role          | Primary Attributes              | Rationale                                                       |\n| --------------- | ------------ | ---------------------- | ------------------------------- | --------------------------------------------------------------- |\n| `<dtbook>`      | `<main>`     | `role=\"document\"`      | `data-daisy-type=\"dtbook\"`      | Main represents primary content, role clarifies document nature |\n| `<book>`        | `<article>`  | Self-contained content | `data-daisy-type=\"book\"`        | Article represents complete, independent content                |\n| `<frontmatter>` | `<section>`  | Document section       | `data-daisy-type=\"frontmatter\"` | Section with semantic identifier maintains structure            |\n| `<bodymatter>`  | `<main>`     | Primary content        | `data-daisy-type=\"bodymatter\"`  | Main for primary content area                                   |\n| `<rearmatter>`  | `<section>`  | Document section       | `data-daisy-type=\"rearmatter\"`  | Section maintains document structure semantics                  |\n\n### Navigation and Hierarchy Elements\n\n| DAISY Element           | HTML Mapping     | Semantic Role          | Primary Attributes               | Implementation Notes                                  |\n| ----------------------- | ---------------- | ---------------------- | -------------------------------- | ----------------------------------------------------- |\n| `<level>`, `<level1-6>` | `<section>`      | Hierarchical sections  | `data-daisy-type=\"level-1\"` etc. | Section preserves hierarchy with level indication     |\n| `<hd>`                  | `<h1>` to `<h6>` | Heading based on level | Dynamic based on nesting         | Native HTML headings maintain accessibility hierarchy |\n| `<bridgehead>`          | `<h3>`           | Subheading             | `data-daisy-type=\"bridgehead\"`   | Consistent h3 for bridgeheads regardless of context   |\n| `<pagenum>`             | `<span>`         | Page marker            | `data-daisy-type=\"page-number\"`  | Span with data attributes for screen reader control   |\n\n### Document Metadata Elements\n\n| DAISY Element  | HTML Mapping | Semantic Role   | Primary Attributes                  | Usage Context          |\n| -------------- | ------------ | --------------- | ----------------------------------- | ---------------------- |\n| `<doctitle>`   | `<h1>`       | Document title  | `data-daisy-type=\"document-title\"`  | Main document title    |\n| `<docauthor>`  | `<div>`      | Document author | `data-daisy-type=\"document-author\"` | Document author info   |\n| `<covertitle>` | `<h2>`       | Cover title     | `data-daisy-type=\"cover-title\"`     | Cover/title page title |\n| `<author>`     | `<cite>`     | Author citation | `data-daisy-type=\"author\"`          | Author attribution     |\n\n### Text Structure Elements\n\n| DAISY Element | HTML Mapping | Semantic Role     | Primary Attributes            | Usage Context                      |\n| ------------- | ------------ | ----------------- | ----------------------------- | ---------------------------------- |\n| `<linegroup>` | `<div>`      | Text grouping     | `data-daisy-type=\"linegroup\"` | Poetry, drama, structured text     |\n| `<line>`      | `<span>`     | Text line         | `data-daisy-type=\"line\"`      | Individual lines within linegroup  |\n| `<linenum>`   | `<span>`     | Line numbering    | `data-daisy-type=\"linenum\"`   | Line numbers for reference         |\n| `<sent>`      | `<span>`     | Sentence boundary | `data-daisy-type=\"sentence\"`  | Sentence-level markup for TTS      |\n| `<w>`         | `<span>`     | Word boundary     | `data-daisy-type=\"word\"`      | Word-level markup for fine control |\n\n### Notes and Annotations\n\n| DAISY Element  | HTML Mapping | Semantic Role         | Primary Attributes                  | Accessibility Features                           |\n| -------------- | ------------ | --------------------- | ----------------------------------- | ------------------------------------------------ |\n| `<prodnote>`   | `<aside>`    | Supplementary content | `data-daisy-type=\"production-note\"` | Aside semantically represents producer notes     |\n| `<noteref>`    | `<a>`        | Note reference link   | `data-daisy-type=\"note-ref\"`        | Anchor maintains linking with enhanced semantics |\n| `<annoref>`    | `<a>`        | Annotation ref link   | `data-daisy-type=\"annotation-ref\"`  | Links to annotations with semantic marking       |\n| `<annotation>` | `<aside>`    | Annotation content    | `data-daisy-type=\"annotation\"`      | Aside for supplementary annotation content       |\n| `<note>`       | `<aside>`    | Note content          | `data-daisy-type=\"note\"`            | General note content as aside                    |\n\n### Specialized Content Elements\n\n| DAISY Element | HTML Mapping   | Semantic Role       | Primary Attributes           | Content Type                  |\n| ------------- | -------------- | ------------------- | ---------------------------- | ----------------------------- |\n| `<sidebar>`   | `<aside>`      | Sidebar content     | `data-daisy-type=\"sidebar\"`  | Tangential content            |\n| `<epigraph>`  | `<blockquote>` | Quotation           | `data-daisy-type=\"epigraph\"` | Opening quotations            |\n| `<poem>`      | `<article>`    | Self-contained poem | `data-daisy-type=\"poem\"`     | Poetic content                |\n| `<byline>`    | `<div>`        | Author attribution  | `data-daisy-type=\"byline\"`   | Author/byline information     |\n| `<dateline>`  | `<div>`        | Date information    | `data-daisy-type=\"dateline\"` | Date and location information |\n\n### List Elements\n\n| DAISY Element | HTML Mapping     | Semantic Role       | Primary Attributes                      | List Type Handling                     |\n| ------------- | ---------------- | ------------------- | --------------------------------------- | -------------------------------------- |\n| `<list>`      | `<ul>` or `<ol>` | List container      | Based on `type` attribute               | `type=\"ol\"` → `<ol>`, otherwise `<ul>` |\n| `<lic>`       | `<span>`         | List item component | `data-daisy-type=\"list-item-component\"` | Components within list items           |\n\n### Special Element Handling\n\n| DAISY Element | HTML Mapping | Conversion Rule                  | Rationale                               |\n| ------------- | ------------ | -------------------------------- | --------------------------------------- |\n| `<acronym>`   | `<abbr>`     | Converted with `data-daisy-type` | `<acronym>` is deprecated in HTML5      |\n| `<imggroup>`  | `<section>`  | Semantic section container       | Section better represents grouped media |\n\n### DAISY Attribute Conversion\n\nThe library intelligently handles attributes to ensure HTML validity while preserving DAISY semantics:\n\n#### Standard HTML Attributes (Preserved)\n\nThese attributes are preserved as-is on all elements since they are valid HTML:\n\n- **Global attributes**: `id`, `class`, `lang`, `dir`, `title`, `tabindex`, `accesskey`\n- **ARIA attributes**: `aria-*` (all ARIA attributes), `role`\n- **Data attributes**: `data-*` (existing data attributes)\n- **Link attributes**: `href`, `hreflang`, `rel`, `profile`, `target`\n- **Media attributes**: `src`, `alt`, `width`, `height`, `media`, `charset`\n- **Table attributes**: `colspan`, `rowspan`, `headers`, `scope`, `axis`, `cellpadding`, `cellspacing`, `frame`, `rules`, `summary`\n- **Layout attributes**: `align`, `valign`, `border`\n- **Form attributes**: `name`, `content`, `type`\n- **Meta attributes**: `http-equiv`, `cite`, `style`\n\n#### DAISY-Specific Attributes (Converted to data-daisy-\\*)\n\nThese attributes are converted to the `data-daisy-*` format to maintain DAISY semantics while ensuring HTML validity:\n\n- **Rendering control**: `render` → `data-daisy-render`\n- **Structure attributes**: `depth` → `data-daisy-depth`, `level` → `data-daisy-level`, `page` → `data-daisy-page`\n- **Media references**: `smilref` → `data-daisy-smilref`, `imgref` → `data-daisy-imgref`\n- **Pronunciation**: `pronounce` → `data-daisy-pronounce`\n- **Custom attributes**: Any other DAISY-specific attributes → `data-daisy-{attribute}`\n\n#### Examples\n\n```xml\n<!-- Input: HTML element with mixed attributes -->\n<p id=\"para1\" class=\"intro\" render=\"optional\" depth=\"2\">Content</p>\n<blockquote cite=\"http://example.com\" render=\"required\">Quote</blockquote>\n<div aria-label=\"Navigation\" custom-attr=\"value\">Menu</div>\n```\n\n```html\n<!-- Output: Attribute handling -->\n<p id=\"para1\" class=\"intro\" data-daisy-render=\"optional\" data-daisy-depth=\"2\"\n  >Content</p\n>\n<blockquote cite=\"http://example.com\" data-daisy-render=\"required\"\n  >Quote</blockquote\n>\n<div aria-label=\"Navigation\" data-daisy-custom-attr=\"value\">Menu</div>\n```\n\nThis approach ensures that:\n\n- **HTML validity** is maintained by using only standard HTML attributes\n- **DAISY semantics** are preserved through data attributes\n- **Accessibility** is enhanced by keeping ARIA attributes intact\n- **Styling and scripting** can target both HTML and DAISY-specific attributes\n\n### Preserved HTML Elements\n\nThe following elements are **not converted** and remain as standard HTML:\n\n**Text content**: `<p>`, `<div>`, `<span>`, `<blockquote>`, `<pre>`\n**Inline semantics**: `<strong>`, `<em>`, `<code>`, `<kbd>`, `<samp>`, `<cite>`, `<q>`, `<abbr>`, `<dfn>`, `<sub>`, `<sup>`, `<bdo>`\n**Lists**: `<ul>`, `<ol>`, `<li>`, `<dl>`, `<dt>`, `<dd>`\n**Tables**: `<table>`, `<thead>`, `<tbody>`, `<tfoot>`, `<tr>`, `<th>`, `<td>`, `<caption>`, `<col>`, `<colgroup>`\n**Media**: `<img>`, `<audio>`, `<video>`\n**Links**: `<a>`, `<link>`\n**Forms**: `<form>`, `<input>`, `<button>`, `<select>`, `<textarea>`, etc.\n**Sectioning**: `<section>`, `<article>`, `<aside>`, `<nav>`, `<header>`, `<footer>`, `<main>`\n**Headings**: `<h1>`, `<h2>`, `<h3>`, `<h4>`, `<h5>`, `<h6>`\n**Metadata**: `<head>`, `<title>`, `<meta>`, `<style>`, `<script>`\n\n> **Note**: The transformation preserves all original attributes from DAISY\n> elements while adding semantic HTML equivalents. Custom attributes are\n> converted to `data-daisy-*` format to maintain information while ensuring HTML\n> validity.\n\n## Types\n\nThis package is fully typed with [TypeScript](https://www.typescriptlang.org/).\nIt exports the additional types [`Options`](#options) and `DaisyElementMapping`.\n\n## Compatibility\n\nProjects maintained by the unified collective are compatible with maintained\nversions of Node.js.\n\nThis package is compatible with Node.js 16+.\nIt works with `xast-util-from-xml` version 4+, and integrates well with the\nbroader unified ecosystem including `rehype` and `hast-util-*` packages.\n\nThe library provides comprehensive DAISY v3 specification compliance with full\nelement and attribute mapping, ensuring robust transformation of DAISY audiobook\ncontent to modern HTML5 standards.\n\n## Security\n\nThis utility processes XML content and generates HTML. When working with\nuntrusted content, consider using appropriate sanitization tools like\n[`hast-util-sanitize`](https://github.com/syntax-tree/hast-util-sanitize) on the\noutput.\n\nThe transformation preserves most attributes and content from the source DAISY\ndocument, including IDs and classes, which could potentially be used for DOM\nclobbering attacks if not properly sanitized.\n\n## Related\n\n- [`xast-util-from-xml`](https://github.com/syntax-tree/xast-util-from-xml) —\n  parse XML to xast\n- [`hast-util-to-html`](https://github.com/syntax-tree/hast-util-to-html) —\n  serialize hast to HTML\n- [`hast-util-sanitize`](https://github.com/syntax-tree/hast-util-sanitize) —\n  sanitize hast\n- [`rehype`](https://github.com/rehypejs/rehype) — HTML processor powered by plugins\n- [`unified`](https://github.com/unifiedjs/unified) — interface for parsing,\n  inspecting, transforming, and serializing content through syntax trees\n\n## Contribute\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) in\n[`clc-blind/hast-util-from-daisy`](https://github.com/clc-blind/hast-util-from-daisy)\nfor ways to get started.\nSee [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) for how to interact with this project.\n\n## License\n\n[MIT](LICENSE.md) © [clc-blind](https://github.com/clc-blind)\n","readmeFilename":"README.md"}