[
  {
    "path": ".changeset/README.md",
    "content": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works\nwith multi-package repos, or single-package repos to help you version and publish your code. You can\nfind the full documentation for it [in our repository](https://github.com/changesets/changesets)\n\nWe have a quick list of common questions to get you started engaging with this project in\n[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)\n"
  },
  {
    "path": ".changeset/config.json",
    "content": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@1.6.0/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \"commit\": false,\n  \"linked\": [],\n  \"access\": \"public\",\n  \"baseBranch\": \"main\",\n  \"updateInternalDependencies\": \"patch\",\n  \"ignore\": []\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nindent_style = tab\n\n[*.{yml,yaml}]\nindent_style = space\nindent_size = 2\n\n[vcbuild.bat]\nend_of_line = crlf\n\n[Makefile]\nindent_style = tab\nindent_size = 8\n\n[{deps}/**]\nindent_style = ignore\nindent_size = ignore\nend_of_line = ignore\ntrim_trailing_whitespace = ignore\ncharset = ignore\n\n[{test/fixtures,deps,tools/node_modules,tools/gyp,tools/icu,tools/msvs}/**]\ninsert_final_newline = false\n"
  },
  {
    "path": ".eslintignore",
    "content": "node_modules\n**/dist/**\n**/__tests__/**/*.json\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: ['xiaoxinghu']\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: CI\n\non:\n  push:\n    branches:\n      - main\n    paths-ignore:\n      - 'docs/**'\n      - '**/README.org'\n      - '**/README.md'\n  pull_request:\n    paths-ignore:\n      - 'docs/**'\n      - '**/README.org'\n      - '**/README.md'\n\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Use Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 24\n      - uses: pnpm/action-setup@v4\n        with:\n          version: 10\n          cache: 'pnpm'\n      - name: install dependencies\n        run: pnpm install\n      - name: build packages\n        run: pnpm build\n      - name: run unit tests\n        run: pnpm test\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Release\n\non:\n  push:\n    branches:\n      - main\n\nenv:\n  CI: true\n\npermissions: {}\n\njobs:\n  release:\n    name: Release\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write      # Required for OIDC trusted publishing\n      contents: write      # Required for changesets to commit\n      pull-requests: write # Required for changesets to create PRs\n    steps:\n      - name: Checkout Repo\n        uses: actions/checkout@v4\n        with:\n          # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits\n          fetch-depth: 0\n\n      - name: Setup Node.js 24\n        uses: actions/setup-node@v4\n        with:\n          node-version: 24\n\n      - uses: pnpm/action-setup@v4\n        with:\n          version: 10\n      - name: install dependencies\n        run: pnpm install --no-frozen-lockfile\n      - name: Create Release Pull Request or Publish to npm\n        uses: changesets/action@v1\n        with:\n          version: pnpm ci:version\n          commit: 'chore: update versions'\n          title: 'chore: update versions'\n          publish: pnpm ci:publish\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          NPM_CONFIG_PROVENANCE: true\n"
  },
  {
    "path": ".github/workflows/website.yml",
    "content": "name: Deploy to GitHub Pages\n\non:\n  # Trigger the workflow every time you push to the `main` branch\n  # Using a different branch name? Replace `main` with your branch’s name\n  push:\n    branches: [main]\n  # Allows you to run this workflow manually from the Actions tab on GitHub.\n  workflow_dispatch:\n\n# Allow this job to clone the repo and create a page deployment\npermissions:\n  contents: read\n  pages: write\n  id-token: write\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout your repository using git\n        uses: actions/checkout@v3\n\n      - name: Setup PNPM\n        uses: pnpm/action-setup@v4\n        with:\n          version: 10\n\n      - name: Setup Node.js\n        uses: actions/setup-node@v4\n        with:\n          node-version: 20\n          cache: pnpm\n          cache-dependency-path: pnpm-lock.yaml\n\n      - name: Install\n        run: |\n          pnpm install\n          pnpm run build\n          pnpm run docs\n\n      - name: Upload Page Artifact\n        uses: actions/upload-pages-artifact@v3\n        with:\n          path: '.out/'\n\n  deploy:\n    needs: build\n    # Grant GITHUB_TOKEN the permissions required to make a Pages deployment\n    permissions:\n      pages: write # to deploy to Pages\n      id-token: write # to verify the deployment originates from an appropriate source\n    environment:\n      name: github-pages\n      url: ${{ steps.deployment.outputs.page_url }}\n    runs-on: ubuntu-latest\n    steps:\n      - name: Deploy to GitHub Pages\n        id: deployment\n        uses: actions/deploy-pages@v4\n"
  },
  {
    "path": ".gitignore",
    "content": "# macOS\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# next.js build output\n.next\n\n.npmrc\n\n# private\n.archive\n\n/.idea\n.vscode\n\n# build artifacts\ndist\n*.tsbuildinfo\n\n*.d.ts\n*.d.ts.map\n!packages/reorg-parse/index.d.ts\n!packages/loader/index.d.ts\n!packages/orga-build/lib/content.d.ts\n\n.meta.json\n.orga-build\n\n.turbo\n.aider*\n\n.out\n\n.direnv\n.website\ndeprecated\n"
  },
  {
    "path": ".prettierignore",
    "content": ".archive\n.cache\nnode_modules\n.next\npublic\nlib\n**/dist/**\n.yarn/*\n**/__tests__/**/*.json\n"
  },
  {
    "path": ".prettierrc",
    "content": "{\n\t\"singleQuote\": true,\n\t\"semi\": false,\n\t\"trailingComma\": \"none\",\n\t\"bracketSpacing\": true,\n\t\"useTabs\": true\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n- feat!: major version bump ([998c0f3](https://github.com/orgapp/orgajs/commit/998c0f30a7c8f9af27243b3cb48b650708cdc4b3))\n\n### Bug Fixes\n\n- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))\n- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))\n- fix headline tags parsing issue [#126](https://github.com/orgapp/orgajs/issues/126) ([71d7f82](https://github.com/orgapp/orgajs/commit/71d7f8277708fc72d3b5be01ed0f72233bf7057b))\n- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))\n- fix publish script ([7fc1bdf](https://github.com/orgapp/orgajs/commit/7fc1bdfc6880e825cd10d99d108da9685f58638c))\n- fix publish script ([f175e5b](https://github.com/orgapp/orgajs/commit/f175e5bb3cad0ce31cc118c1c675fe30b4065fc9))\n- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n- update yarn.lock file ([bf0e695](https://github.com/orgapp/orgajs/commit/bf0e6954246f7ed78a014601aca756cd47fa4fec))\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))\n- **gatsby:** process images ([76fdade](https://github.com/orgapp/orgajs/commit/76fdaded0d87a3bc2e188392b520f62ad789598c))\n\n### BREAKING CHANGES\n\n- due to my own lack of knowledge about how conventional commits works in\n  lerna, I published the breaking change as a minor version 2.5.0. Here I am\n  trying to get it right. It might not work... Sorry for the inconvenience.\n\n## 2.4.9 (2021-07-13)\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))\n- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))\n- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))\n- fix publish script ([7fc1bdf](https://github.com/orgapp/orgajs/commit/7fc1bdfc6880e825cd10d99d108da9685f58638c))\n- fix publish script ([f175e5b](https://github.com/orgapp/orgajs/commit/f175e5bb3cad0ce31cc118c1c675fe30b4065fc9))\n- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n- update yarn.lock file ([bf0e695](https://github.com/orgapp/orgajs/commit/bf0e6954246f7ed78a014601aca756cd47fa4fec))\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))\n- **gatsby:** process images ([76fdade](https://github.com/orgapp/orgajs/commit/76fdaded0d87a3bc2e188392b520f62ad789598c))\n- **gatsby-plugin-orga:** better code block ([e6d7d20](https://github.com/orgapp/orgajs/commit/e6d7d20f63fa1871d8f53b0534b50ac6d7d99fc9))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package orgajs\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n## 2.4.6 (2021-04-25)\n\n**Note:** Version bump only for package orgajs\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package orgajs\n"
  },
  {
    "path": "CONTRIBUTING.org",
    "content": "#+title: How to contribute to orgajs\n\nHi 👋 🦄.\n\n* Getting Started\nMake sure you have latest yarn installed locally.\nTo get started with the repo, after cloning the repo.\n\n#+begin_src sh\nyarn install\n#+end_src\n\n* Ways to Contribute\n\n** Improve documentation\nDocumentations resides in the [[file:docs][docs]] folder. The content will be published to the [[https://orga.js.org][official website]]. As a user of the library and tools, you are the best person for writing them. Any help with documentation would be appreciated greatly.\n\n** Write code and tests\nIt's often a good idea to create an issue to discuss the bug or feature before creating a pull request to prevent from doing unnecessary work.\n\n** Discussion\nHave some cool ideas? Let's talk about it in the [[https://github.com/orgapp/orgajs/discussions][Discussions]] tab.\n\n* Commit Messages\n\nWe are following the [[https://www.conventionalcommits.org/en/v1.0.0/][conventional commits]] standards, an example would be:\n\n#+begin_example\nfeat(parser): add new syntax\n\nthis is a body\n#+end_example\n\nThe above commit message would result in a minor version bump when it is merged into master for release. Take a look at the spec for more details. This is for extracting changelog and streamline version bump automatically.\n\n* Run Unit Tests\n\n#+begin_src sh\nyarn build # always build before running tests\nyarn test\n#+end_src\n\n* Submitting Pull Requests\nPlease submit pull requests against =develop= branch. =master= is for releasing.\n\n* Releasing\nAll packages in orgajs is automatically released once merged into master. That's why the commit message is extra important. Especially when there are =BRAKING CHANGE=.\n\n"
  },
  {
    "path": "LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "README.org",
    "content": "#+title: Orga\n#+subtitle: org-mode < JavaScript\n\n* What Is It\n\n=Orga= is a flexible org-mode syntax parser. It parses org content into AST ([[https://en.wikipedia.org/wiki/Abstract_syntax_tree][Abstract Syntax Tree 🌲]]). And it's written in JavaScript.\n\n* Why\norg-mode is simply a superior format than other more popular ones, but it's mostly trapped inside of emacs. It's so good that it was the #1 reason to learn and use emacs for a lot of people (me included). But it's too good to not share with the rest of the world. If it can run in JavaScript, it can run on anything.\n\n* Compatible Eco-systems\nIt integrates natively with popular tools.\n\n** [[https://unifiedjs.com][Unified]]\n\n#+BEGIN_QUOTE\n☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees\n#+END_QUOTE\n\nThe =orga= parser is completely compatible with unified. Which means you get to take advantage of the works of others put into the pipeline. [[https://github.com/retextjs/retext][linting for natural language]], [[https://alexjs.com][correct your writing]], [[https://wooorm.com/write-music/][write music]]? etc. Here is [[https://github.com/orgapp/orgajs/tree/develop/examples/getting-started][an example]].\n\n** [[https://webpack.js.org][Webpack]]\n=@orgajs/loader= is a webpack loader that made orga native citizen of webpack ecosystem. Coupled with plugins, it works smoothly. Take a look at [[https://github.com/orgapp/orgajs/tree/develop/examples/webpack][the example project]].\n\n\n** [[https://reactjs.org/][React]]\n#+begin_quote\nA JavaScript library for building user interfaces\n#+end_quote\n\nYou can render react components directly in your org file. Something like this:\n#+begin_src org\n,* Hello World\n\nLet's render *the box*.\n\n,#+begin_export jsx\n<div style={{\n  backgroundColor: 'gold',\n  padding: '1em',\n  border: '1px solid black',\n  boxShadow: '5px 5px'\n}}>I am a box with shadow</div>\n,#+end_export\n#+end_src\n\n[[https://orga.js.org/playground/?text=*%20Hello%20World%0A%0ALet's%20render%20*the%20box*.%0A%0A%23%2Bbegin_export%20jsx%0A%3Cdiv%20style%3D%7B%7B%0A%20%20backgroundColor%3A%20'gold'%2C%20%0A%20%20padding%3A%20'1em'%2C%0A%20%20border%3A%20'1px%20solid%20black'%2C%0A%20%20boxShadow%3A%20'5px%205px'%0A%7D%7D%3EI%20am%20a%20box%20with%20shadow%3C%2Fdiv%3E%0A%23%2Bend_export%0A][Try it our yourself in the playground]].\n\n** [[https://vitejs.dev][Vite]]\n#+begin_quote\nNext generation frontend tooling\n#+end_quote\n\n=@orgajs/rollup= is a plugin compatible with both Rollup and Vite. It lets you import =.org= files directly in your project.\n\n- Package: =@orgajs/rollup=\n\n** [[https://astro.build][Astro]]\n#+begin_quote\nThe web framework for content-driven websites\n#+end_quote\n\nAstro integration is maintained in a standalone repository.\n\n- [[https://github.com/orgapp/orga-astro][orga-astro repository]]\n- Package: =@orgajs/astro=\n\n** [[https://nextjs.org][Nextjs]]\n#+begin_quote\nThe React Framework\n#+end_quote\n\nNext.js integration is maintained in a standalone repository.\n\n- [[https://github.com/orgapp/orga-next][orga-next repository]]\n- Package: =@orgajs/next=\n- Guide: [[https://orga.js.org/guides/next][Next.js integration guide]]\n\n\n* Examples\nTake a look at the [[https://github.com/orgapp/orgajs/tree/main/examples][collection of examples]] to quickly get started.\n\n* Contribute\n\nSee the [[file:CONTRIBUTING.org][contributing file]] for ways to get started.\n"
  },
  {
    "path": "biome.json",
    "content": "{\n\t\"$schema\": \"https://biomejs.dev/schemas/2.4.4/schema.json\",\n\t\"files\": {\n\t\t\"includes\": [\"packages/**\", \"!packages/**/__tests__/**/*.json\"]\n\t},\n\t\"vcs\": {\n\t\t\"enabled\": true,\n\t\t\"clientKind\": \"git\",\n\t\t\"useIgnoreFile\": true\n\t},\n\t\"formatter\": {\n\t\t\"indentStyle\": \"tab\",\n\t\t\"bracketSpacing\": true\n\t},\n\t\"javascript\": {\n\t\t\"formatter\": {\n\t\t\t\"quoteStyle\": \"single\",\n\t\t\t\"semicolons\": \"asNeeded\",\n\t\t\t\"trailingCommas\": \"none\"\n\t\t}\n\t},\n\t\"linter\": {\n\t\t\"rules\": {\n\t\t\t\"complexity\": {\n\t\t\t\t\"useArrowFunction\": \"off\"\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "docs/.gitignore",
    "content": "out\n"
  },
  {
    "path": "docs/_components.tsx",
    "content": "import { Editor } from '@orgajs/react-editor'\nimport { ReactCodeMirror } from '@orgajs/react-cm'\nimport { tags as t } from '@lezer/highlight'\nimport { EditorView } from '@codemirror/view'\nimport {\n\tHighlightStyle,\n\tdefaultHighlightStyle,\n\tsyntaxHighlighting,\n\tfoldGutter\n} from '@codemirror/language'\nimport { javascript } from '@codemirror/lang-javascript'\n\nexport function Notice({\n\ttitle,\n\tchildren\n}: {\n\ttitle?: string\n\tchildren: React.ReactNode\n}) {\n\treturn (\n\t\t<div role=\"alert\" className=\"alert\">\n\t\t\t<svg\n\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\tfill=\"none\"\n\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\tclassName=\"stroke-info h-6 w-6 shrink-0\"\n\t\t\t>\n\t\t\t\t<path\n\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\td=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n\t\t\t\t></path>\n\t\t\t</svg>\n\t\t\t<span>{children}</span>\n\t\t</div>\n\t)\n}\n\nconst nord0 = '#2E3440',\n\tnord1 = '#3B4252',\n\tnord2 = '#434C5E',\n\tnord3 = '#4C566A',\n\tnord4 = '#D8DEE9',\n\tnord5 = '#E5E9F0',\n\tnord6 = '#ECEFF4',\n\tnord7 = '#8FBCBB',\n\tnord8 = '#88C0D0',\n\tnord9 = '#81A1C1',\n\tnord10 = '#5E81AC',\n\tnord11 = '#BF616A',\n\tnord12 = '#D08770',\n\tnord13 = '#EBCB8B',\n\tnord14 = '#A3BE8C',\n\tnord15 = '#B48EAD'\n\nconst nordTheme = EditorView.theme(\n\t{\n\t\t'&': {\n\t\t\tcolor: nord4,\n\t\t\tbackgroundColor: nord0\n\t\t},\n\t\t'.cm-content': {\n\t\t\tcaretColor: nord4\n\t\t},\n\t\t'.cm-cursor, .cm-dropCursor': { borderLeftColor: nord4 },\n\t\t'&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':\n\t\t\t{\n\t\t\t\tbackgroundColor: nord2\n\t\t\t},\n\t\t'.cm-panels': { backgroundColor: nord1, color: nord5 },\n\t\t'.cm-panels.cm-panels-top': { borderBottom: `2px solid ${nord3}` },\n\t\t'.cm-panels.cm-panels-bottom': { borderTop: `2px solid ${nord3}` },\n\t\t'.cm-searchMatch': {\n\t\t\tbackgroundColor: nord13,\n\t\t\toutline: `1px solid ${nord3}`\n\t\t},\n\t\t'.cm-searchMatch.cm-searchMatch-selected': {\n\t\t\tbackgroundColor: nord12\n\t\t},\n\t\t'.cm-activeLine': { backgroundColor: nord1 },\n\t\t'.cm-activeLineGutter': { backgroundColor: nord2 },\n\t\t'.cm-selectionMatch': { backgroundColor: nord3 },\n\t\t'.cm-matchingBracket, .cm-nonmatchingBracket': {\n\t\t\tbackgroundColor: nord8,\n\t\t\toutline: `none`\n\t\t},\n\t\t'.cm-gutters': {\n\t\t\tbackgroundColor: nord0,\n\t\t\tcolor: nord3,\n\t\t\tborder: 'none'\n\t\t},\n\t\t'.cm-lineNumbers .cm-gutterElement': {\n\t\t\tpadding: '0 3px 0 5px'\n\t\t},\n\t\t'.cm-tooltip': {\n\t\t\tborder: `1px solid ${nord3}`,\n\t\t\tbackgroundColor: nord2\n\t\t},\n\t\t'.cm-tooltip-autocomplete': {\n\t\t\t'& > ul > li[aria-selected]': {\n\t\t\t\tbackgroundColor: nord3,\n\t\t\t\tcolor: nord6\n\t\t\t}\n\t\t}\n\t},\n\t{ dark: true }\n)\n\nconst nordHighlightStyle = HighlightStyle.define([\n\t{ tag: t.keyword, color: nord9 },\n\t{\n\t\ttag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],\n\t\tcolor: nord4\n\t},\n\t{ tag: [t.function(t.variableName), t.labelName], color: nord8 },\n\t{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: nord7 },\n\t{ tag: [t.definition(t.name), t.separator], color: nord4 },\n\t{ tag: [t.className], color: nord7 },\n\t{\n\t\ttag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],\n\t\tcolor: nord15\n\t},\n\t{ tag: [t.typeName], color: nord7 },\n\t{ tag: [t.operator, t.operatorKeyword], color: nord9 },\n\t{ tag: [t.url, t.escape, t.regexp, t.link], color: nord13 },\n\t{ tag: [t.meta, t.comment], color: nord3, fontStyle: 'italic' },\n\t{ tag: [t.strong], fontWeight: 'bold' },\n\t{ tag: [t.emphasis], fontStyle: 'italic' },\n\t{ tag: [t.strikethrough], textDecoration: 'line-through' },\n\t{ tag: [t.string], color: nord14 },\n\t{ tag: [t.invalid], color: nord11 }\n])\n\nconst nord = [nordTheme, syntaxHighlighting(nordHighlightStyle)]\n\nexport function JSEditor({\n\tclassName,\n\tchildren\n}: {\n\tclassName?: string\n\tchildren: string\n}) {\n\treturn (\n\t\t<div className={className}>\n\t\t\t<ReactCodeMirror\n\t\t\t\textensions={[\n\t\t\t\t\tfoldGutter(),\n\t\t\t\t\tsyntaxHighlighting(defaultHighlightStyle, { fallback: true }),\n\t\t\t\t\tjavascript(),\n\t\t\t\t\tEditorView.editable.of(false),\n\t\t\t\t\tnord\n\t\t\t\t]}\n\t\t\t\tcontent={children}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n\nexport function OrgEditor({ className = '', content, onChange }) {\n\treturn (\n\t\t<Editor\n\t\t\tclassName={className}\n\t\t\tcontent={content}\n\t\t\tonChange={onChange}\n\t\t\textensions={[nord]}\n\t\t/>\n\t)\n}\n"
  },
  {
    "path": "docs/_layout.tsx",
    "content": "import { ReactNode } from 'react'\nimport { Link } from 'orga-build/components'\n\nimport type { SVGProps } from 'react'\nconst GitHub = (props: SVGProps<SVGSVGElement>) => (\n\t<svg\n\t\twidth=\"1em\"\n\t\theight=\"1em\"\n\t\tviewBox=\"0 0 1024 1024\"\n\t\tfill=\"none\"\n\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t{...props}\n\t>\n\t\t<path\n\t\t\tfillRule=\"evenodd\"\n\t\t\tclipRule=\"evenodd\"\n\t\t\td=\"M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z\"\n\t\t\ttransform=\"scale(64)\"\n\t\t\tfill=\"#1B1F23\"\n\t\t/>\n\t</svg>\n)\n\ninterface LayoutProps {\n\ttitle: string\n\tchildren: ReactNode\n}\n\nconst navItems = [\n\t{ name: 'Orga', href: '/' },\n\t{ name: 'Documents', href: '/guides' },\n\t{ name: 'Playground', href: '/playground' }\n]\n\nexport default function Layout({ children }: LayoutProps) {\n\treturn (\n\t\t<>\n\t\t\t<nav className=\"navbar bg-base-200 shadow-sm\">\n\t\t\t\t<ol className=\"flex flex-1 gap-4\">\n\t\t\t\t\t{navItems.map((item) => (\n\t\t\t\t\t\t<li key={item.name}>\n\t\t\t\t\t\t\t<Link href={item.href} className=\"btn btn-ghost\">\n\t\t\t\t\t\t\t\t{item.name}\n\t\t\t\t\t\t\t</Link>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t))}\n\t\t\t\t</ol>\n\t\t\t\t<div className=\"navbar-end\">\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName=\"btn btn-ghost btn-circle\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\thref=\"https://github.com/orgapp/orgajs\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<div className=\"indicator\">\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\twidth=\"24\"\n\t\t\t\t\t\t\t\theight=\"24\"\n\t\t\t\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\t\t\t\tstrokeWidth=\"2\"\n\t\t\t\t\t\t\t\tstrokeLinecap=\"round\"\n\t\t\t\t\t\t\t\tstrokeLinejoin=\"round\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\" />\n\t\t\t\t\t\t\t\t<path d=\"M9 19c-4.3 1.4 -4.3 -2.5 -6 -3m12 5v-3.5c0 -1 .1 -1.4 -.5 -2c2.8 -.3 5.5 -1.4 5.5 -6a4.6 4.6 0 0 0 -1.3 -3.2a4.2 4.2 0 0 0 -.1 -3.2s-1.1 -.3 -3.5 1.3a12.3 12.3 0 0 0 -6.2 0c-2.4 -1.6 -3.5 -1.3 -3.5 -1.3a4.2 4.2 0 0 0 -.1 3.2a4.6 4.6 0 0 0 -1.3 3.2c0 4.6 2.7 5.7 5.5 6c-.6 .6 -.6 1.2 -.5 2v3.5\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</a>\n\t\t\t\t</div>\n\t\t\t</nav>\n\t\t\t<main className=\"flex-grow flex-row overflow-hidden\">{children}</main>\n\t\t\t<footer className=\"footer sm:footer-horizontal footer-center bg-base-200 text-base-content p-4\">\n\t\t\t\t<aside>\n\t\t\t\t\t<p>Copyright © {new Date().getFullYear()} - All right reserved</p>\n\t\t\t\t</aside>\n\t\t\t</footer>\n\t\t\t{/* Client-side JS is now added by build process */}\n\t\t</>\n\t)\n}\n\ntype Page = {\n\tslug: string\n\ttitle: string\n\tposition: number\n\ttype: string\n}\n\nfunction findParentSlug(slug: string, pages: Page[]): string | null {\n\tconst parts = slug.split('/').filter(Boolean)\n\twhile (parts.length > 0) {\n\t\tparts.pop()\n\t\tconst parentSlug = '/' + parts.join('/')\n\t\tif (pages.some((p) => p.slug === parentSlug)) return parentSlug\n\t}\n\treturn null\n}\n\nfunction renderMenu(path: string, pages: Page[]) {\n\tconst children = pages\n\t\t.filter(\n\t\t\t(p) => findParentSlug(p.slug, pages) === path && p.type === 'document'\n\t\t)\n\t\t.sort((a, b) => (Number(a.position) || 0) - (Number(b.position) || 0))\n\n\tif (children.length === 0) return null\n\n\treturn (\n\t\t<ul>\n\t\t\t{children.map((child) => (\n\t\t\t\t<li key={child.slug}>\n\t\t\t\t\t<Link href={child.slug}>{child.title}</Link>\n\t\t\t\t\t{renderMenu(child.slug, pages)}\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ul>\n\t)\n}\n\nexport function DocumentLayout({ title, pages = [], children }) {\n\treturn (\n\t\t<div className=\"flex h-full w-full\">\n\t\t\t<ul className=\"menu bg-base-300 w-56\">{renderMenu('/', pages)}</ul>\n\t\t\t<Content>\n\t\t\t\t<h1>{title}</h1>\n\t\t\t\t{children}\n\t\t\t</Content>\n\t\t</div>\n\t)\n}\n\nfunction Content({ children }: { children: ReactNode }) {\n\treturn (\n\t\t<div className=\"overflow-auto h-full w-full\">\n\t\t\t<article className=\"prose p-4\">{children}</article>\n\t\t</div>\n\t)\n}\n"
  },
  {
    "path": "docs/_snippets/hey.org",
    "content": "* Hey, there\n\nThe /beauty/ of org *must* be shared.\n[[https://upload.wikimedia.org/wikipedia/commons/a/a6/Org-mode-unicorn.svg][org-mode logo]]\n"
  },
  {
    "path": "docs/advanced/_layout.tsx",
    "content": "import { DocumentLayout } from '../_layout.tsx'\nexport default DocumentLayout\n"
  },
  {
    "path": "docs/advanced/api.org",
    "content": "#+title: API\n#+published: true\n#+position: 201\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\nDescribe the API.\n"
  },
  {
    "path": "docs/advanced/ast.org",
    "content": "#+title: AST\n#+published: true\n#+position: 202\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\nOrga Abstract Syntax Tree.\n"
  },
  {
    "path": "docs/advanced/index.org",
    "content": "#+title: Advanced\n#+published: true\n#+type: document\n#+position: 200\n\n#+jsx: <Notice>This page is a WIP</Notice>\n"
  },
  {
    "path": "docs/advanced/latex.org",
    "content": "#+title: Latex Support\n#+published: true\n#+position: 203\n#+type: document\n\n\n** Inline Math\nOrgajs supports inline math with latex math delimiters.\n\n#+begin_src org\nIf $$a^2=b$$ and \\( b=2 \\), then the solution must be either $$ a=+\\sqrt{2} $$ or \\[ a=-\\sqrt{2} \\].\n#+end_src\n\nWith be rendered as follows.\n\nIf $$a^2=b$$ and \\( b=2 \\), then the solution must be either $$ a=+\\sqrt{2} $$ or \\[ a=-\\sqrt{2} \\].\n\n** Latex Block\n\nIt also supports =\\begin= commands.\n\n#+begin_src org\n\\begin{equation}\nx=\\sqrt{b}\n\\end{equation}\n#+end_src\n\nWill be rendered\n\n\\begin{equation}\nx=\\sqrt{b}\n\\end{equation}\n\n** Styling\n\n=@orgajs/rehype-latex= is the plugin for handling latex. It uses [[https://katex.org][katex]] underneath, so you will have to add the css link yourself in your website. Add the following to the =head=.\n"
  },
  {
    "path": "docs/contribute.org",
    "content": "#+title: Contribute\n#+published: true\n#+position: 300\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\n* Need Some Inspiration?\n\nYou can find tons of plugins for remark, since they work in similar ways, we can steal some ideas [[https://github.com/remarkjs/remark/blob/main/doc/plugins.md#creating-plugins][here]] and [[https://github.com/remarkjs/awesome-remark][there]], maybe even use them directly.\n"
  },
  {
    "path": "docs/guides/_layout.tsx",
    "content": "import { DocumentLayout } from '../_layout.tsx'\nexport default DocumentLayout\n"
  },
  {
    "path": "docs/guides/astro.org",
    "content": "#+title: Astro\n#+published: true\n#+type: document\n#+position: 5\n\nUse =@orgajs/astro= to write Astro pages in Org Mode (=.org=) and compile them with orgx.\n\n* Quick Start\n\n1. Install the integration:\n\n#+begin_src sh\npnpm add @orgajs/astro\n#+end_src\n\n2. Register it in =astro.config.mjs=:\n\n#+begin_src javascript\nimport { defineConfig } from 'astro/config'\nimport orgMode from '@orgajs/astro'\n\nexport default defineConfig({\n  integrations: [orgMode()]\n})\n#+end_src\n\n3. Create a page at =src/pages/index.org=:\n\n#+begin_src org\n,* Hello from Org Mode\n\nThis page is rendered from Org Mode in Astro.\n#+end_src\n\n4. Start Astro:\n\n#+begin_src sh\npnpm astro dev\n#+end_src\n\n* Major Features\n\n** Native =.org= pages in Astro\nAny file in =src/pages/*.org= is treated as a page route, just like Astro files in other supported formats.\n\n** Org metadata support\nOrg keywords such as =#+title:=, =#+description:=, and =#+slug:= are parsed and exposed as entry metadata for Astro content handling.\n\n** orgx-powered compilation\nUnder the hood, this integration uses orgx (via =@orgajs/rollup=), so you get:\n- Org Mode parsing to JSX-compatible output\n- JavaScript imports/exports inside Org documents\n- Unified/rehype/recma pipeline compatibility\n\n** Inline JSX components\nYou can embed JSX directly in Org files, including imported components.\n\n#+begin_src org\n,#+jsx: import Card from '../components/Card.astro'\n\nHere is a Card rendered inline:\n\n,#+jsx: <Card title=\"Inline component\">Hello from Org + JSX</Card>\n\n,#+begin_export jsx\n<section className=\"hero\">\n  <h2>JSX export block</h2>\n  <p>You can also write larger JSX blocks.</p>\n</section>\n,#+end_export\n#+end_src\n\nUse =#+jsx:= for single-line JSX/imports and =#+begin_export jsx= for multi-line blocks.\n"
  },
  {
    "path": "docs/guides/gatsby.org",
    "content": "#+title: Gatsby\n#+published: true\n#+type: document\n#+position: 102\n\n#+jsx: <Notice title=\"DEPRECATED\">I'm no longer actively maintaining this Gatsby integration due to the rapid pace of frontend development. However, the source code remains available for those who wish to adapt and maintain it independently. You can refer to the orgajs project for examples of advanced usage.</Notice>\n\n* Create Gatsby Project\n\nCreate a new gatsby website following the [[https://www.gatsbyjs.com/get-started/][documentation]]. Or simply\n\n#+begin_src sh\nnpx gatsby new gatsby-site\n#+end_src\n\n* Installation\n\nInstall packages.\n\n#+begin_src sh\ncd gatsby-site\nyarn add gatsby-plugin-orga @orgajs/react @orgajs/loader\n#+end_src\n\n* Configuration\n\nAdd =gatsby-plugin-orga= to =gatsby-config.js=.\n\n#+begin_src javascript\nmodule.exports = {\n  plugins: ['gatsby-plugin-orga']\n}\n#+end_src\n\nAdd a org file in folder =src/pages= directory. It should work out of the box.\n\nFor more advanced usage, please checkout code of [[https://github.com/orgapp/orgajs][orgajs project]], which generate this website via =gatsby-theme-orga-docs=.\n"
  },
  {
    "path": "docs/guides/index.org",
    "content": "#+title: Getting Started\n#+published: true\n#+type: document\n#+position: 100\n\n** Basic Setup\nOrga is built on the [[https://unifiedjs.com][unified]] ecosystem. The core parser package =@orgajs/reorg= is the minimum requirement to get started.\n\n** Simple HTML Compilation\nTo transform Org-mode content into HTML, install the required packages:\n\n#+begin_src sh\nnpm install @orgajs/reorg @orgajs/reorg-rehype rehype-stringify unified-stream\n#+end_src\n\nCreate a basic compilation script:\n\n#+begin_src javascript\n// compile.js\nconst stream = require('unified-stream')\nconst reorg = require('@orgajs/reorg')\nconst mutate = require('@orgajs/reorg-rehype')\nconst html = require('rehype-stringify')\n\nconst processor = reorg()\n      .use(mutate)\n      .use(html)\n\nprocess.stdin.pipe(stream(processor)).pipe(process.stdout)\n#+end_src\n\nConvert your Org files to HTML:\n\n#+begin_src sh\nnode compile.js < input.org > output.html\n#+end_src\n#+end_src\n\nExample Input (input.org)\n#+begin_src org\n,* Hello Orga\nOrga is *awesome*.\n#+end_src\n\nYields Output (output.html)\n#+begin_src html\n<div class=\"section\">\n\t<h1>Hello Orga</h1>\n\t<p>Orga is <strong class=\"\">awesome</strong>. </p>\n</div>\n#+end_src\n"
  },
  {
    "path": "docs/guides/next.org",
    "content": "#+title: Next.js\n#+published: true\n#+type: document\n#+position: 4\n\nUse =@orgajs/next= to write Next.js pages in Org Mode (=.org=) and compile them with orgx.\n\nStandalone repository:\n\n- [[https://github.com/orgapp/orga-next][orgapp/orga-next]]\n\n* Quick Start\n\n1. Install the integration:\n\n#+begin_src sh\npnpm add @orgajs/next @orgajs/loader @orgajs/react\n#+end_src\n\n2. Register it in =next.config.js=:\n\n#+begin_src javascript\nconst withOrg = require('@orgajs/next')()\n\nmodule.exports = withOrg({\n  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'org'],\n})\n#+end_src\n\n3. Create a page at =app/page.org= (or =pages/index.org=):\n\n#+begin_src org\n,* Hello from Org Mode\n\nThis page is rendered from Org Mode in Next.js.\n#+end_src\n\n4. Start Next.js:\n\n#+begin_src sh\npnpm next dev\n#+end_src\n\n* Major Features\n\n** Native =.org= routes in Next.js\nOrg files can be used as top-level routes in Next.js once =pageExtensions= includes =org=.\n\n** Works with App Router and Pages Router\nYou can place Org pages in either:\n- =app/**/page.org=\n- =pages/**/*.org=\n\n** Global Org component mapping\nCreate =org-components.js= at project root to override rendered elements globally.\n\n#+begin_src javascript\nexport function useOrgComponents() {\n  return {\n    h1: (props) => <h1 style={{ color: 'tomato' }} {...props} />,\n  }\n}\n#+end_src\n\n** orgx-powered compilation\nThis integration uses =@orgajs/loader= under the hood, providing Org Mode to JSX compilation and compatibility with orgx features.\n\n* Notes\n\n- Package name: =@orgajs/next=\n- Repository: [[https://github.com/orgapp/orga-next][orgapp/orga-next]]\n"
  },
  {
    "path": "docs/guides/orga-build.org",
    "content": "#+title: Build a blog with orga-build\n#+position: 2\n#+type: document\n\n\n=orga-build= is a powerful static site generator that allows you to build entire websites using only Org-mode files. Tired of learning ever changing frontend frameworks, just want to build a good old static website? This is for you.\n\n\nGet a bunch of org files in a folder. Run\n\n#+begin_src sh\nnpx orga-build\n#+end_src\n\nThis command will generate a static website in the =out= folder, with each Org-mode file translated into an HTML file. The end.\n\n** Layouts\n\nLayout is powerful tool that allows you to define the overall structure and appearance of your website pages. If you are not allergic to write a little bit of =jsx=, you can create layout files and nest them within folders to apply specific layouts to different sections of your website.\n\nTo add a layout, create a file named =_layout.tsx= in the desired folder. The root-level layout file (=<project_root>/_layout.tsx=) will be applied to all pages, while nested layout files (e.g., =<project_root>/blog/_layout.tsx=) will be applied to all pages within that specific folder, nested inside the root-level layout.\n\n*** Layout Props\n\nLayout components have access to the in-buffer settings of the corresponding Org-mode file. For example, if you have the following lines in your Org-mode file:\n\n#+begin_src org\n,#+title: My Page\n,#+author: John\n#+end_src\n\nThese values will be available as props in your layout file, allowing you to use them dynamically.\n\nAdditionally, the layout component receives a =pages= prop, which is an array of page objects representing the pages within the current folder. This feature makes it easy to build navigation components that reflect the structure of your website.\n\n** Build Commands\n\n=orga-build= supports two lifecycle hooks: =preBuild= and =postBuild=. These hooks allow you to run custom commands before and after the main build process, respectively. You can set up these hooks in the =orga.config.js= file by exporting named variables:\n\n#+begin_src javascript\nexport const preBuild = ['npm run build:css']\n#+end_src\n\nThe =preBuild= and =postBuild= variables should be arrays of strings, where each string represents a shell command to be executed by the build process.\n\n** Custom Components\n\n=orga-build= allows you to create and use custom React components within your Org-mode files. To do this, create a file named =_components.tsx= in your project root and export your custom components:\n\n#+begin_src jsx\nexport function FancyBox({ children }) {\n  return <div className=\"fancy\">{children}</div>;\n}\n#+end_src\n\nYou can then use these components directly in your Org-mode files using the =#+jsx:= syntax:\n\n#+begin_src org\n#+jsx: <FancyBox>hey, box</FancyBox>\n#+end_src\n\nThis powerful feature enables you to extend the functionality of your website and create rich, interactive experiences.\n"
  },
  {
    "path": "docs/guides/webpack.org",
    "content": "#+title: Webpack\n#+published: true\n#+type: document\n#+position: 3\n\n=@orgajs/loader= is a webpack loader taht can be used natrually with webpack setup.\nFor hassle free experience, use [[file:orga-build.org][orga-build]].\n\n* Installation\n\n#+begin_src sh\nnpm install --save-dev @orgajs/loader @orgajs/estree-jsx @orgajs/rehype-estree @orgajs/reorg-rehype\n#+end_src\n\n* Configuration\n\nAn example =webpack.config.js= file.\n\n#+begin_src javascript\nimport toEstree from '@orgajs/rehype-estree'\nimport toRehype from '@orgajs/reorg-rehype'\nimport toJsx from '@orgajs/estree-jsx'\n\nconst config = {\n  mode: 'development',\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        use: 'babel-loader',\n        exclude: /node_modules/\n      },\n      {\n        test: /\\.org$/,\n        use: [\n          'babel-loader',\n          {\n            loader: '@orgajs/loader',\n            options: {\n              plugins: [\n                toRehype,\n                toEstree,\n                toJsx,\n              ]\n            }\n          }],\n      },\n    ]\n  },\n}\n\nexport default config\n#+end_src\n\nAs you can see that the output of =@orgajs/loader= is normal JSX code, so you will need [[https://webpack.js.org/loaders/babel-loader/][babel-loader]] to finish it at the end.\n\n* Babel Configuration\n\nYOu will need to configure babel to support react syntax. An example of =.babelrc= file.\n\n#+begin_src json\n{\n  \"presets\": [\"@babel/env\", \"@babel/react\"]\n}\n#+end_src\n\nTake a look at webpack documentation for creating a basic react project for more details.\n"
  },
  {
    "path": "docs/index.org",
    "content": "#+title: Orgajs\n#+jsx: import code from './index.org?raw'\n\n* What Is It\n\n=Orga= is a flexible org-mode syntax parser. It parses org content into AST ([[https://en.wikipedia.org/wiki/Abstract_syntax_tree][Abstract Syntax Tree 🌲]]). And it's written in JavaScript.\n\n* What can I do with it\n\n** Editor\n\nIntroducing org editor. This the source code of *this page*.\n\n#+jsx: <OrgEditor className='h-64 not-prose' content={code}/>\n\n** Publication\n\nBuild a website with org-mode files and [[/guides/orga-build][orga-build]].\n\n# the \"orga-editor\" is a web-component, the following line defines it\n#+jsx: <script type=\"module\" src=\"/editor.js\"/>\n"
  },
  {
    "path": "docs/playground.tsx",
    "content": "import { ReactNode, useEffect, useMemo, useState } from 'react'\nimport { VFile } from 'vfile'\nimport { evaluate } from '@orgajs/orgx'\nimport * as runtime from 'react/jsx-runtime'\nimport { map } from 'unist-util-map'\nimport { JSEditor, OrgEditor } from './_components'\nimport initContent from './_snippets/hey.org?raw'\n\nconst tabs = ['Rendered', 'Oast (Org-mode)', 'Hast (HTML)', 'JSX Code']\n\nexport default function Playground() {\n\tconst [content, setContent] = useState<string>(initContent)\n\tconst [parsed, setParsed] = useState({\n\t\toast: '',\n\t\thast: '',\n\t\tjsx: '',\n\t\tpreview: <div>rendering...</div>\n\t})\n\tconst [activeTab, setActiveTab] = useState(0)\n\n\tconst showPosition = false\n\n\tconst code = useMemo(() => {\n\t\tswitch (activeTab) {\n\t\t\tcase 1:\n\t\t\t\treturn parsed.oast\n\t\t\tcase 2:\n\t\t\t\treturn parsed.hast\n\t\t\tcase 3:\n\t\t\t\treturn parsed.jsx\n\t\t\tdefault:\n\t\t\t\treturn ''\n\t\t}\n\t}, [activeTab, parsed])\n\n\tuseEffect(() => {\n\t\tconst url = new URL(window.location.href)\n\t\tconst text = url.searchParams.get('text')\n\t\tif (text) {\n\t\t\tsetContent(decodeURIComponent(text))\n\t\t}\n\t}, [])\n\n\tuseEffect(() => {\n\t\trender(content).then(setParsed)\n\t}, [content])\n\n\treturn (\n\t\t<div className=\"flex h-full w-full\">\n\t\t\t{/* Editor panel */}\n\t\t\t<div className=\"h-full w-1/2 border-1 border-gray-600\">\n\t\t\t\t<OrgEditor\n\t\t\t\t\tclassName=\"h-full\"\n\t\t\t\t\tcontent={content}\n\t\t\t\t\tonChange={(state) => setContent(state.doc.toString())}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{/* Preview panel */}\n\t\t\t<div className=\"h-full w-1/2 flex flex-col\">\n\t\t\t\t<ul className=\"tabs tabs-border\">\n\t\t\t\t\t{tabs.map((tab, i) => (\n\t\t\t\t\t\t<input\n\t\t\t\t\t\t\tkey={`tab-${i}`}\n\t\t\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\t\t\tname=\"tabs\"\n\t\t\t\t\t\t\tclassName=\"tab\"\n\t\t\t\t\t\t\taria-label={tab}\n\t\t\t\t\t\t\tonChange={() => setActiveTab(i)}\n\t\t\t\t\t\t\tchecked={activeTab === i}\n\t\t\t\t\t\t/>\n\t\t\t\t\t))}\n\t\t\t\t</ul>\n\t\t\t\t<div className=\"h-full overflow-auto\">\n\t\t\t\t\t<div className={`p-4 ${activeTab === 0 ? 'block' : 'hidden'}`}>\n\t\t\t\t\t\t{parsed.preview}\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className={activeTab === 0 ? 'hidden' : 'block'}>\n\t\t\t\t\t\t<JSEditor>{code}</JSEditor>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"menu lg:menu-horizontal rounded-box w-full justify-end\">\n\t\t\t\t\t<li>\n\t\t\t\t\t\t<button onClick={generateLink}>\n\t\t\t\t\t\t\t<svg\n\t\t\t\t\t\t\t\txmlns=\"http://www.w3.org/2000/svg\"\n\t\t\t\t\t\t\t\theight=\"24px\"\n\t\t\t\t\t\t\t\tviewBox=\"0 -960 960 960\"\n\t\t\t\t\t\t\t\twidth=\"24px\"\n\t\t\t\t\t\t\t\tfill=\"#e3e3e3\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<path d=\"M440-280H280q-83 0-141.5-58.5T80-480q0-83 58.5-141.5T280-680h160v80H280q-50 0-85 35t-35 85q0 50 35 85t85 35h160v80ZM320-440v-80h320v80H320Zm200 160v-80h160q50 0 85-35t35-85q0-50-35-85t-85-35H520v-80h160q83 0 141.5 58.5T880-480q0 83-58.5 141.5T680-280H520Z\" />\n\t\t\t\t\t\t\t</svg>\n\t\t\t\t\t\t\tGenerate Link\n\t\t\t\t\t\t</button>\n\t\t\t\t\t</li>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</div>\n\t)\n\n\t// Generate shareable link\n\tfunction generateLink() {\n\t\tconst url = new URL(window.location.href)\n\t\tconst encoded = encodeURIComponent(content)\n\t\turl.searchParams.set('text', encoded)\n\t\tnavigator.clipboard.writeText(url.toString())\n\t\t// This assumes window.echo is available globally\n\t\tif (typeof window.echo === 'function') {\n\t\t\twindow.echo('Link copied to clipboard')\n\t\t} else {\n\t\t\tconsole.log('Link copied to clipboard')\n\t\t}\n\t}\n\n\tasync function render(content: string) {\n\t\tconst file = new VFile(content)\n\t\tlet oast = ''\n\t\tlet hast = ''\n\t\tlet jsx = ''\n\n\t\tconst { default: Content } = await evaluate(file, {\n\t\t\t...runtime,\n\t\t\trehypePlugins: [capture((v) => (hast = toJSON(v)))],\n\t\t\treorgPlugins: [capture((v) => (oast = toJSON(v)))]\n\t\t})\n\n\t\tjsx = String(file)\n\t\treturn {\n\t\t\toast,\n\t\t\thast,\n\t\t\tjsx,\n\t\t\tpreview: (\n\t\t\t\t<div className=\"prose h-full overflow-auto\">\n\t\t\t\t\t<Content />\n\t\t\t\t</div>\n\t\t\t)\n\t\t}\n\t}\n\n\tfunction capture(fn: (v: any) => void) {\n\t\treturn function () {\n\t\t\treturn function (tree) {\n\t\t\t\tfn(tree)\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction toJSON(tree: any) {\n\t\treturn JSON.stringify(\n\t\t\tmap(tree, (node) => {\n\t\t\t\tconst { position, ...rest } = node\n\t\t\t\tif (!showPosition) {\n\t\t\t\t\treturn rest\n\t\t\t\t}\n\t\t\t\treturn node\n\t\t\t}),\n\t\t\tnull,\n\t\t\t2\n\t\t)\n\t}\n}\n"
  },
  {
    "path": "docs/style.css",
    "content": "@import 'tailwindcss';\n@plugin \"@tailwindcss/typography\";\n@plugin \"daisyui\" {\n\tthemes: nord --default, dark --prefersdark;\n}\n\n#root {\n\t@apply flex flex-col h-screen;\n}\n\n.cm-editor {\n\toutline: none;\n}\n\n.cm-editor.cm-focused {\n\toutline: none;\n}\n\n/* GitHub-like code block styling for rehype-pretty-code output */\n.prose pre[data-theme] {\n\tbackground-color: #0d1117;\n\tborder: 1px solid #30363d;\n\tborder-radius: 8px;\n\tcolor: #c9d1d9;\n\tmargin: 1.25rem 0;\n\toverflow-x: auto;\n\tpadding: 1rem 0;\n}\n\n.prose pre[data-theme] code {\n\tbackground: transparent;\n\tcolor: inherit;\n\tcounter-reset: line;\n\tdisplay: grid;\n\tfont-size: 0.875rem;\n\tline-height: 1.5;\n\tpadding: 0;\n}\n\n.prose pre[data-theme] code .line {\n\tdisplay: inline-block;\n\tmin-height: 1.5rem;\n\tpadding: 0 1rem;\n\twidth: 100%;\n}\n\n.prose pre[data-theme] code .line--highlighted {\n\tbackground-color: rgba(56, 139, 253, 0.15);\n}\n\n.prose pre[data-theme] code .word--highlighted {\n\tbackground-color: rgba(56, 139, 253, 0.3);\n\tborder: 1px solid rgba(56, 139, 253, 0.45);\n\tborder-radius: 4px;\n\tpadding: 0.1rem 0.25rem;\n}\n\n.prose code:not(pre code) {\n\tbackground-color: rgba(175, 184, 193, 0.2);\n\tborder-radius: 6px;\n\tfont-size: 0.875em;\n\tpadding: 0.15rem 0.35rem;\n}\n"
  },
  {
    "path": "docs/tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"lib\": [\"esnext\", \"DOM\"],\n\t\t\"moduleResolution\": \"node\",\n\t\t\"allowJs\": true,\n\t\t\"esModuleInterop\": true,\n\t\t\"allowSyntheticDefaultImports\": true,\n\t\t\"allowImportingTsExtensions\": true,\n\t\t\"skipLibCheck\": true,\n\t\t\"isolatedModules\": true,\n\t\t\"target\": \"esnext\",\n\t\t\"module\": \"esnext\"\n\t}\n}\n"
  },
  {
    "path": "examples/README.org",
    "content": "#+TITLE: Examples\n\n* Setup\n\nBefore using any of the examples, you have to build the monorepo.\n\n#+begin_src shell\ngit clone git@github.com:orgapp/orgajs.git\ncd orgajs\nyarn\nyarn build\n#+end_src\n\nNow you can =cd= into specific example project directory and start hacking.\n\n* Which Example To Follow\n\nYou should choose...\n\n- [[file:gatsby/][gatsby]] :: if you use gatsby, want highly customized website, render react component directly in org file. okay with one page per org file.\n- [[file:gatsby-posts/][gatsby-posts]] :: if you use gatsby, want out-of-the-box blog-like website. Organize posts into either files or sections in files. Mostly okay with the default layout.\n- [[file:gatsby-posts-core/][gatsby-posts-core]] :: if you want to customize gatsby-posts to the bone.\n- [[file:next/][next]] :: if you use next.js\n- [[file:webpack/][webpack]] :: if you want total control, build from scratch, use webpack\n\n* A Little Bit Of Details About Gatsby Examples\n\nIf you are trying to choose a gatsby example, here are some technical details that you should know.\nThere are currently two styles of rendering org-mode content in gatsby.\n\n** [[file:~/Code/orgajs/packages/gatsby-transformer-orga/][gatsby-transformer-orga]] (original)\nThis is the original implementation. To draw parity from the markdown world, the implementation is similar to [[https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-transformer-remark][gatsby-transformer-remark]]. It's a gatsby [[https://www.gatsbyjs.com/docs/how-to/plugins-and-themes/creating-a-transformer-plugin/][\"transfomer\"]] plugin. To summaries, it taps into gatsby's build lifecycle and transform source (your org files in this case) into gatsby nodes, eventually render them as web pages. You will get custom graphql types (=OrgContent=, if use the [[file:~/Code/orgajs/packages/gatsby-theme-orga-posts-core/][gatsby-theme-posts-core]] or [[file:~/Code/orgajs/packages/gatsby-theme-orga-posts/][gatsby-theme-posts]], it gets translated into =OrgPost= type). So you can generate your own custom pages, like a post list page, with the help of graphql queries. Another special feature is the ability to generate multiple pages from sections within single org-mode file. Basically your org-mode files are treated as *data*. Take a look at the following examples for details.\n- [[file:gatsby-posts/][gatsby-posts]]\n- [[file:gatsby-posts-core/][gatsby-posts-core]]\n\n** [[file:~/Code/orgajs/packages/gatsby-plugin-orga/][gatsby-plugin-orga]] (new)\nThis is the latest implementation from the v3.x release. This is the equivalent of [[https://mdxjs.com][mdx]] on the markdown side. It is powered by the webpack loader [[file:~/Code/orgajs/packages/loader/][@orgajs/loader]], which enables orga to be easily integrated with a much wider range of tools (e.g. next.js, webpack, create-react-app etc...).\n\nHere is a list of my favorite features:\n- render react components in org-mode file, just like mdx\n- per file custom layout\n- passing arbitrary data to layout component via =#+key: value=\n- replace default elements with your own react components\n\nBasically Your org files are powerful *pages*. the [[file:gatsby/][gatsby example project]] is a minimal setup. For more advanced example, you can draw some inspirations from the [[file:~/Code/orgajs/website/][website]] (source code for https://orga.js.org).\n\n** The Themes\nThere are a couple of [[https://www.gatsbyjs.com/docs/themes/][gatsby themes]] you can choose from if you want some out of the box goodies. Also they are good resources for creating your own theme.\n\n- gatsby-theme-orga-posts-core :: Powered by =gatsby-transformer-orga=, it transforms your org files into blog posts, with zero UI elements (it literally print out stringified JSON objects by default). It's totally up to you to customize the look and feel.\n- gatsby-theme-orga-posts :: A wrapper around =gatsby-theme-posts-core=, with opinionated UI design. Yet still customizable to certain extend through [[https://www.gatsbyjs.com/docs/how-to/plugins-and-themes/shadowing/][component shadowing]].\n- gatsby-theme-orga-docs :: Powered by =gatsby-plugin-orga=, this is what the [[file:~/Code/orgajs/website/][website]] is using. It's designed for documentation kind of websites, with swappable components (through shadowing)\n\n"
  },
  {
    "path": "examples/build/index.org",
    "content": "#+title: Build with Orga\n\n* Hi\n\nYou can build a static website with *just* org files.\n\nHere's [[file:more.org][another page]].\n\n#+begin_src sh\norga-build\n#+end_src\n"
  },
  {
    "path": "examples/build/more.org",
    "content": "#+title: Another Page\n\nThis is another page.\n"
  },
  {
    "path": "examples/build/package.json",
    "content": "{\n\t\"name\": \"@orgajs/example-build\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"dev\": \"orga-build dev\",\n\t\t\"build\": \"orga-build\"\n\t},\n\t\"devDependencies\": {\n\t\t\"orga-build\": \"workspace:^\"\n\t}\n}\n"
  },
  {
    "path": "examples/build/test-content.tsx",
    "content": "import { getPages, getPage } from 'orga-build:content'\n\nexport default function TestContent() {\n  // Test 1: Get all pages\n  const allPages = getPages()\n\n  // Test 2: Get a specific page\n  const indexPage = getPage('index')\n\n  // Test 3: Filter pages\n  const filtered = getPages('', (entry) => entry.ext === 'org')\n\n  return (\n    <div>\n      <h1>Content API Test</h1>\n\n      <h2>All Pages ({allPages.length})</h2>\n      <ul>\n        {allPages.map((page) => (\n          <li key={page.id}>\n            <strong>{page.id}</strong> - {page.slug} (path: {page.path || '(root)'})\n            {page.data && Object.keys(page.data).length > 0 && (\n              <pre>{JSON.stringify(page.data, null, 2)}</pre>\n            )}\n          </li>\n        ))}\n      </ul>\n\n      <h2>Index Page</h2>\n      {indexPage ? (\n        <div>\n          <p>Found: {indexPage.slug}</p>\n          <pre>{JSON.stringify(indexPage, null, 2)}</pre>\n        </div>\n      ) : (\n        <p>Not found</p>\n      )}\n\n      <h2>Filtered Pages (org only)</h2>\n      <ul>\n        {filtered.map((page) => (\n          <li key={page.id}>{page.slug} - {page.ext}</li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n"
  },
  {
    "path": "examples/editor/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndist-ssr\n*.local\n\n# Editor directories and files\n.vscode/*\n!.vscode/extensions.json\n.idea\n.DS_Store\n*.suo\n*.ntvs*\n*.njsproj\n*.sln\n*.sw?\n"
  },
  {
    "path": "examples/editor/CHANGELOG.md",
    "content": "# @orgajs/example-editor\n\n## 0.3.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/editor@1.4.0\n\n## 0.2.4\n\n### Patch Changes\n\n- Updated dependencies [60ad38f]\n  - @orgajs/editor@1.3.1\n\n## 0.2.3\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/editor@1.3.0\n\n## 0.2.2\n\n### Patch Changes\n\n- Updated dependencies [2f7b62d]\n  - @orgajs/editor@1.2.2\n\n## 0.2.1\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n- Updated dependencies [e3ef3a5]\n  - @orgajs/editor@1.2.1\n\n## 0.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/editor@1.2.0\n\n## 0.1.7\n\n### Patch Changes\n\n- 0f825de5: update editor dependencies\n- Updated dependencies [0f825de5]\n  - @orgajs/editor@1.1.7\n\n## 0.1.6\n\n### Patch Changes\n\n- Updated dependencies [e9564ff5]\n  - @orgajs/editor@1.1.6\n\n## 0.1.5\n\n### Patch Changes\n\n- Updated dependencies [0ffa3415]\n  - @orgajs/editor@1.1.5\n\n## 0.1.4\n\n### Patch Changes\n\n- dc3a9db2: cleanup editor\n- Updated dependencies [dc3a9db2]\n  - @orgajs/editor@1.1.4\n\n## 0.1.3\n\n### Patch Changes\n\n- Updated dependencies [7cfff79a]\n  - @orgajs/editor@1.1.3\n\n## 0.1.2\n\n### Patch Changes\n\n- Updated dependencies [ea032b35]\n  - @orgajs/editor@1.1.2\n\n## 0.1.1\n\n### Patch Changes\n\n- ac322714: implement editor\n- Updated dependencies [ac322714]\n  - @orgajs/editor@1.1.1\n\n## 0.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/editor@1.1.0\n"
  },
  {
    "path": "examples/editor/content.org",
    "content": "#+title:  Example Org File\n#+date:   2023-11-24\n#+todo: TODO NEXT | DONE\n\nOrg uses single characters to markup *bold* /italic/ _underline_ +strike through+ ~code~ and =verbatim=. Links also use minimal\nmarkup in [[https://orgmode.org][Org]].\n\n* NEXT Blocks\n\n#+begin_src js\nconsole.log('hello')\n#+end_src\n\n* Lists\n\n- one\n- two\n- three\n\n\n* Tasks\n\n** DONE buy milk\n** TODO drink it\n"
  },
  {
    "path": "examples/editor/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/vite.svg\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n    <title>Vite + TS</title>\n  </head>\n  <body>\n    <div id=\"container\">\n      <h1>Org Editor</h1>\n      <div id=\"editor\"></div>\n    </div>\n    <script type=\"module\" src=\"/src/main.ts\"></script>\n  </body>\n</html>\n"
  },
  {
    "path": "examples/editor/package.json",
    "content": "{\n\t\"name\": \"@orgajs/example-editor\",\n\t\"private\": true,\n\t\"version\": \"0.3.0\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"dev\": \"vite --port 3000 --force\",\n\t\t\"build\": \"tsc && vite build\",\n\t\t\"preview\": \"vite preview\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@codemirror/view\": \"^6.36.2\",\n\t\t\"typescript\": \"^5.9.2\",\n\t\t\"vite\": \"^6.0.11\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/editor\": \"workspace:^\",\n\t\t\"cm6-theme-nord\": \"^0.2.0\"\n\t}\n}\n"
  },
  {
    "path": "examples/editor/src/main.ts",
    "content": "import { makeEditor } from '@orgajs/editor'\nimport content from '../content.org?raw'\nimport './style.css'\n\nconst target = document.querySelector('#editor')\n\nif (target === null) {\n\tthrow new Error('No target element found')\n}\nmakeEditor({ target, content, extensions: [] })\n"
  },
  {
    "path": "examples/editor/src/style.css",
    "content": "body {\n\tbackground-color: #e7e6e5;\n}\n\n#editor {\n\twidth: 720px;\n\theight: 800px;\n\toverflow: auto;\n\tborder: 1px solid #ccc;\n\tbackground-color: #fff;\n}\n"
  },
  {
    "path": "examples/editor/tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\": [\"ES2020\", \"DOM\", \"DOM.Iterable\"],\n    \"skipLibCheck\": true,\n\n    /* Bundler mode */\n    \"moduleResolution\": \"bundler\",\n    \"allowImportingTsExtensions\": true,\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true,\n\n    /* Linting */\n    \"strict\": true,\n    \"noUnusedLocals\": true,\n    \"noUnusedParameters\": true,\n    \"noFallthroughCasesInSwitch\": true\n  },\n  \"include\": [\"src\"]\n}\n"
  },
  {
    "path": "examples/getting-started/.gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directory used by tools like istanbul\ncoverage\n\n# nyc test coverage\n.nyc_output\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (https://nodejs.org/api/addons.html)\nbuild/Release\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# next.js build output\n.next"
  },
  {
    "path": "examples/getting-started/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.2.12\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.11\n\n## 4.2.11\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.10\n\n## 4.2.10\n\n### Patch Changes\n\n- Updated dependencies [bd2365a]\n  - @orgajs/reorg@4.3.3\n  - @orgajs/reorg-rehype@4.3.9\n\n## 4.2.9\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.8\n\n## 4.2.8\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.7\n\n## 4.2.7\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.6\n\n## 4.2.6\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.5\n\n## 4.2.5\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.4\n\n## 4.2.4\n\n### Patch Changes\n\n- @orgajs/reorg@4.3.2\n- @orgajs/reorg-rehype@4.3.3\n\n## 4.2.3\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.2\n- @orgajs/reorg@4.3.1\n\n## 4.2.2\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.1\n\n## 4.2.1\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/reorg-rehype@4.3.0\n  - @orgajs/reorg@4.3.0\n\n## 4.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/reorg-rehype@4.2.0\n  - @orgajs/reorg@4.2.0\n\n## 4.1.3\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.1.3\n\n## 4.1.2\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.1.2\n- @orgajs/reorg@4.1.2\n\n## 4.1.1\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.1.1\n- @orgajs/reorg@4.1.1\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/reorg-rehype@4.1.0\n  - @orgajs/reorg@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - @orgajs/reorg-rehype@4.0.0\n  - @orgajs/reorg@4.0.0\n\n## 3.1.8\n\n### Patch Changes\n\n- Updated dependencies [eeccc870]\n  - @orgajs/reorg-rehype@3.0.10\n  - @orgajs/reorg@3.1.7\n\n## 3.1.7\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.9\n- @orgajs/reorg@3.1.6\n\n## 3.1.6\n\n### Patch Changes\n\n- 4bde5155: tidy up dependencies\n  - @orgajs/reorg-rehype@3.0.8\n  - @orgajs/reorg@3.1.5\n\n## 3.1.5\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.7\n- @orgajs/reorg@3.1.4\n\n## 3.1.4\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.6\n- @orgajs/reorg@3.1.3\n\n## 3.1.3\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.5\n- @orgajs/reorg@3.1.2\n\n## 3.1.2\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.4\n- @orgajs/reorg@3.1.1\n\n## 3.1.1\n\n### Patch Changes\n\n- Updated dependencies [7f209ff5]\n  - @orgajs/reorg-rehype@3.0.3\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - @orgajs/reorg@3.1.0\n  - @orgajs/reorg-rehype@3.0.2\n\n## 3.0.1\n\n### Patch Changes\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - @orgajs/reorg@3.0.1\n  - @orgajs/reorg-rehype@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - @orgajs/reorg@3.0.0\n  - @orgajs/reorg-rehype@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n**Note:** Version bump only for package @orgajs/getting-started\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package example\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package example\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package example\n"
  },
  {
    "path": "examples/getting-started/README.org",
    "content": "This is an example project, with [[file:index.js][10 lines of code]].\n\n#+BEGIN_SRC sh\nnpm install\nnpm run build\n#+END_SRC\n\nTake a look at =readme.html= file.\n"
  },
  {
    "path": "examples/getting-started/index.js",
    "content": "import { reorg } from '@orgajs/reorg'\nimport { stream } from 'unified-stream'\nimport mutate from '@orgajs/reorg-rehype'\nimport html from 'rehype-stringify'\n\nconst processor = reorg().use(mutate).use(html)\n\nprocess.stdin.pipe(stream(processor)).pipe(process.stdout)\n"
  },
  {
    "path": "examples/getting-started/package.json",
    "content": "{\n  \"private\": true,\n  \"name\": \"@orgajs/getting-started\",\n  \"version\": \"4.2.12\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"type\": \"module\",\n  \"scripts\": {\n    \"build\": \"node index.js < README.org > readme.html\"\n  },\n  \"author\": \"\",\n  \"license\": \"ISC\",\n  \"dependencies\": {\n    \"@orgajs/reorg\": \"workspace:*\",\n    \"@orgajs/reorg-rehype\": \"workspace:*\",\n    \"rehype-stringify\": \"^10.0.1\",\n    \"unified\": \"11.0.5\",\n    \"unified-stream\": \"^3.0.0\"\n  }\n}\n"
  },
  {
    "path": "examples/webpack/.babelrc",
    "content": "{\n  \"presets\": [\"@babel/preset-env\", \"@babel/preset-react\"]\n}\n"
  },
  {
    "path": "examples/webpack/CHANGELOG.md",
    "content": "# Change Log\n\n## 3.2.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n## 3.1.1\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n\n## 3.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n## 3.0.1\n\n### Patch Changes\n\n- 4bde5155: tidy up dependencies\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n**Note:** Version bump only for package @orgajs/example-webpack\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/example-webpack\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/example-webpack\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/example-webpack\n"
  },
  {
    "path": "examples/webpack/README.org",
    "content": "#+title: Webpack + Orga\n\nThis is a minimal webpack website that recognizes org-mode files as pages.\n\n-----\n\n* Running locally\n\nSee the [[file:../README.org][setup instructions]] before using this project.\n\n#+begin_src shell\nyarn start\n#+end_src\n\n"
  },
  {
    "path": "examples/webpack/package.json",
    "content": "{\n\t\"name\": \"@orgajs/example-webpack\",\n\t\"private\": true,\n\t\"version\": \"3.2.0\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"scripts\": {\n\t\t\"build\": \"webpack\",\n\t\t\"webpack\": \"webpack\",\n\t\t\"start\": \"webpack serve\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@babel/core\": \"^7.22.11\",\n\t\t\"@babel/preset-env\": \"^7.22.14\",\n\t\t\"@babel/preset-react\": \"^7.22.5\",\n\t\t\"@orgajs/loader\": \"workspace:^\",\n\t\t\"babel-loader\": \"^9.1.3\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"webpack\": \"^5.104.1\",\n\t\t\"webpack-cli\": \"^5.1.4\",\n\t\t\"webpack-dev-server\": \"^4.15.1\"\n\t}\n}\n"
  },
  {
    "path": "examples/webpack/public/index.html",
    "content": "<!DOCTYPE html>\n<meta charset=\"utf-8\" />\n<div id=\"root\"></div>\n<script src=\"main.js\"></script>\n"
  },
  {
    "path": "examples/webpack/src/box.js",
    "content": "import React from 'react'\n\nexport default ({ children }) => (\n  <div\n    style={{\n      padding: 20,\n      backgroundColor: 'tomato',\n      color: 'white',\n    }}\n  >\n    {children}\n  </div>\n)\n"
  },
  {
    "path": "examples/webpack/src/hello.org",
    "content": "#+jsx: import Box from './box'\n\n* Hello\n\n#+begin_export jsx\nexport default ({ children }) =>\n  <div style={{ padding: 20 }}>\n    <h1 style={{ color: 'blue' }}>Orga + Webpack</h1>\n    {children}\n  </div>\n#+end_export\n\nThis is *org-mode* with /JSX/!\n\n-----\n\n#+begin_export jsx\n<Box>the tomato box</Box>\n#+end_export\n\n"
  },
  {
    "path": "examples/webpack/src/index.js",
    "content": "import React from 'react'\nimport { createRoot } from 'react-dom/client'\nimport Hello from './hello.org'\n\nconst root = createRoot(document.getElementById('root'))\nroot.render(<Hello />)\n"
  },
  {
    "path": "examples/webpack/webpack.config.mjs",
    "content": "export default {\n  mode: 'development',\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        use: 'babel-loader',\n        exclude: /node_modules/,\n      },\n      {\n        test: /\\.org$/,\n        use: ['@orgajs/loader'],\n      },\n    ],\n  },\n}\n"
  },
  {
    "path": "orga.config.js",
    "content": "import tailwindcss from '@tailwindcss/vite'\nimport rehypePrettyCode from 'rehype-pretty-code'\n\nexport const containerClass = 'prose p-4'\nexport const styles = ['docs/style.css']\nexport const vitePlugins = [tailwindcss()]\nexport const rehypePlugins = [[rehypePrettyCode, { theme: 'github-dark' }]]\nexport const root = 'docs'\nexport const exclude = ['config.d.ts']\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"orgajs\",\n\t\"private\": true,\n\t\"type\": \"module\",\n\t\"devDependencies\": {\n\t\t\"@biomejs/biome\": \"^2.4.4\",\n\t\t\"@changesets/cli\": \"^2.29.8\",\n\t\t\"@codemirror/lang-javascript\": \"^6.2.3\",\n\t\t\"@codemirror/language\": \"^6.10.8\",\n\t\t\"@codemirror/theme-one-dark\": \"^6.1.2\",\n\t\t\"@codemirror/view\": \"^6.36.2\",\n\t\t\"@lezer/highlight\": \"^1.2.1\",\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"@orgajs/react-cm\": \"workspace:^\",\n\t\t\"@orgajs/react-editor\": \"workspace:^\",\n\t\t\"@tailwindcss/typography\": \"^0.5.9\",\n\t\t\"@tailwindcss/vite\": \"^4.1.4\",\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"@types/react\": \"^19.1.2\",\n\t\t\"@types/react-dom\": \"^19.1.2\",\n\t\t\"daisyui\": \"^5.0.28\",\n\t\t\"orga-build\": \"workspace:^\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"rehype-pretty-code\": \"^0.14.1\",\n\t\t\"shiki\": \"^3.23.0\",\n\t\t\"tailwindcss\": \"^4.0.3\",\n\t\t\"type-coverage\": \"^2.29.7\",\n\t\t\"typescript\": \"^5.9.2\",\n\t\t\"unist-util-map\": \"4.0.0\",\n\t\t\"vfile\": \"^6.0.3\"\n\t},\n\t\"scripts\": {\n\t\t\"build\": \"pnpm -r --filter './packages/*' --if-present run build && tsc --build --clean && tsc --build && type-coverage\",\n\t\t\"clean\": \"tsc --build --clean\",\n\t\t\"lint\": \"biome lint .\",\n\t\t\"lint:fix\": \"biome lint . --write\",\n\t\t\"test\": \"pnpm run check && pnpm -r --filter './packages/*' --if-present run test\",\n\t\t\"format\": \"biome format --write .\",\n\t\t\"check\": \"biome check .\",\n\t\t\"check:fix\": \"biome check . --write\",\n\t\t\"changeset\": \"changeset\",\n\t\t\"ci:version\": \"changeset version\",\n\t\t\"ci:publish\": \"pnpm build && changeset publish\",\n\t\t\"docs\": \"orga-build\",\n\t\t\"docs:dev\": \"orga-build dev\"\n\t}\n}\n"
  },
  {
    "path": "packages/astro/README.org",
    "content": "* @orgajs/astro (Moved)\n\nThe Astro integration package has moved to a dedicated repository:\n\n[[https://github.com/orgapp/orga-astro][github.com/orgapp/orga-astro]]\n\nPlease use that repository for source code, issues, and releases.\n"
  },
  {
    "path": "packages/codemirror-lang/CHANGELOG.md",
    "content": "# @orgajs/cm-lang\n\n## 1.3.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/lezer@1.4.0\n\n## 1.2.1\n\n### Patch Changes\n\n- @orgajs/lezer@1.3.1\n\n## 1.2.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/lezer@1.3.0\n\n## 1.1.6\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n- Updated dependencies [e3ef3a5]\n  - @orgajs/lezer@1.2.1\n\n## 1.1.5\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/lezer@1.2.0\n\n## 1.1.4\n\n### Patch Changes\n\n- 0f825de5: update editor dependencies\n- Updated dependencies [0f825de5]\n  - @orgajs/lezer@1.1.4\n\n## 1.1.3\n\n### Patch Changes\n\n- @orgajs/lezer@1.1.3\n\n## 1.1.2\n\n### Patch Changes\n\n- Updated dependencies [ea032b35]\n  - @orgajs/lezer@1.1.2\n\n## 1.1.1\n\n### Patch Changes\n\n- ac322714: implement editor\n- Updated dependencies [ac322714]\n  - @orgajs/lezer@1.1.1\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/lezer@1.1.0\n"
  },
  {
    "path": "packages/codemirror-lang/index.js",
    "content": "/** @typedef {import('@lezer/common').SyntaxNode} SyntaxNode */\n\nimport {\n\tdefineLanguageFacet,\n\tfoldNodeProp,\n\tfoldService,\n\tLanguage,\n\tLanguageSupport,\n\tsyntaxTree\n} from '@codemirror/language'\nimport { parser as baseParser } from '@orgajs/lezer'\n\nconst data = defineLanguageFacet({})\n\n// --- folding ---\n\n/**\n * @param {SyntaxNode} node\n */\nfunction getHeadlineLevel(node) {\n\tif (node.type.name !== 'headline') return\n\tconst stars = node.getChild('stars')\n\tif (stars) {\n\t\tconst level = stars.to - stars.from\n\t\treturn level\n\t}\n}\n\n/**\n * @param {SyntaxNode} headerNode\n */\nfunction findSectionEnd(headerNode) {\n\tconst level = getHeadlineLevel(headerNode)\n\tif (level === undefined) throw new Error('Not a headline')\n\tlet last = headerNode\n\tfor (;;) {\n\t\tconst next = last.nextSibling\n\t\tif (!next) {\n\t\t\tbreak\n\t\t}\n\n\t\tconst l = getHeadlineLevel(next)\n\t\tif (l !== undefined && l <= level) {\n\t\t\treturn next.from - 1 // Escape the newline. TODO: is this safe?\n\t\t}\n\n\t\tlast = next\n\t}\n\n\treturn last.to\n}\n\nconst headerIndent = foldService.of((state, start, end) => {\n\tfor (\n\t\tlet /** @type {SyntaxNode | null} */ node = syntaxTree(state).resolveInner(\n\t\t\t\tend,\n\t\t\t\t-1\n\t\t\t);\n\t\tnode;\n\t\tnode = node.parent\n\t) {\n\t\tif (node.from < start) {\n\t\t\tbreak\n\t\t}\n\n\t\tif (!node.type.name.startsWith('headline')) {\n\t\t\tcontinue\n\t\t}\n\n\t\tconst upto = findSectionEnd(node)\n\t\tif (upto > end) {\n\t\t\treturn { from: end, to: upto }\n\t\t}\n\t}\n\n\treturn null\n})\n\nconst parser = baseParser.configure({\n\tprops: [\n\t\tfoldNodeProp.add((type) => {\n\t\t\tif (type.name !== 'headline') {\n\t\t\t\treturn undefined\n\t\t\t}\n\n\t\t\treturn (tree, state) => ({\n\t\t\t\tfrom: state.doc.lineAt(tree.from).to,\n\t\t\t\tto: state.doc.lineAt(tree.from).to\n\t\t\t})\n\t\t})\n\t]\n})\n\n/**\n * @param {any} parser\n */\nfunction mkLang(parser) {\n\treturn new Language(data, parser, [headerIndent], 'org')\n}\n\nexport function org() {\n\tconst lang = mkLang(parser)\n\treturn new LanguageSupport(lang)\n}\n\nexport { tags } from '@orgajs/lezer'\n"
  },
  {
    "path": "packages/codemirror-lang/package.json",
    "content": "{\n\t\"name\": \"@orgajs/cm-lang\",\n\t\"version\": \"1.3.0\",\n\t\"description\": \"codemirror language: org\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"scripts\": {},\n\t\"keywords\": [\n\t\t\"org\",\n\t\t\"org-mode\",\n\t\t\"orgajs\",\n\t\t\"orga\",\n\t\t\"codemirror\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com:orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/cm-lang\"\n\t},\n\t\"dependencies\": {\n\t\t\"@codemirror/language\": \"^6.10.8\",\n\t\t\"@orgajs/lezer\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@codemirror/state\": \"^6.5.2\",\n\t\t\"@lezer/common\": \"^1.1.1\"\n\t}\n}\n"
  },
  {
    "path": "packages/codemirror-lang/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/editor/CHANGELOG.md",
    "content": "# @orgajs/editor\n\n## 1.4.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 1.4.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/cm-lang@1.3.0\n\n## 1.3.1\n\n### Patch Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n  - @orgajs/cm-lang@1.2.1\n\n## 1.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/cm-lang@1.2.0\n\n## 1.2.2\n\n### Patch Changes\n\n- 2f7b62d: fix package.json file\n\n## 1.2.1\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n- Updated dependencies [e3ef3a5]\n  - @orgajs/cm-lang@1.1.6\n\n## 1.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- @orgajs/cm-lang@1.1.5\n\n## 1.1.7\n\n### Patch Changes\n\n- 0f825de5: update editor dependencies\n- Updated dependencies [0f825de5]\n  - @orgajs/cm-lang@1.1.4\n\n## 1.1.6\n\n### Patch Changes\n\n- e9564ff5: remove opinionated extensions from default editor\n\n## 1.1.5\n\n### Patch Changes\n\n- 0ffa3415: cleanup theme\n\n## 1.1.4\n\n### Patch Changes\n\n- dc3a9db2: cleanup editor\n\n## 1.1.3\n\n### Patch Changes\n\n- 7cfff79a: headline elements (stars, todo keywords and priority) end after the whitespaces\n  - @orgajs/cm-lang@1.1.3\n\n## 1.1.2\n\n### Patch Changes\n\n- ea032b35: bug fix, link generating button\n  - @orgajs/cm-lang@1.1.2\n\n## 1.1.1\n\n### Patch Changes\n\n- ac322714: implement editor\n- Updated dependencies [ac322714]\n  - @orgajs/cm-lang@1.1.1\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/cm-lang@1.1.0\n"
  },
  {
    "path": "packages/editor/README.org",
    "content": "* TODO Quick Start\n\n* Customization\n** TODO Write a Theme\n** TODO key bindings\n"
  },
  {
    "path": "packages/editor/index.js",
    "content": "/**\n * @typedef {import('./lib/editor.js').Config} EditorConfig\n */\n\nexport { tags } from '@orgajs/cm-lang'\nexport { makeEditor } from './lib/editor.js'\nexport { settings } from './lib/settings.js'\nexport { setup } from './lib/setup.js'\n"
  },
  {
    "path": "packages/editor/lib/actions/fold.js",
    "content": "/**\n * @file Actions to shift sections.\n *\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {import('@lezer/common').Tree} Tree\n * @typedef {import('@lezer/common').SyntaxNode} Node\n * @typedef {import('@codemirror/state').ChangeSpec} ChangeSpec\n */\nimport {\n\tfoldAll,\n\tfoldCode,\n\tfoldState,\n\tunfoldAll,\n\tunfoldCode\n} from '@codemirror/language'\nimport { EditorState } from '@codemirror/state'\nimport { selectedLines } from './utils'\n\n/**\n * @param {EditorView} view\n */\nexport function toggleFold(view) {\n\tconst { state } = view\n\n\tconst lines = selectedLines(view)\n\tfor (const line of lines) {\n\t\tconst folded = findFold(state, line.from, line.to)\n\t\tif (folded) {\n\t\t\tunfoldCode(view)\n\t\t} else {\n\t\t\tfoldCode(view)\n\t\t}\n\t}\n\treturn true\n}\n\n/**\n * @param {EditorState} state\n * @param {number} from\n * @param {number} to\n */\nfunction findFold(state, from, to) {\n\t/** @type {{from:number, to:number} | null} */ let found = null\n\tstate.field(foldState, false)?.between(from, to, (from, to) => {\n\t\tif (!found || found.from > from) found = { from, to }\n\t})\n\treturn found\n}\n\n/**\n * @param {EditorView} view\n */\nexport function toggleFoldAll(view) {\n\tconst state = view.state\n\tconst folds = state.field(foldState, false)\n\tif (folds?.size) {\n\t\tunfoldAll(view)\n\t} else {\n\t\tfoldAll(view)\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "packages/editor/lib/actions/shift.js",
    "content": "/**\n * @file Actions to shift sections.\n *\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {import('@lezer/common').Tree} Tree\n * @typedef {import('@lezer/common').SyntaxNode} Node\n * @typedef {import('@codemirror/state').ChangeSpec} ChangeSpec\n */\n\nimport { syntaxTree } from '@codemirror/language'\n\n/**\n * Shift the headline.\n * @param {number} delta - The number of spaces to shift. Positive values shift right, negative values shift left.\n * @param {boolean} [recursive=false] - Whether to shift subsections recursively.\n */\nexport function shift(delta, recursive = false) {\n\t/**\n\t * @param {EditorView} view\n\t */\n\treturn function (view) {\n\t\tconst { state } = view\n\t\tconst tree = syntaxTree(state)\n\t\tconst pos = state.selection.main.head\n\t\t// the selection must be in a headline\n\t\tconst headline = getHeadline(tree, pos)\n\t\tif (!headline) return false\n\t\t/** @type {ChangeSpec[]} */\n\t\tconst changes = []\n\t\tlet cancelled = false\n\t\tif (recursive === false) {\n\t\t\tconst stars = headline.getChild('stars')\n\t\t\tif (!stars || stars.to - stars.from + delta < 1) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tconst change = _shift(stars, delta)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t}\n\t\t} else {\n\t\t\tconst cursor = headline.cursor()\n\t\t\tconst change = _shift(headline, delta)\n\t\t\tif (change) {\n\t\t\t\tchanges.push(change)\n\t\t\t} else {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\twhile (cursor.nextSibling()) {\n\t\t\t\tif (cursor.type.name === 'headline') {\n\t\t\t\t\tconst change = _shift(cursor.node, delta)\n\t\t\t\t\tif (change) {\n\t\t\t\t\t\tchanges.push(change)\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcancelled = true\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (!cancelled && changes.length > 0) {\n\t\t\tview.dispatch({ changes })\n\t\t}\n\t\treturn true\n\t}\n}\n\n/**\n * shift the stars\n * @param {Node|null|undefined} node\n * @param {number} delta\n * @returns {ChangeSpec | undefined}\n */\nfunction _shift(node, delta) {\n\tif (!node) return undefined\n\tif (node.type.name === 'headline')\n\t\treturn _shift(node.getChild('stars'), delta)\n\tif (node.type.name !== 'stars') return\n\n\tif (delta > 0) {\n\t\treturn {\n\t\t\tfrom: node.from,\n\t\t\tinsert: '*'.repeat(delta)\n\t\t}\n\t}\n\tif (delta < 0 && node.to - node.from + delta >= 1) {\n\t\treturn {\n\t\t\tfrom: node.from,\n\t\t\tto: node.from - delta,\n\t\t\tinsert: ''\n\t\t}\n\t}\n}\n\n/**\n * @param {Tree} tree\n * @param {number} pos\n */\nfunction getHeadline(tree, pos) {\n\t/** @type {import('@lezer/common').NodeIterator | null} */\n\tlet iter = tree.resolveStack(pos)\n\twhile (iter) {\n\t\tconst name = iter.node.type.name\n\t\tif (name.startsWith('headline')) return iter.node\n\t\titer = iter.next\n\t}\n\treturn null\n}\n"
  },
  {
    "path": "packages/editor/lib/actions/todo.js",
    "content": "/**\n * @typedef {import('@codemirror/view').EditorView} EditorView\n */\n\nimport { syntaxTree } from '@codemirror/language'\nimport { parseTodoKeywords } from 'orga/todo'\nimport { settings } from '../settings'\nimport { getTodo } from './utils'\n\n/**\n * @param {EditorView} view\n */\nexport function toggleTodo(view) {\n\tconst { state } = view\n\tconst pos = state.selection.main.head\n\tconst tree = syntaxTree(state)\n\n\tconst _todo = getTodo(tree, pos)\n\tif (!_todo) return false\n\tconst content = state.sliceDoc(_todo.from, _todo.to)\n\tconst _settings = state.field(settings)\n\tconst t = parseTodoKeywords(_settings.todo)\n\tconst next = t.next(content)\n\tconst change = {\n\t\tfrom: _todo.from,\n\t\tto: _todo.to,\n\t\t...(next !== undefined && { insert: next })\n\t}\n\tview.dispatch({ changes: change })\n\tconsole.log({ todo: _todo, content, next })\n\treturn true\n}\n"
  },
  {
    "path": "packages/editor/lib/actions/utils.js",
    "content": "/**\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {import('@lezer/common').Tree} Tree\n */\n\n/**\n * @param {EditorView} view\n */\nexport function selectedLines(view) {\n\t/** @type {Array<import('@codemirror/view').BlockInfo>} */\n\tconst lines = []\n\tfor (const { head } of view.state.selection.ranges) {\n\t\tif (lines.some((l) => l.from <= head && l.to >= head)) continue\n\t\tlines.push(view.lineBlockAt(head))\n\t}\n\treturn lines\n}\n\n/**\n * @param {Tree} tree\n * @param {number} pos\n */\nexport function getTodo(tree, pos) {\n\tconst headline = getNode(tree, pos, 'headline')\n\treturn headline?.getChild('todo')\n}\n\n/**\n * @param {Tree} tree\n * @param {number} pos\n * @param {string} type\n */\nexport function getNode(tree, pos, type) {\n\t/** @type {import('@lezer/common').NodeIterator | null} */\n\tlet iter = tree.resolveStack(pos)\n\twhile (iter) {\n\t\tconst name = iter.node.type.name\n\t\tif (name === type) return iter.node\n\t\titer = iter.next\n\t}\n\treturn null\n}\n"
  },
  {
    "path": "packages/editor/lib/editor.js",
    "content": "/**\n * @callback OnChange\n * @param {EditorState} state\n */\n\n/**\n * @typedef Config\n * @property {Element} target\n * @property {string} [content='']\n * @property {import('@codemirror/state').Extension} [extensions=[]]\n * @property {boolean} [dark=false]\n * @property {OnChange} [onChange=() => {}]\n */\nimport { EditorState } from '@codemirror/state'\nimport { EditorView } from '@codemirror/view'\nimport { setup } from './setup.js'\n\n/**\n * @param {Config} config\n */\nexport function makeEditor(config) {\n\tconst { target, content = '', extensions = [], onChange } = config\n\tconst state = EditorState.create({\n\t\tdoc: content,\n\t\textensions: [setup, extensions]\n\t})\n\tconst editor = new EditorView({\n\t\tstate,\n\t\tparent: target,\n\t\tdispatch: (tr) => {\n\t\t\teditor.update([tr])\n\t\t\ttr.docChanged && onChange && onChange(editor.state)\n\t\t}\n\t})\n\n\treturn { editor }\n}\n"
  },
  {
    "path": "packages/editor/lib/extensions/cleanup.js",
    "content": "/**\n * @typedef Range\n * @property {number} from\n * @property {number} to\n *\n * @typedef {object} Options\n * @property {boolean} hideStars\n * @property {boolean} hideLinks\n */\nimport { syntaxTree } from '@codemirror/language'\nimport { Decoration, ViewPlugin } from '@codemirror/view'\nimport { parseTodoKeywords } from 'orga/todo'\nimport { settings } from '../settings'\n\n/**\n * @param {Range} a\n * @param {Range} b\n */\nfunction overlap(a, b) {\n\treturn a.from <= b.to && a.to >= b.from\n}\n\n/**\n * @param {Options} options\n */\nexport function cleanup(options) {\n\treturn ViewPlugin.define(\n\t\t(view) => {\n\t\t\tlet _data = createDecorations(view, options)\n\t\t\tlet _selection = view.state.selection.main\n\n\t\t\treturn {\n\t\t\t\tget decorations() {\n\t\t\t\t\treturn _data.decorations\n\t\t\t\t},\n\t\t\t\tget selection() {\n\t\t\t\t\treturn _selection\n\t\t\t\t},\n\t\t\t\tupdate(update) {\n\t\t\t\t\t_selection = update.state.selection.main\n\t\t\t\t\tif (update.docChanged) {\n\t\t\t\t\t\t_data = createDecorations(update.view, options)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdecorations: (v) => {\n\t\t\t\tconst { decorations, selection } = v\n\t\t\t\treturn decorations.update({\n\t\t\t\t\tfilter: (_from, _to, deco) => {\n\t\t\t\t\t\tconst revealRange = deco.spec.revealRange\n\t\t\t\t\t\tif (revealRange) {\n\t\t\t\t\t\t\treturn !overlap(revealRange, selection)\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t},\n\t\t\teventHandlers: {\n\t\t\t\t// cmd+click to open links\n\t\t\t\tmousedown(e, view) {\n\t\t\t\t\tconst pos = view.posAtCoords(e)\n\t\t\t\t\tif (!pos) return\n\t\t\t\t\tif (!e.metaKey) return\n\t\t\t\t\tthis.decorations.between(pos, pos, (_from, _to, deco) => {\n\t\t\t\t\t\tconst { tagName, attributes } = deco.spec\n\t\t\t\t\t\tif (tagName === 'a' && attributes) {\n\t\t\t\t\t\t\te.preventDefault()\n\t\t\t\t\t\t\t// TODO: is it possible to make it a real link?\n\t\t\t\t\t\t\t// I guess that'd be difficult because it's a fucking editor\n\t\t\t\t\t\t\twindow.open(deco.spec.attributes.href, '_blank')\n\t\t\t\t\t\t\treturn false\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t)\n}\n\n// TODO: this plugin is getting big, in terms of responsibility, break it down\n\n/**\n * @param {Range | null} reveal\n */\nfunction hide(reveal) {\n\treturn Decoration.replace({\n\t\trevealRange: reveal\n\t})\n}\n\n/**\n * @param {boolean} actionable\n */\nfunction todo(actionable) {\n\treturn Decoration.mark({\n\t\tattributes: {\n\t\t\tclass: 'cm-org-todo',\n\t\t\t'data-actionable': actionable.toString()\n\t\t}\n\t})\n}\n\n/**\n * @param {import('@codemirror/view').EditorView} view\n * @param {Options} options\n */\nfunction createDecorations(view, options) {\n\tconst _settings = view.state.field(settings)\n\tconst t = parseTodoKeywords(_settings.todo)\n\tlet decorations = Decoration.none\n\t/** @type {Range[]} */\n\tconst links = []\n\n\t/** @type {Range | null} */\n\tlet headlineRange = null\n\t/** @type {Range | null} */\n\tlet linkRange = null\n\tsyntaxTree(view.state).iterate({\n\t\tenter(node) {\n\t\t\tif (node.name.startsWith('headline')) {\n\t\t\t\theadlineRange = { from: node.from, to: node.to }\n\t\t\t}\n\n\t\t\tif (node.name === 'link') {\n\t\t\t\tlinkRange = { from: node.from, to: node.to }\n\t\t\t}\n\n\t\t\tif (node.name === 'url') {\n\t\t\t\tif (linkRange === null) return\n\t\t\t\t// get text of node\n\t\t\t\tconst text = view.state.doc.sliceString(node.from, node.to)\n\t\t\t\tdecorations = decorations.update({\n\t\t\t\t\tadd: [\n\t\t\t\t\t\tDecoration.mark({\n\t\t\t\t\t\t\ttagName: 'a',\n\t\t\t\t\t\t\tattributes: { class: 'cm-link', href: text.slice(1, -1) }\n\t\t\t\t\t\t}).range(linkRange.from, linkRange.to)\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (options.hideLinks && (node.name === 'url' || node.name === 'mark')) {\n\t\t\t\tdecorations = decorations.update({\n\t\t\t\t\tadd: [hide(linkRange).range(node.from, node.to)]\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (options.hideStars && node.name === 'stars') {\n\t\t\t\tconst revealRange = { from: headlineRange?.from, to: headlineRange?.to }\n\t\t\t\tdecorations = decorations.update({\n\t\t\t\t\tadd: [\n\t\t\t\t\t\tDecoration.replace({\n\t\t\t\t\t\t\trevealRange\n\t\t\t\t\t\t}).range(node.from, node.to)\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (node.name === 'todo') {\n\t\t\t\tconst content = view.state.doc.sliceString(node.from, node.to).trim()\n\t\t\t\tdecorations = decorations.update({\n\t\t\t\t\tadd: [todo(t.actionable(content)).range(node.from, node.to)]\n\t\t\t\t})\n\t\t\t}\n\n\t\t\tif (node.name === 'done') {\n\t\t\t\tdecorations = decorations.update({\n\t\t\t\t\tadd: [todo(false).range(node.from, node.to)]\n\t\t\t\t})\n\t\t\t}\n\t\t},\n\t\tleave: (node) => {\n\t\t\tif (node.name.startsWith('headline')) headlineRange = null\n\t\t\tif (node.name === 'link') linkRange = null\n\t\t}\n\t})\n\treturn { decorations, links }\n}\n"
  },
  {
    "path": "packages/editor/lib/settings.js",
    "content": "/**\n * @typedef {import('@codemirror/state').EditorState} EditorState\n *\n * @typedef {Object} TodoKeywordSet\n * @property {string[]} actionables - The keywords that represent actionable states (e.g. \"TODO\", \"NEXT\").\n * @property {string[]} done - The keywords that represent completed states (e.g. \"DONE\", \"CANCELLED\").\n *\n * @typedef {Object} Settings\n * @property {string} todo - The set of todo keywords used in the document.\n */\n\nimport { syntaxTree } from '@codemirror/language'\nimport { StateField } from '@codemirror/state'\n\nexport const settings = StateField.define({\n\tcreate(state) {\n\t\treturn extractSettings(state)\n\t},\n\tupdate(value, tr) {\n\t\tif (tr.docChanged) {\n\t\t\treturn extractSettings(tr.state)\n\t\t}\n\t\treturn value\n\t}\n})\n\n/**\n * @param {EditorState} state\n * @return {Settings}\n */\nfunction extractSettings(state) {\n\tconst tree = syntaxTree(state)\n\t/** @type {Settings} */\n\tconst settings = {\n\t\ttodo: 'TODO DONE'\n\t}\n\ttree.iterate({\n\t\tenter(node) {\n\t\t\tif (node.name === 'keyword') {\n\t\t\t\tconst content = state.doc.sliceString(node.from, node.to).trim()\n\t\t\t\tconst m = content.match(/^#\\+(\\w+):(?:[ \\t]+(.*))?$/y)\n\t\t\t\tif (!m) return true\n\t\t\t\tconst [_, key, value] = m\n\t\t\t\tif (!key || !value) return true\n\n\t\t\t\tif (key.toLowerCase() === 'todo') {\n\t\t\t\t\tsettings.todo = value.trim()\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t})\n\treturn settings\n}\n"
  },
  {
    "path": "packages/editor/lib/setup.js",
    "content": "import { defaultKeymap } from '@codemirror/commands'\nimport { bracketMatching, foldGutter } from '@codemirror/language'\nimport { EditorView, highlightActiveLine, keymap } from '@codemirror/view'\nimport { org } from '@orgajs/cm-lang'\nimport { toggleFold, toggleFoldAll } from './actions/fold.js'\nimport { shift } from './actions/shift.js'\nimport { toggleTodo } from './actions/todo'\nimport { cleanup } from './extensions/cleanup.js'\nimport { settings } from './settings'\nimport theme from './theme.js'\n\nconst keys = [\n\t{ key: 'Tab', run: toggleFold, shift: toggleFoldAll },\n\t{\n\t\tkey: 'Cmd-ArrowLeft',\n\t\trun: shift(-1),\n\t\tshift: shift(-1, true),\n\t\tpreventDefault: true\n\t},\n\t{\n\t\tkey: 'Cmd-ArrowRight',\n\t\trun: shift(1),\n\t\tshift: shift(1, true),\n\t\tpreventDefault: true\n\t},\n\t{\n\t\tkey: 'Cmd-x',\n\t\trun: toggleTodo,\n\t\tpreventDefault: true\n\t}\n]\n\nexport const setup = (() => [\n\torg(),\n\tsettings,\n\ttheme,\n\tkeymap.of([...keys, ...defaultKeymap]),\n\thighlightActiveLine(),\n\tfoldGutter({\n\t\topenText: '▾',\n\t\tclosedText: '▸'\n\t}),\n\tEditorView.lineWrapping,\n\tbracketMatching(),\n\tcleanup({ hideStars: false, hideLinks: true })\n])()\n"
  },
  {
    "path": "packages/editor/lib/theme.js",
    "content": "import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'\nimport { EditorView } from '@codemirror/view'\nimport { tags as t } from '@orgajs/cm-lang'\n\nconst theme = EditorView.baseTheme({\n\t'&': {\n\t\theight: '100%'\n\t},\n\t'.cm-link': {\n\t\tcursor: 'pointer'\n\t},\n\t'.cm-org-todo': {\n\t\tcolor: 'white',\n\t\tbackgroundColor: 'green',\n\t\tpadding: '0 2px',\n\t\tborderRadius: '2px',\n\t\tcursor: 'pointer'\n\t},\n\t'.cm-org-todo[data-actionable=\"true\"]': {\n\t\tbackgroundColor: 'red'\n\t}\n})\n\nconst baseStyle = HighlightStyle.define([\n\t{\n\t\ttag: [t.heading],\n\t\tfontWeight: 'bold',\n\t\ttextDecoration: 'underline'\n\t},\n\t{ tag: [t.keyword, t.strong], fontWeight: 'bold' },\n\t{ tag: t.emphasis, fontStyle: 'italic' },\n\t{\n\t\ttag: t.monospace,\n\t\tborderRadius: '4px',\n\t\tpadding: '1px 4px',\n\t\tfontFamily: \"'JetBrains Mono', monospace\"\n\t},\n\t{ tag: t.strikethrough, textDecoration: 'line-through' },\n\t{ tag: t.underline, textDecoration: 'underline' }\n])\n\nconst lightColors = HighlightStyle.define(\n\t[\n\t\t{ tag: t.keyword, color: '#e45649' },\n\t\t{ tag: t.comment, color: '#9ca0a4' },\n\t\t{ tag: t.processingInstruction, color: '#9ca0a4' },\n\t\t{ tag: t.attributeName, color: '#9ca0a4' }\n\t],\n\t{ themeType: 'light' }\n)\n\nconst darkColors = HighlightStyle.define(\n\t[\n\t\t{ tag: t.keyword, color: 'green' },\n\t\t{ tag: t.comment, color: 'red' },\n\t\t{ tag: t.processingInstruction, color: 'gray' },\n\t\t{ tag: t.attributeName, color: 'gray' }\n\t],\n\t{ themeType: 'dark' }\n)\n\nexport default [\n\ttheme,\n\tsyntaxHighlighting(lightColors),\n\tsyntaxHighlighting(darkColors),\n\tsyntaxHighlighting(baseStyle)\n]\n"
  },
  {
    "path": "packages/editor/package.json",
    "content": "{\n\t\"name\": \"@orgajs/editor\",\n\t\"version\": \"1.4.1\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"description\": \"react org-mode editor based on prose-mirror\",\n\t\"scripts\": {},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/editor\"\n\t},\n\t\"keywords\": [\n\t\t\"org-mode\",\n\t\t\"CodeMirror\",\n\t\t\"editor\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"dependencies\": {\n\t\t\"@codemirror/commands\": \"^6.8.0\",\n\t\t\"@codemirror/language\": \"^6.10.8\",\n\t\t\"@codemirror/state\": \"^6.5.2\",\n\t\t\"@codemirror/view\": \"^6.36.2\",\n\t\t\"@orgajs/cm-lang\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@lezer/common\": \"^1.2.3\",\n\t\t\"orga\": \"workspace:^\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/editor/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/esbuild/CHANGELOG.md",
    "content": "# @orgajs/esbuild\n\n## 1.1.5\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/orgx@2.6.1\n\n## 1.1.4\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/orgx@2.6.0\n\n## 1.1.3\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.2\n\n## 1.1.2\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.1\n\n## 1.1.1\n\n### Patch Changes\n\n- 8451164: move orga-build to esbuild\n\n## 1.1.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/orgx@2.5.0\n\n## 1.0.1\n\n### Patch Changes\n\n- Updated dependencies [e3ef3a5]\n  - @orgajs/orgx@2.4.1\n\n## 1.0.0\n\n### Major Changes\n\n- 351f690: introduce @orgajs/node-loader, @orgajs/esbuild, @orgajs/build\n\n  - @orgajs/node-loader : the nodejs loader for org-mode files\n  - @orgajs/esbuild : esbuild plugin\n  - @orgajs/build : static site generator, a.k.a orga-build\n\n### Patch Changes\n\n- Updated dependencies [351f690]\n  - @orgajs/orgx@2.4.0\n"
  },
  {
    "path": "packages/esbuild/index.js",
    "content": "/**\n * @import { CompileOptions } from '@orgajs/orgx'\n * @import {\n      OnLoadResult,\n      PluginBuild\n * } from 'esbuild'\n */\nimport fs from 'node:fs/promises'\nimport { compile } from '@orgajs/orgx'\nimport { SourceMapGenerator } from 'source-map'\nimport { VFile } from 'vfile'\n\nconst name = '@orgajs/esbuild'\n\n/**\n * Create Node.js hooks to handle org files.\n *\n * @param {Readonly<CompileOptions> | null | undefined} [options]\n *   Configuration (optional).\n * @returns\n *   Node.js hooks.\n */\nfunction esbuild(options) {\n\treturn {\n\t\tname,\n\t\tsetup\n\t}\n\n\t/**\n\t * @param {PluginBuild} build\n\t *   Build.\n\t * @returns {undefined}\n\t *   Nothing.\n\t */\n\tfunction setup(build) {\n\t\tbuild.onLoad({ filter: /\\.org$/ }, onload)\n\t}\n\n\t/**\n\t * @param {any} data\n\t *   Data.\n\t * @returns {Promise<OnLoadResult>}\n\t *   Result.\n\t */\n\tasync function onload(data) {\n\t\tconst document = String(\n\t\t\tdata.pluginData &&\n\t\t\t\tdata.pluginData.contents !== null &&\n\t\t\t\tdata.pluginData.contents !== undefined\n\t\t\t\t? data.pluginData.contents\n\t\t\t\t: await fs.readFile(data.path)\n\t\t)\n\n\t\tconst file = new VFile({ path: data.path, value: document })\n\t\tconst code = await compile(file, { ...options, SourceMapGenerator })\n\t\tconst contents =\n\t\t\tString(code) +\n\t\t\t'\\n' +\n\t\t\t'//# sourceMappingURL=data:application/json;base64,' +\n\t\t\tBuffer.from(JSON.stringify(file.map)).toString('base64') +\n\t\t\t'\\n'\n\n\t\treturn {\n\t\t\tcontents\n\t\t}\n\t}\n}\n\nexport default esbuild\n"
  },
  {
    "path": "packages/esbuild/package.json",
    "content": "{\n\t\"name\": \"@orgajs/esbuild\",\n\t\"version\": \"1.1.5\",\n\t\"description\": \"esbuild plugin for orgajs\",\n\t\"type\": \"module\",\n\t\"exports\": \"./index.js\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.d.ts.map\",\n\t\t\"index.d.ts\",\n\t\t\"index.js\"\n\t],\n\t\"scripts\": {},\n\t\"license\": \"MIT\",\n\t\"keywords\": [\n\t\t\"esbuild\",\n\t\t\"jsx\",\n\t\t\"org-mode\",\n\t\t\"react\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/esbuild\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"source-map\": \"^0.7.4\",\n\t\t\"vfile\": \"^6.0.3\"\n\t},\n\t\"devDependencies\": {\n\t\t\"esbuild\": \"^0.24.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/CHANGELOG.md",
    "content": "# @orgajs/lezer\n\n## 1.4.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - orga@4.7.1\n\n## 1.4.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - orga@4.6.0\n\n## 1.3.1\n\n### Patch Changes\n\n- Updated dependencies [60ad38f]\n  - orga@4.5.1\n\n## 1.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - orga@4.5.0\n\n## 1.2.1\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n\n## 1.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - orga@4.4.0\n\n## 1.1.4\n\n### Patch Changes\n\n- 0f825de5: update editor dependencies\n\n## 1.1.3\n\n### Patch Changes\n\n- Updated dependencies [7cfff79a]\n  - orga@4.3.0\n\n## 1.1.2\n\n### Patch Changes\n\n- ea032b35: bug fix, link generating button\n\n## 1.1.1\n\n### Patch Changes\n\n- ac322714: implement editor\n- Updated dependencies [ac322714]\n  - orga@4.2.0\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - orga@4.1.0\n"
  },
  {
    "path": "packages/lezer/README.org",
    "content": "#+title: Lezer Parser for org-mode\n\n* Tasks\n\n** TODO properly support incremental parsing\n** TODO finish nodes design\n** TODO finish handlers\n** TODO cleanup dependencies\n"
  },
  {
    "path": "packages/lezer/index.js",
    "content": "export { OrgParser, parser } from './lib/index.js'\nexport { tags } from './lib/nodes.js'\n"
  },
  {
    "path": "packages/lezer/lib/context.js",
    "content": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n * @typedef {import('@lezer/common').TreeFragment} TreeFragment\n * @typedef {import('./fragments.js').FragmentCursor} FragmentCursor\n */\n\nimport { getSettings, makeParser } from 'orga'\nimport { fragmentCursor } from './fragments.js'\nimport { nodes } from './nodes.js'\nimport { toLezer } from './oast-to-lezer.js'\nimport { treeBuilder } from './tree.js'\n\n/**\n * @param {import('./index.js').OrgParser} config\n * @param {Input} input\n * @param {TreeFragment[]} _fragments\n * @param {{from: number, to: number}[]} ranges\n * @returns {PartialParse}\n */\nexport function parseContext(config, input, _fragments, ranges) {\n\tconst { log, nodeSet } = config\n\tlet cursor = ranges[0].from\n\tconst end = ranges[ranges.length - 1].to\n\tconst rangeI = 0\n\t/** @type {number | null} */\n\tlet stoppedAt = null\n\tconst full = input.read(0, input.length)\n\n\tconst builder = treeBuilder(nodeSet, nodes.document, 0, cursor, 0, 0)\n\n\tconst fragments = _fragments.length\n\t\t? fragmentCursor(config, _fragments, input)\n\t\t: null\n\n\t// Read settings directly from document text\n\tconst settings = getSettings(full)\n\n\t/** @type {import('orga').Parser | null} */\n\tlet parser = null\n\n\t/**\n\t * check if we reached the end of the input (ranges)\n\t * finish the block in parser if exist\n\t * check if we can reuse a fragment\n\t * @returns {import('@lezer/common').Tree | null}\n\t */\n\tfunction advance() {\n\t\tlog('advance called', cursor, end)\n\t\t// TODO: should we set an end to the tree?\n\t\t// will take a look when this actually happens\n\t\tif (stoppedAt != null && cursor > stoppedAt) return builder.build()\n\n\t\tif (cursor >= end) {\n\t\t\t// end of the tree has to match the end of the input\n\t\t\t// sometimes the the chidren does not fill the whole tree\n\t\t\t// which causes the end of the tree to be smaller than the end of the input\n\t\t\t// set it to the end of the input will prevent unnecessary parsing\n\t\t\treturn builder.build(end)\n\t\t}\n\n\t\tif (fragments !== null && couldReuse(fragments)) {\n\t\t\tconst result = fragments.takeNodes(cursor, ranges, rangeI)\n\t\t\tif (result.taken > 0) {\n\t\t\t\twrapUpParser()\n\t\t\t\tbuilder.addChildren(result.nodes, result.positions)\n\t\t\t\tcursor += result.taken\n\t\t\t\treturn null\n\t\t\t} else {\n\t\t\t\tlog('took nothing')\n\t\t\t}\n\t\t}\n\n\t\tif (!parser) {\n\t\t\tlog('-- creating parser --', cursor, end)\n\n\t\t\tparser = makeParser(full, {\n\t\t\t\trange: { start: cursor, end },\n\t\t\t\tsettings,\n\t\t\t\tflat: true\n\t\t\t})\n\t\t}\n\n\t\t// parser.advance should finish a block\n\t\tconst document = parser.advance()\n\t\tif (typeof document === 'number') {\n\t\t\tcursor = document\n\t\t\treturn null\n\t\t}\n\n\t\twrapUpParser()\n\t\treturn null\n\t}\n\n\tfunction wrapUpParser() {\n\t\tif (!parser) return\n\t\tconst document = parser.finish()\n\t\tlog(\n\t\t\t`wrap up parser: ${document.children.length}, ${document.position?.start.offset}, ${document.position?.end.offset}`\n\t\t)\n\n\t\tconst tree = toLezer(document, nodeSet)\n\t\tlog(document)\n\t\tlog(tree)\n\t\tbuilder.takeChildren(tree, document.position?.start.offset)\n\t\tbuilder.takeProps(tree)\n\t\tif (document.position?.end.offset) cursor = document.position.end.offset\n\t\tlog('-- destroying parser --')\n\t\tparser = null\n\t}\n\n\t/**\n\t * check if we can reuse nodes from fragments\n\t * @param {FragmentCursor} fragments\n\t */\n\tfunction couldReuse(fragments) {\n\t\tconst hash = builder.hash\n\t\t// TODO: pass the real lineStart\n\t\tif (!fragments.moveTo(cursor, cursor)) return false\n\t\tif (!fragments.matches(hash)) return false\n\t\treturn true\n\t}\n\n\treturn {\n\t\tget parsedPos() {\n\t\t\tlog('parsedPos called', cursor)\n\t\t\t// if return undefined, the call of advance was not as intense\n\t\t\treturn cursor\n\t\t\t// return parser.now\n\t\t},\n\t\tadvance,\n\t\tstopAt(pos) {\n\t\t\tlog('stopAt called', pos, stoppedAt)\n\t\t\tif (stoppedAt != null && stoppedAt < pos)\n\t\t\t\tthrow new RangeError(\"Can't move stoppedAt forward\")\n\t\t\tstoppedAt = pos\n\t\t},\n\t\tget stoppedAt() {\n\t\t\treturn stoppedAt\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/lib/fragments.js",
    "content": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n * @typedef {import('@lezer/common').TreeFragment} TreeFragment\n * @typedef {import('@lezer/common').TreeCursor} TreeCursor\n *\n * @typedef TakeNodesResult\n * @property {Tree[]} nodes\n * @property {number[]} positions\n * @property {number} taken\n *\n * @typedef FragmentCursor\n * @property {(pos: number, lineStart: number) => boolean} moveTo\n * @property {(hash: number) => boolean} matches\n * @property {(start: number, ranges: {from: number, to: number}[], rangeI: number) => TakeNodesResult} takeNodes\n */\n\nimport { NodeProp, Tree } from '@lezer/common'\nimport { nodes } from './nodes.js'\n\n/**\n * @param {import('./index.js').OrgParser} config\n * @param {TreeFragment[]} fragments\n * @param {Input} input\n * @returns {FragmentCursor}\n */\nexport function fragmentCursor({ log, nodeSet }, fragments, input) {\n\tlet i = 0\n\t/** @type {TreeCursor | null} */\n\tlet cursor = null\n\t/** @type {TreeFragment | null} */\n\tlet fragment = fragments.length ? fragments[i++] : null\n\tlet fragmentEnd = -1\n\n\treturn {\n\t\tmoveTo,\n\t\tmatches,\n\t\ttakeNodes\n\t}\n\n\tfunction nextFragment() {\n\t\tfragment = i < fragments.length ? fragments[i++] : null\n\t\tcursor = null\n\t\tfragmentEnd = -1\n\t}\n\n\t/**\n\t * move the cursor to the first block after `pos`.\n\t * @param {number} pos\n\t * @param {number} lineStart\n\t */\n\tfunction moveTo(pos, lineStart) {\n\t\twhile (fragment && fragment.to < pos) nextFragment()\n\t\tif (!fragment || fragment.from > (pos ? pos - 1 : 0)) {\n\t\t\treturn false\n\t\t}\n\n\t\tfragmentEnd = fragment.to\n\n\t\tif (fragmentEnd < 0) {\n\t\t\tlet end = fragment.to\n\t\t\twhile (end > 0 && input.read(end - 1, end) !== '\\n') end--\n\t\t\tfragmentEnd = end ? end - 1 : 0\n\t\t}\n\n\t\tconst c = cursor || fragment.tree.cursor()\n\t\tif (!cursor) {\n\t\t\tcursor = c\n\t\t\tc.firstChild()\n\t\t}\n\t\t// if (!c) {\n\t\t//   c = cursor = fragment.tree.cursor()\n\t\t//   c?.firstChild()\n\t\t// }\n\n\t\tconst rPos = pos + fragment.offset\n\t\twhile (c.to <= rPos) if (!c.parent()) return false\n\t\tfor (;;) {\n\t\t\tif (c.from >= rPos) return fragment.from <= lineStart\n\t\t\tif (!c.childAfter(rPos)) return false\n\t\t}\n\t}\n\n\t/**\n\t * @param {number} hash\n\t */\n\tfunction matches(hash) {\n\t\tconst tree = cursor?.tree\n\t\tconst result = tree ? tree.prop(NodeProp.contextHash) === hash : false\n\t\tif (result) {\n\t\t\tlog('✅ fragment matches, reusing', {\n\t\t\t\thash,\n\t\t\t\tnp: tree?.prop(NodeProp.contextHash)\n\t\t\t})\n\t\t} else {\n\t\t\tlog('❌ fragment does not match, not reusing', {\n\t\t\t\thash,\n\t\t\t\tnp: tree?.prop(NodeProp.contextHash)\n\t\t\t})\n\t\t}\n\t\treturn result\n\t}\n\n\t/**\n\t * @param {number} start\n\t * @param {{from: number, to: number}[]} ranges\n\t * @param {number} rangeI\n\t * @returns {TakeNodesResult}\n\t */\n\tfunction takeNodes(start, ranges, rangeI) {\n\t\t/** @type {TakeNodesResult} */\n\t\tconst result = {\n\t\t\tnodes: [],\n\t\t\tpositions: [],\n\t\t\ttaken: 0\n\t\t}\n\n\t\tlog('takeNodes', start, ranges, rangeI)\n\n\t\tif (!cursor || !fragment) return result\n\t\tconst cur = cursor\n\t\tconst off = fragment.offset\n\t\tlet end = start\n\t\t// let prevEnd = end\n\t\tlet blockI = 0\n\t\t// let prevI = 0\n\t\tconst fragEnd = fragmentEnd - (fragment.openEnd ? 1 : 0)\n\t\tfor (;;) {\n\t\t\tif (cur.to - off > fragEnd) {\n\t\t\t\tif (cur.type.isAnonymous && cur.firstChild()) continue\n\t\t\t\tlog(\n\t\t\t\t\t`stop takeNodes from ${cur.name}: fe: ${fragEnd} | ${fragmentEnd}, cur: ${cur.name}, cur.from: ${cur.from}, cur.to: ${cur.to}, off: ${off}`\n\t\t\t\t)\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconst pos = toRelative(cur.from - off, ranges)\n\t\t\tif (cur.to - off <= ranges[rangeI].to) {\n\t\t\t\t// Fits in current range\n\t\t\t\tlog(\n\t\t\t\t\t`Fits in current range, name: ${cur.name}, pos: ${pos}, cur.from: ${cur.from}, cur.to: ${cur.to}`\n\t\t\t\t)\n\t\t\t\tconst tree = cur.tree\n\n\t\t\t\tif (tree) {\n\t\t\t\t\tresult.nodes.push(tree)\n\t\t\t\t\tresult.positions.push(pos)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog('create dummy')\n\t\t\t\tconst dummy = new Tree(\n\t\t\t\t\tnodeSet.types[nodes.paragraph],\n\t\t\t\t\t[],\n\t\t\t\t\t[],\n\t\t\t\t\t0\n\t\t\t\t\t// cx.block.hashProp\n\t\t\t\t)\n\t\t\t\tresult.nodes.push(dummy)\n\t\t\t\tresult.positions.push(pos)\n\t\t\t\t// reuse dummy?\n\t\t\t}\n\n\t\t\tif (cur.type.is('Block')) {\n\t\t\t\tlog('got block:', cur.type.name)\n\t\t\t\tend = cur.to - off\n\t\t\t\tblockI = result.nodes.length\n\t\t\t}\n\t\t\tif (!cur.nextSibling()) break\n\t\t}\n\t\tlog(`>> popping: ${blockI} / ${result.nodes.length}`)\n\t\tlog('node:', result.nodes.map((n) => n.type.name).join(','))\n\t\twhile (result.nodes.length > blockI) {\n\t\t\tconst n = result.nodes.pop()\n\t\t\tlog('.. pop non blocks', n?.type.name)\n\t\t\tresult.positions.pop()\n\t\t}\n\n\t\tresult.taken = end - start\n\t\treturn result\n\t}\n}\n\n/**\n * Convert an input-stream-relative position to a\n * Markdown-doc-relative position by subtracting the size of all input\n * gaps before `abs`.\n * @param {number} abs\n * @param {{from: number, to: number}[]} ranges\n */\nfunction toRelative(abs, ranges) {\n\tlet pos = abs\n\tfor (let i = 1; i < ranges.length; i++) {\n\t\tconst gapFrom = ranges[i - 1].to,\n\t\t\tgapTo = ranges[i].from\n\t\tif (gapFrom < abs) pos -= gapTo - gapFrom\n\t}\n\treturn pos\n}\n"
  },
  {
    "path": "packages/lezer/lib/handlers.js",
    "content": "/**\n * @typedef {import('./types.js').Seed} Seed\n * @typedef {import('./types.js').Handler} Handler\n\n * @typedef {Record<string, Handler>} Handlers\n *   Handle nodes.\n\n */\nimport { NodeProp } from '@lezer/common'\nimport { nodes } from './nodes.js'\n\n// class NodeProp extends _NodeProp {\n//   static path = new _NodeProp({ perNode: true })\n// }\n\n/** @type {NodeProp<{level: number}>} */\nexport const headlineProp = new NodeProp({ perNode: true })\n\nexport const documentProp = new NodeProp({\n\tperNode: true\n\t// deserialize: (str) => {\n\t// \tconsole.log('deserialize', str)\n\t// \treturn str\n\t// }\n})\n\n/**\n * @type {Handlers}\n */\nexport const handlers = {\n\tdocument: (_s, doc) => {\n\t\tif (doc.type !== 'document') {\n\t\t\treturn false\n\t\t}\n\t\treturn {\n\t\t\tid: nodes.document,\n\t\t\tprops: [[documentProp, doc.properties]]\n\t\t}\n\t},\n\theadline: (_s, node) => {\n\t\tif (node.type === 'headline') {\n\t\t\treturn {\n\t\t\t\tid: nodes.headline,\n\t\t\t\tprops: [[headlineProp, { level: node.level }]]\n\t\t\t}\n\t\t}\n\t\treturn false\n\t},\n\tstars: () => nodes.stars,\n\ttodo: (_s, node) => {\n\t\tif (node.type !== 'todo') {\n\t\t\treturn false\n\t\t}\n\n\t\treturn nodes.todo\n\t},\n\t'link.path': () => nodes.url,\n\t// 'link.description': () => nodes.linkDescription,\n\tlink: () => nodes.link,\n\topening: () => nodes.mark,\n\tclosing: () => nodes.mark,\n\tblock: () => nodes.block,\n\thtml: () => nodes.html,\n\tjsx: () => nodes.jsx,\n\t'block.begin': () => nodes.blockBegin,\n\t'block.end': () => nodes.blockEnd,\n\ttags: () => nodes.marker,\n\tkeyword: () => nodes.keyword,\n\tparagraph: () => nodes.paragraph,\n\tlist: () => nodes.list,\n\t'list.item.bullet': () => nodes.marker,\n\ttext: (_, node) => {\n\t\tif (node.type !== 'text') {\n\t\t\treturn false\n\t\t}\n\t\tswitch (node.style) {\n\t\t\tcase 'bold':\n\t\t\t\treturn nodes.bold\n\t\t\tcase 'italic':\n\t\t\t\treturn nodes.italic\n\t\t\tcase 'strikeThrough':\n\t\t\t\treturn nodes.strikeThrough\n\t\t\tcase 'code':\n\t\t\t\treturn nodes.code\n\t\t\tcase 'verbatim':\n\t\t\t\treturn nodes.code\n\t\t\tcase 'underline':\n\t\t\t\treturn nodes.underline\n\t\t}\n\t\treturn false\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/lib/index.js",
    "content": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n * @typedef {import('@lezer/common').TreeFragment} TreeFragment\n */\n\n/**\n * @typedef OrgParserConfig\n * @property {import('@lezer/common').NodePropSource[] | undefined | null} props\n */\n\nimport { NodeSet, Parser } from '@lezer/common'\nimport { parseContext } from './context.js'\nimport { nodeSet } from './nodes.js'\n\nexport { tags } from './nodes.js'\n\nexport class OrgParser extends Parser {\n\t/**\n\t * @param {NodeSet} nodeSet\n\t * @param {(...data: any[]) => void} [log]\n\t */\n\tconstructor(nodeSet, log = () => {}) {\n\t\tsuper()\n\t\tthis.nodeSet = nodeSet\n\t\tthis.log = log\n\t}\n\n\t/**\n\t * @param {Input} input\n\t * @param {TreeFragment[]} fragments\n\t * @param {{from: number, to: number}[]} ranges\n\t * @returns {PartialParse}\n\t */\n\tcreateParse(input, fragments, ranges) {\n\t\tconst r = ranges.map((r) => `${r.from}-${r.to}`).join(', ')\n\t\tconst frags = fragments\n\t\t\t.map(\n\t\t\t\t(f) => `(${f.from}-${f.to}, offset: ${f.offset}, openEnd: ${f.openEnd})`\n\t\t\t)\n\t\t\t.join(' ')\n\t\t// TODO: add info more about fragments, how do I use ranges vs fragments?\n\t\tthis.log(`createParse`, `ranges: (${r}), frags: [${frags}]`)\n\t\tconst parse = parseContext(this, input, fragments, ranges)\n\t\treturn parse\n\t}\n\n\t/**\n\t * @param {OrgParserConfig} config\n\t */\n\tconfigure(config) {\n\t\tlet { nodeSet } = this\n\t\tconst nodeTypes = nodeSet.types.slice()\n\n\t\tnodeSet = new NodeSet(nodeTypes)\n\t\tif (config.props && config.props.length > 0) {\n\t\t\tnodeSet = nodeSet.extend(...config.props)\n\t\t}\n\t\treturn new OrgParser(nodeSet, this.log)\n\t}\n}\n\nexport const parser = new OrgParser(\n\tnodeSet,\n\tconsole.log.bind(console, 'orga-parser')\n)\n"
  },
  {
    "path": "packages/lezer/lib/nodes.js",
    "content": "import { NodeProp, NodeSet, NodeType } from '@lezer/common'\nimport { styleTags, Tag, tags as t } from '@lezer/highlight'\n\nlet i = 0\nexport const nodes = Object.freeze({\n\tnone: i++,\n\t// block\n\tdocument: i++,\n\theadline: i++,\n\tparagraph: i++,\n\tkeyword: i++,\n\tblock: i++,\n\tlist: i++,\n\thtml: i++,\n\tjsx: i++,\n\t// inline\n\tstars: i++,\n\ttodo: i++,\n\tdone: i++,\n\tlink: i++,\n\tmarker: i++,\n\tbold: i++,\n\titalic: i++,\n\tcode: i++,\n\tstrikeThrough: i++,\n\tunderline: i++,\n\turl: i++,\n\tblockBegin: i++,\n\tblockEnd: i++,\n\t// smaller\n\tmark: i++\n})\n\n/**\n * @type {NodeProp<{level: number}>}\n */\nexport const headlineProp = new NodeProp()\n\n/** @type {NodeType[]} */\nexport const nodeTypes = Object.entries(nodes).map(([name, id]) =>\n\tNodeType.define({\n\t\tid,\n\t\tname,\n\t\tprops: id >= nodes.stars ? [] : [[NodeProp.group, ['Block']]],\n\t\ttop: name === 'document'\n\t})\n)\n\n// extra tags\nconst underline = Tag.define(t.content)\n\nconst orgHighlighting = styleTags({\n\t'headline/...': t.heading,\n\tkeyword: t.attributeName,\n\tlink: t.link,\n\t'stars mark blockBegin blockEnd': t.processingInstruction,\n\titalic: t.emphasis,\n\tbold: t.strong,\n\tstrikeThrough: t.strikethrough,\n\tparagraph: t.content,\n\tlist: t.list,\n\tunderline: underline,\n\t'html jsx code block': t.monospace\n})\n\nexport const tags = {\n\t...t,\n\tunderline\n}\n\nexport const nodeSet = new NodeSet(nodeTypes).extend(orgHighlighting)\n"
  },
  {
    "path": "packages/lezer/lib/oast-to-lezer.js",
    "content": "/**\n * @typedef {import('orga').Document} OrgTree\n * @typedef {import('@lezer/common').Tree} LezerTree\n * @typedef {import('@lezer/common').NodeSet} NodeSet\n * @typedef {import('orga').Document} OastRoot\n * @typedef {import('orga').Content} OastContent\n * @typedef {import('orga').Parent} OastParent\n\n * @callback Mapping\n *   Transform an oast node to prose node.\n * @param {OastNodes} node\n * @param {number} id\n * @param {Array<LezerTree> | undefined} [children]\n * @returns {LezerTree | null | undefined}\n\n * @typedef {import('./types.js').State} ParseState\n */\nimport { NodeProp, Tree } from '@lezer/common'\nimport { handlers } from './handlers.js'\n\n/**\n * @param {import('vfile').VFile | null} file\n * @param {NodeSet} nodeSet\n * @returns {ParseState}\n */\nfunction createParseState(file, nodeSet) {\n\t/** @type {ParseState} */\n\tconst state = {\n\t\tfile,\n\t\tignore: ['newline', 'emptyLine'],\n\t\tnodeSet: nodeSet,\n\t\thandlers,\n\t\tone(node, parent, base = 0) {\n\t\t\treturn one(this, node, parent, base)\n\t\t},\n\t\tall(parent, base) {\n\t\t\treturn all(this, parent, base)\n\t\t}\n\t}\n\treturn state\n}\n\n/**\n * @param {OrgTree} tree\n * @param {NodeSet} nodeSet\n * @param {import('vfile').VFile | null} [file=null]\n * @returns {import('@lezer/common').Tree}\n */\nexport function toLezer(tree, nodeSet, file = null) {\n\t// TODO: inject gaps\n\tconst state = createParseState(file, nodeSet)\n\tconst result = state.one(tree)\n\tif (!result) {\n\t\tthrow new Error('no result')\n\t}\n\tconst t = result.nodes[0]\n\tconst _props = tree.properties\n\treturn t\n}\n\n/** @type {import('./types.js').Handler} */\nfunction defaultUnknownHandler() {\n\t// console.log('unknown node', n.type, n)\n\treturn true\n}\n\n/**\n * @param {import('./types.js').OastNode} node\n * @returns {[number, number]}\n */\nfunction getRange(node) {\n\tconst start = node.position?.start.offset || 0\n\tconst end = node.position?.end.offset || 0\n\treturn [start, end - start]\n}\n\n/**\n * @param {ParseState} state\n * @param {import('./types.js').OastNode} node\n * @param {OastParent | undefined} [parent]\n * @param {number} [base=0]\n * @returns {{nodes: LezerTree[], positions: number[]} | null | undefined}}\n */\nfunction one(state, node, parent, base = 0) {\n\tif (state.ignore.includes(node.type)) {\n\t\treturn state.all(node, base)\n\t}\n\n\tconst handler = state.handlers[node.type] || defaultUnknownHandler\n\tconst seed = handler(state, node, parent)\n\n\tif (typeof seed === 'boolean') {\n\t\tif (seed) {\n\t\t\treturn state.all(node, base)\n\t\t}\n\t\treturn null\n\t}\n\n\tlet [id, skip, props] =\n\t\ttypeof seed === 'number' ? [seed, false] : [seed.id, seed.skip, seed.props]\n\n\tconst [loc, len] = getRange(node)\n\tconst pos = loc - base\n\n\t/** @type {Tree[]} */\n\tlet nodes = []\n\t/** @type {number[]} */\n\tlet positions = []\n\tif (!skip) {\n\t\tconst result = state.all(node, loc)\n\t\tnodes = result.nodes\n\t\tpositions = result.positions\n\t}\n\n\tif (node.data?.hash !== undefined) {\n\t\tif (!props) {\n\t\t\tprops = []\n\t\t}\n\t\tprops.push([NodeProp.contextHash, node.data.hash])\n\t}\n\n\tconst tree = new Tree(state.nodeSet.types[id], nodes, positions, len, props)\n\tconst result = { nodes: [tree], positions: [pos] }\n\treturn result\n}\n\n/**\n * @param {ParseState} state\n * @param {import('./types.js').OastNode} parent\n * @param {number} base\n * @returns {{nodes: LezerTree[], positions: number[]}}}\n */\nfunction all(state, parent, base) {\n\t/** @type {Array<LezerTree>} */\n\tconst _nodes = []\n\t/** @type {Array<number>} */\n\tconst _positions = []\n\n\tif ('children' in parent) {\n\t\tlet index = -1\n\t\twhile (++index < parent.children.length) {\n\t\t\tconst node = parent.children[index]\n\t\t\tconst { nodes, positions } = state.one(node, parent, base) || {\n\t\t\t\tnodes: [],\n\t\t\t\tpositions: []\n\t\t\t}\n\t\t\t_nodes.push(...nodes)\n\t\t\t_positions.push(...positions)\n\t\t}\n\t}\n\treturn {\n\t\tnodes: _nodes,\n\t\tpositions: _positions\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/lib/tree.js",
    "content": "import { NodeProp, NodeType, Tree } from '@lezer/common'\nimport { documentProp } from './handlers.js'\n\n// import { nodes } from './nodes.js'\n\n/**\n * @param {number} type\n * @param {number} value\n * @param {number} [parentHash=0]\n */\nfunction hash(type, value, parentHash = 0) {\n\treturn (parentHash + (parentHash << 8) + type + (value << 4)) | 0\n}\n\n/**\n * @param {import('@lezer/common').NodeSet} nodeSet\n * @param {number} type\n * @param {number} value\n * @param {number} from\n * @param {number} parentHash\n * @param {number} originalEnd\n */\nexport function treeBuilder(\n\tnodeSet,\n\ttype,\n\tvalue,\n\tfrom,\n\tparentHash,\n\toriginalEnd\n) {\n\t/** @type {Tree[]} */\n\tconst children = []\n\t/** @type {number[]} */\n\tconst positions = []\n\n\tconst _hash = hash(type, value, parentHash)\n\n\t/** @type {[NodeProp<any>, any][]} */\n\tconst props = [[NodeProp.contextHash, _hash]]\n\n\treturn {\n\t\taddChild,\n\t\taddChildren,\n\t\ttakeChildren,\n\t\ttakeProps,\n\t\taddProps: (/** @type {[NodeProp<any>, any][]} */ p) => props.push(...p),\n\t\tbuild,\n\t\thash: _hash\n\t}\n\n\t/**\n\t * @param {Tree} child\n\t * @param {number} pos\n\t */\n\tfunction addChild(child, pos) {\n\t\tif (child.prop(NodeProp.contextHash) !== _hash)\n\t\t\tchild = new Tree(\n\t\t\t\tchild.type,\n\t\t\t\tchild.children,\n\t\t\t\tchild.positions,\n\t\t\t\tchild.length,\n\t\t\t\tprops\n\t\t\t)\n\t\tchildren.push(child)\n\t\tpositions.push(pos)\n\t}\n\n\t/**\n\t * @param {Tree[]} children\n\t * @param {number[]} positions\n\t */\n\tfunction addChildren(children, positions) {\n\t\tfor (let i = 0; i < children.length; i++)\n\t\t\taddChild(children[i], positions[i])\n\t}\n\n\t/**\n\t * @param {Tree} tree\n\t * @param {number} [offset=0]\n\t */\n\tfunction takeChildren(tree, offset = 0) {\n\t\t// addChildren(tree.children, tree.positions)\n\t\tconst cursor = tree.cursor()\n\t\tif (!cursor.firstChild()) return\n\t\tdo {\n\t\t\tconst child = cursor.tree\n\t\t\tif (!child) continue\n\t\t\t// TODO: is the position correct?\n\t\t\taddChild(child, cursor.from + offset)\n\t\t} while (cursor.nextSibling())\n\t}\n\n\t/**\n\t * @param {Tree} tree\n\t */\n\tfunction takeProps(tree) {\n\t\tconst doc = tree.prop(documentProp)\n\t\tif (doc) {\n\t\t\tprops.push([documentProp, doc])\n\t\t}\n\t}\n\n\t/**\n\t * @param {number} [end = originalEnd] - end of the tree\n\t * @returns {Tree}\n\t */\n\tfunction build(end = originalEnd) {\n\t\tconst last = children.length - 1\n\t\tif (last >= 0)\n\t\t\tend = Math.max(end, positions[last] + children[last].length + from)\n\n\t\tconst tree = new Tree(\n\t\t\tnodeSet.types[type],\n\t\t\tchildren,\n\t\t\tpositions,\n\t\t\tend - from\n\t\t).balance({\n\t\t\tmakeTree: (children, positions, length) =>\n\t\t\t\tnew Tree(NodeType.none, children, positions, length, props)\n\t\t})\n\n\t\treturn tree\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/lib/types.ts",
    "content": "import type { Tree as LezerTree, NodeSet } from '@lezer/common'\nimport type { Content, Document, Parent as OastParent, Token } from 'orga'\nimport type { Position } from 'unist'\nimport type { VFile } from 'vfile'\n\nexport type OastNode = Document | Content | Token\n\ntype Action = boolean\n\nexport type Seed =\n\t| {\n\t\t\tid: number\n\t\t\tposition?: Position\n\t\t\tprops?: any\n\t\t\tskip?: Action\n\t  }\n\t| Action\n\t| number\n\ninterface LezerChild {\n\tnode: LezerTree\n\tposition: number\n}\n\nexport type Handler = (\n\tstate: State,\n\tnode: OastNode,\n\tparent: OastParent | undefined\n) => Seed\n\nexport interface State {\n\tfile: VFile | null\n\tignore: string[]\n\treadonly nodeSet: NodeSet\n\thandlers: Record<string, Handler>\n\tone: (\n\t\tnode: OastNode,\n\t\tparent?: OastParent | undefined,\n\t\tbase?: number\n\t) => { nodes: LezerTree[]; positions: number[] } | null | undefined\n\tall: (\n\t\tnode: OastNode,\n\t\tbase: number\n\t) => { nodes: LezerTree[]; positions: number[] }\n}\n"
  },
  {
    "path": "packages/lezer/package.json",
    "content": "{\n\t\"name\": \"@orgajs/lezer\",\n\t\"version\": \"1.4.1\",\n\t\"description\": \"lezer parser for org-mode\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"scripts\": {\n\t\t\"test\": \"node --test tests/*.test.js\"\n\t},\n\t\"keywords\": [\n\t\t\"org-mode\",\n\t\t\"org\",\n\t\t\"parser\",\n\t\t\"lezer\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"url\": \"orgapp/orgajs\",\n\t\t\"directory\": \"packages/lezer\"\n\t},\n\t\"dependencies\": {\n\t\t\"@lezer/common\": \"^1.1.1\",\n\t\t\"@lezer/highlight\": \"^1.2.1\",\n\t\t\"orga\": \"workspace:^\",\n\t\t\"unist-util-visit\": \"^5.0.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/unist\": \"^3.0.3\",\n\t\t\"text-kit\": \"workspace:^\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/lezer/tests/compare-tree.js",
    "content": "import { Tree } from '@lezer/common'\n\n/**\n * @typedef {import('@lezer/common').Tree} Tree\n */\n\n/**\n * @param {Tree} a\n * @param {Tree} b\n */\nexport function compareTree(a, b) {\n\tconst curA = a.cursor(),\n\t\tcurB = b.cursor()\n\tfor (;;) {\n\t\tlet mismatch = null,\n\t\t\tnext = false\n\t\tif (curA.type !== curB.type)\n\t\t\tmismatch = `Node type mismatch (${curA.name} vs ${curB.name})`\n\t\telse if (curA.from !== curB.from)\n\t\t\tmismatch = `Start pos mismatch for ${curA.name}: ${curA.from} vs ${curB.from}`\n\t\telse if (curA.to !== curB.to)\n\t\t\tmismatch = `End pos mismatch for ${curA.name}: ${curA.to} vs ${curB.to}`\n\t\telse {\n\t\t\tnext = curA.next()\n\t\t\tif (next !== curB.next()) mismatch = `Tree size mismatch`\n\t\t}\n\t\tif (mismatch) {\n\t\t\tconst lines = [mismatch, 'a-:>', ...print(a), 'b-:>', ...print(b)]\n\t\t\tthrow new Error(lines.join('\\n'))\n\t\t}\n\n\t\tif (!next) break\n\t}\n}\n\n/**\n * @param {import('@lezer/common').TreeCursor | Tree} tree\n * @param {string} [prefix]\n */\nexport function print(tree, prefix = '') {\n\tconst cur = tree instanceof Tree ? tree.cursor() : tree\n\tconst lines = [`${prefix}${cur.name} (${cur.from}-${cur.to})`]\n\tif (cur.firstChild()) {\n\t\tdo {\n\t\t\tlines.push(...print(cur, `${' '.repeat(prefix.length)}└╴`))\n\t\t} while (cur.nextSibling())\n\t\tcur.parent()\n\t}\n\treturn lines\n}\n"
  },
  {
    "path": "packages/lezer/tests/incremental.test.js",
    "content": "/**\n * @typedef {{from: number, to?: number, insert?: string}[]} ChangeSpec\n */\n\nimport assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { Tree, TreeFragment } from '@lezer/common'\nimport { parser } from '../lib/index.js'\nimport { compareTree } from './compare-tree.js'\n\nconst doc = `* Header\nThis is a /paragraph/.\nStill the same =paragraph=.\n\n#+begin_src js\nconsole.log('hello')\n#+end_src\n\nhere is a link: [[https://example.com][link text]]\n`\nconst docLength = doc.length\n\nclass State {\n\tconstructor(doc, tree, fragments) {\n\t\tthis.doc = doc\n\t\tthis.tree = tree\n\t\tthis.fragments = fragments\n\t}\n\n\tstatic start(doc) {\n\t\tconst tree = parser.parse(doc)\n\t\treturn new State(doc, tree, TreeFragment.addTree(tree))\n\t}\n\n\t/**\n\t * @param {ChangeSpec[]} changes\n\t * @param {boolean} reparse\n\t */\n\tupdate(changes, reparse = true) {\n\t\tlet changed = [],\n\t\t\tdoc = this.doc,\n\t\t\toff = 0\n\t\tfor (const { from, to = from, insert = '' } of changes) {\n\t\t\tdoc = doc.slice(0, from) + insert + doc.slice(to)\n\t\t\tchanged.push({\n\t\t\t\tfromA: from - off,\n\t\t\t\ttoA: to - off,\n\t\t\t\tfromB: from,\n\t\t\t\ttoB: from + insert.length\n\t\t\t})\n\t\t\toff += insert.length - (to - from)\n\t\t}\n\t\tconst fragments = TreeFragment.applyChanges(this.fragments, changed, 2)\n\t\tif (!reparse) return new State(doc, Tree.empty, fragments)\n\t\t// return this\n\t\tconst tree = parser.parse(doc, fragments)\n\t\treturn new State(doc, tree, TreeFragment.addTree(tree, fragments))\n\t}\n}\n\n// const state1 = State.start(doc)\n\n/**\n * @param {ChangeSpec} change\n * @param {boolean} [verbose=false]\n * @param {number} reuse\n */\nfunction testChange(change, verbose = false, reuse = 10) {\n\tconst state1 = State.start(doc)\n\tconst state = state1.update(change)\n\tconst updatedDoc = state.doc\n\tverbose && console.log('updatedDoc', updatedDoc)\n\tcompareTree(state.tree, parser.parse(updatedDoc))\n\n\tif (reuse) {\n\t\tconst diff = overlap(state.tree, state1.tree)\n\t\tassert.ok(diff > reuse, `diff: ${diff}`)\n\t}\n}\n\n/**\n * @param {Tree} a\n * @param {Tree} b\n */\nfunction overlap(a, b) {\n\tlet inA = new Set(),\n\t\tshared = 0,\n\t\tsharingTo = 0\n\tfor (let cur = a.cursor(); cur.next(); ) if (cur.tree) inA.add(cur.tree)\n\tfor (let cur = b.cursor(); cur.next(); )\n\t\tif (\n\t\t\tcur.tree &&\n\t\t\tinA.has(cur.tree) &&\n\t\t\tcur.type.is('Block') &&\n\t\t\tcur.from >= sharingTo\n\t\t) {\n\t\t\tshared += cur.to - cur.from\n\t\t\tsharingTo = cur.to\n\t\t}\n\treturn Math.round((shared * 100) / b.length)\n}\n\ndescribe('incremential parsing', () => {\n\t// it.runOnly(true)\n\tit('can insert in the middle', () => {\n\t\ttestChange([{ from: 2, to: 2, insert: 'bears' }])\n\t})\n\tit('can insert at the begining', () => {\n\t\ttestChange([{ from: 0, to: 0, insert: 'bears' }])\n\t})\n\tit('can handle deletion', () => {\n\t\ttestChange([{ from: 0, to: 5 }])\n\t})\n\tit('can appending at the end', () => {\n\t\tconst size = doc.length\n\t\ttestChange([{ from: size, to: size, insert: '* another heading' }])\n\t})\n\tit('can replace content', () => {\n\t\ttestChange([{ from: 2, to: 8, insert: 'bears' }])\n\t})\n\tit('reuses nodes from the previous parse', () => {\n\t\tconst state1 = State.start(doc)\n\t\tconst state = state1.update([{ from: 2, to: 8, insert: 'bears' }])\n\t\tconst diff = overlap(state1.tree, state.tree)\n\t\tassert.ok(diff > 90, `diff: ${diff}`)\n\t\tconsole.log('hello test')\n\t})\n\tit('can handle deleting a star', () => testChange([{ from: 0, to: 1 }]))\n\t// it('can reuse content for a change in a block context', () => {})\n\t// it('can handle adding to a quoted block', () => {})\n\t// it('can handle a change in a post-linkref paragraph', () => {})\n\t// it('can handle a change in a paragraph-adjacent linkrefs', () => {})\n\n\tit('can handle insertion at the eof', () =>\n\t\ttestChange([{ from: docLength, to: docLength, insert: '* h' }]))\n})\n"
  },
  {
    "path": "packages/lezer/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/loader/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.4.4\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/orgx@2.6.1\n\n## 4.4.3\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/orgx@2.6.0\n\n## 4.4.2\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.2\n\n## 4.4.1\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.1\n\n## 4.4.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/orgx@2.5.0\n\n## 4.3.2\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n- Updated dependencies [e3ef3a5]\n  - @orgajs/orgx@2.4.1\n\n## 4.3.1\n\n### Patch Changes\n\n- Updated dependencies [351f690]\n  - @orgajs/orgx@2.4.0\n\n## 4.3.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/orgx@2.3.0\n\n## 4.2.2\n\n### Patch Changes\n\n- @orgajs/orgx@2.2.2\n\n## 4.2.1\n\n### Patch Changes\n\n- @orgajs/orgx@2.2.1\n\n## 4.2.0\n\n### Minor Changes\n\n- ac322714: implement editor\n\n### Patch Changes\n\n- Updated dependencies [ac322714]\n  - @orgajs/orgx@2.2.0\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/orgx@2.1.0\n\n## 4.0.1\n\n### Patch Changes\n\n- Updated dependencies [1dbf674d]\n  - @orgajs/orgx@2.0.1\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - @orgajs/orgx@2.0.0\n\n## 3.1.10\n\n### Patch Changes\n\n- Updated dependencies [eeccc870]\n  - @orgajs/orgx@1.0.8\n\n## 3.1.9\n\n### Patch Changes\n\n- Updated dependencies [6c1ddb9f]\n  - @orgajs/orgx@1.0.7\n\n## 3.1.8\n\n### Patch Changes\n\n- 4bde5155: tidy up dependencies\n- Updated dependencies [4bde5155]\n  - @orgajs/orgx@1.0.6\n\n## 3.1.7\n\n### Patch Changes\n\n- @orgajs/orgx@1.0.5\n\n## 3.1.6\n\n### Patch Changes\n\n- @orgajs/orgx@1.0.4\n\n## 3.1.5\n\n### Patch Changes\n\n- Updated dependencies [cd7cac3d]\n  - @orgajs/orgx@1.0.3\n\n## 3.1.4\n\n### Patch Changes\n\n- Updated dependencies [c8edd571]\n  - @orgajs/orgx@1.0.2\n\n## 3.1.3\n\n### Patch Changes\n\n- 594bf16b: ## @orgajs/orgx\n\n  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).\n\n  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:\n\n  - `@orgajs/loader`\n  - `@orgajs/next`\n  - `gatsby-plugin-orga`\n  - `gatsby-theme-orga-docs`\n  - `@orgajs/playground'`\n\n  `gatsby-transformer-orga` is still using the original compiler, since it has it's own ecosystem which requires some work to do a proper migration. That means the derivative packages around it are using the original compiler.\n\n  - `gatsby-theme-orga-posts`\n  - `gatsby-theme-orga-posts-core`\n\n  ## theme-ui support\n\n  `theme-ui` has `mdx` support builtin, and it's hard to do a clean extraction. So the package `@orgajs/theme-ui` is wrapping theme-ui, and provide orga specific tweaks. For gatsby, `gatsby-plugin-orga-theme-ui` is the equivalent of `gatsby-plugin-theme-ui`, but with orga support.\n\n- Updated dependencies [594bf16b]\n  - @orgajs/orgx@1.0.1\n\n## 3.1.2\n\n### Patch Changes\n\n- @orgajs/reorg@3.1.1\n\n## 3.1.1\n\n### Patch Changes\n\n- 8c6f440b: - better layout support\n  - rename MDXxxx to Orgaxxx\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - @orgajs/reorg@3.1.0\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - @orgajs/reorg@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - @orgajs/reorg@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/loader\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/loader\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/loader\n"
  },
  {
    "path": "packages/loader/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/loader/index.cjs",
    "content": "// stolen code from @mdx-js/loader\n\n/**\n * Webpack loader\n *\n * @todo once webpack supports ESM loaders, remove this wrapper.\n *\n * @this {LoaderContext}\n * @param {string} code\n */\nmodule.exports = function orgLoader(code) {\n\tconst callback = this.async()\n\t// Note that `import()` caches, so this should be fast enough.\n\timport('./lib/index.js').then((module) =>\n\t\tmodule.loader.call(this, code, callback)\n\t)\n}\n"
  },
  {
    "path": "packages/loader/index.d.ts",
    "content": "import type { ProcessorOptions } from '@orgajs/orgx'\nimport type { LoaderContext } from 'webpack'\n\n/**\n * A Webpack loader to compile MDX to JavaScript.\n *\n * [Reference for Loader API](https://webpack.js.org/api/loaders/)\n *\n * @this {LoaderContext<unknown>}\n * @param {string} value\n *   The original module source code.\n * @returns {void}\n */\ndeclare function orgLoader(this: LoaderContext<unknown>, value: string): void\n\nexport default orgLoader\n\nexport type Options = ProcessorOptions\n"
  },
  {
    "path": "packages/loader/lib/index.js",
    "content": "/**\n * @typedef {import('webpack').LoaderContext<unknown>} LoaderContext\n */\n\nimport path from 'node:path'\nimport { createProcessor } from '@orgajs/orgx'\n\n/**\n * @param {string} source\n * @param {LoaderContext['callback']} callback\n * @this {LoaderContext}\n */\nexport async function loader(source, callback) {\n\tconst processor = createProcessor({\n\t\tdevelopment: this.mode === 'development',\n\t\t...this.getOptions()\n\t})\n\n\ttry {\n\t\tconst file = await processor.process({\n\t\t\tvalue: source,\n\t\t\tpath: this.resourcePath\n\t\t})\n\t\tcallback(undefined, file.value, file.map)\n\t} catch (error) {\n\t\tconst fpath = path.relative(this.context, this.resourcePath)\n\t\terror.message = `${fpath}:${error.name}: ${error.message}`\n\t\tcallback(error)\n\t}\n}\n"
  },
  {
    "path": "packages/loader/package.json",
    "content": "{\n\t\"name\": \"@orgajs/loader\",\n\t\"version\": \"4.4.4\",\n\t\"description\": \"Load org-mode content through orga.\",\n\t\"type\": \"module\",\n\t\"main\": \"./index.cjs\",\n\t\"types\": \"index.d.ts\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.cjs\",\n\t\t\"index.d.ts\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/loader#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/loader\"\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"node --test tests/*.test.js\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"vfile-reporter\": \"^8.1.1\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@orgajs/react\": \"workspace:^\",\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"babel-loader\": \"^9.1.3\",\n\t\t\"html-loader\": \"^4.2.0\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"webpack\": \"^5.104.1\"\n\t}\n}\n"
  },
  {
    "path": "packages/loader/tests/compiler.js",
    "content": "import { promises as fs } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\nimport webpack from 'webpack'\n\nexport async function compile(fixture, options = {}) {\n\tconst base = new URL('.', import.meta.url)\n\n\tconst result = await promisify(webpack)({\n\t\t// @ts-expect-error TODO: webpack types miss support for `context`.\n\t\tcontext: fileURLToPath(base),\n\t\tentry: `./${fixture}`,\n\t\tmode: 'none',\n\t\toutput: {\n\t\t\tpath: fileURLToPath(base),\n\t\t\tfilename: 'bundle.js'\n\t\t},\n\t\tmodule: {\n\t\t\trules: [\n\t\t\t\t{\n\t\t\t\t\ttest: /\\.org$/,\n\t\t\t\t\tuse: [\n\t\t\t\t\t\t// {\n\t\t\t\t\t\t//   loader: 'babel-loader',\n\t\t\t\t\t\t//   options: {\n\t\t\t\t\t\t//     configFile: false,\n\t\t\t\t\t\t//     plugins: [\n\t\t\t\t\t\t//       '@babel/plugin-transform-runtime',\n\t\t\t\t\t\t//       '@babel/plugin-syntax-jsx',\n\t\t\t\t\t\t//       '@babel/plugin-transform-react-jsx',\n\t\t\t\t\t\t//     ],\n\t\t\t\t\t\t//   },\n\t\t\t\t\t\t// },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t// loader: path.resolve(__dirname, '../dist'),\n\t\t\t\t\t\t\tloader: fileURLToPath(new URL('../index.cjs', import.meta.url)),\n\t\t\t\t\t\t\toptions\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t})\n\n\t// cleanup\n\tawait fs.unlink(new URL('bundle.js', base))\n\treturn result\n}\n"
  },
  {
    "path": "packages/loader/tests/example.md",
    "content": "# hello world\n\nthis is some content.\n"
  },
  {
    "path": "packages/loader/tests/fixture.org",
    "content": "#+title: hello world\n* TODO headline one\n\n#+begin_export jsx\n<div style={{ color: 'red' }}>in a box</div>\n#+end_export\n"
  },
  {
    "path": "packages/loader/tests/loader.test.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { compile } from './compiler.js'\n\ntest('basic org-mode parsing', async () => {\n\tconst stats = await compile('fixture.org', {\n\t\tname: 'Alice'\n\t})\n\n\t// wait for 3 seconds\n\tawait new Promise((resolve) => setTimeout(resolve, 3000))\n\tconsole.log('after the wait')\n\n\tconst output = `${stats.toJson({ source: true }).modules[0].source}`\n\tassert.equal(\n\t\toutput.trim(),\n\t\t`\n/*@jsxRuntime automatic @jsxImportSource react*/\nimport {jsx as _jsx, jsxs as _jsxs} from \"react/jsx-runtime\";\nexport const title = 'hello world';\nfunction _createOrgContent(props) {\n  const _components = Object.assign({\n    div: \"div\",\n    h1: \"h1\"\n  }, props.components);\n  return _jsxs(_components.div, {\n    className: \"section\",\n    children: [_jsx(_components.h1, {\n      children: \"headline one\"\n    }), _jsx(_components.div, {\n      style: {\n        color: 'red'\n      },\n      children: \"in a box\"\n    })]\n  });\n}\nfunction OrgContent(props = {}) {\n  const {wrapper: OrgLayout} = props.components || ({});\n  return OrgLayout ? _jsx(OrgLayout, {\n    ...props,\n    children: _jsx(_createOrgContent, {\n      ...props\n    })\n  }) : _createOrgContent(props);\n}\nexport default OrgContent;\n  `.trim()\n\t)\n})\n"
  },
  {
    "path": "packages/metadata/CHANGELOG.md",
    "content": "# @orgajs/metadata\n\n## 2.4.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 2.4.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n## 2.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n## 2.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n## 2.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n## 2.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n## 1.0.2\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n\n## 1.0.1\n\n### Patch Changes\n\n- 594bf16b: ## @orgajs/orgx\n\n  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).\n\n  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:\n\n  - `@orgajs/loader`\n  - `@orgajs/next`\n  - `gatsby-plugin-orga`\n  - `gatsby-theme-orga-docs`\n  - `@orgajs/playground'`\n\n  `gatsby-transformer-orga` is still using the original compiler, since it has it's own ecosystem which requires some work to do a proper migration. That means the derivative packages around it are using the original compiler.\n\n  - `gatsby-theme-orga-posts`\n  - `gatsby-theme-orga-posts-core`\n\n  ## theme-ui support\n\n  `theme-ui` has `mdx` support builtin, and it's hard to do a clean extraction. So the package `@orgajs/theme-ui` is wrapping theme-ui, and provide orga specific tweaks. For gatsby, `gatsby-plugin-orga-theme-ui` is the equivalent of `gatsby-plugin-theme-ui`, but with orga support.\n"
  },
  {
    "path": "packages/metadata/README.org",
    "content": "#+title: @orgajs/metadata\n"
  },
  {
    "path": "packages/metadata/index.js",
    "content": "/**\n * @typedef {import('./lib/index.js').Metadata} Metadata\n */\n\nexport { parse } from './lib/index.js'\n"
  },
  {
    "path": "packages/metadata/lib/index.js",
    "content": "/**\n * TODO: more types?\n * @typedef {string} Value\n * @typedef {Record<string, Value | Value[]>} Metadata\n */\n\nconst TO_DISCARD = [\n\t'caption',\n\t'header',\n\t'name',\n\t'plot',\n\t'results',\n\t/^attr_\\w+/i, // Affiliated Keywords\n\t/^begin_\\w+/i,\n\t/^end_\\w+/i,\n\t'begin',\n\t'end', // blocks\n\t'call', // call\n\t'jsx' // orga's jsx support\n]\n\n/**\n * @param {string} key\n * @returns {boolean}\n */\nfunction shouldDiscard(key) {\n\treturn !!TO_DISCARD.find((test) => {\n\t\tif (typeof test === 'string') {\n\t\t\treturn test === key.toLowerCase()\n\t\t}\n\t\treturn test.test(key)\n\t})\n}\n\n/**\n * trim whitespaces and strip quotes if necessary\n * @param {string} text\n * @returns {Value}\n */\nfunction processValue(text) {\n\treturn text.trim().replace(/^[\"'](.+(?=[\"']$))[\"']$/, '$1')\n}\n\n/**\n * @param {Metadata} data\n */\nfunction pushTo(data) {\n\t/**\n\t * @param {string} _key\n\t * @param {string} _value\n\t * @returns {Metadata}\n\t */\n\treturn function (_key, _value) {\n\t\tconst key = _key.toLowerCase()\n\t\tconst value = processValue(_value)\n\n\t\tconst existing = data[key]\n\t\tif (existing) {\n\t\t\tif (Array.isArray(existing)) {\n\t\t\t\texisting.push(value)\n\t\t\t} else {\n\t\t\t\tdata[key] = [existing, value]\n\t\t\t}\n\t\t} else {\n\t\t\tdata[key] = value\n\t\t}\n\t\treturn data\n\t}\n}\n\n/**\n * @param {string} text\n * @returns {Metadata}\n */\nexport function parse(text) {\n\tconst matches = text.matchAll(/^\\s*#\\+(\\S+):(.*)$/gm)\n\treturn [...matches].reduce((data, [, key, value]) => {\n\t\tif (shouldDiscard(key)) return data\n\t\treturn pushTo(data)(key, value)\n\t}, {})\n}\n"
  },
  {
    "path": "packages/metadata/package.json",
    "content": "{\n\t\"name\": \"@orgajs/metadata\",\n\t\"version\": \"2.4.1\",\n\t\"description\": \"extract metadata info from org file\",\n\t\"type\": \"module\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/metadata#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/metadata\"\n\t},\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"scripts\": {\n\t\t\"test\": \"node --test --no-warnings tests/test.js\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"tsx\": \"^4.19.2\",\n\t\t\"typescript\": \"^5.9.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/metadata/tests/test.js",
    "content": "import * as assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { parse } from '../index.js'\n\ndescribe('metadata parser', () => {\n\tit('works', () => {\n\t\tassert.deepEqual(parse('#+title: hello world'), {\n\t\t\ttitle: 'hello world'\n\t\t})\n\t})\n\n\tit('can handle multiple entries', () => {\n\t\tassert.deepEqual(\n\t\t\tparse(`\n#+include: file1.org\n#+include: ../file2.org\n`),\n\t\t\t{\n\t\t\t\tinclude: ['file1.org', '../file2.org']\n\t\t\t}\n\t\t)\n\t})\n\n\tit('can handle spaces at the front', () => {\n\t\tassert.deepEqual(\n\t\t\tparse(`\n#+title: orga\n#+keywords: parser ast\n`),\n\t\t\t{\n\t\t\t\ttitle: 'orga',\n\t\t\t\tkeywords: 'parser ast'\n\t\t\t}\n\t\t)\n\t})\n\n\tit('transform keys to lowercase', () => {\n\t\tassert.deepEqual(\n\t\t\tparse(`\n#+TODO: TODO NEXT | DONE\n#+todo: DRAFT | PUBLISHED\n`),\n\t\t\t{\n\t\t\t\ttodo: ['TODO NEXT | DONE', 'DRAFT | PUBLISHED']\n\t\t\t}\n\t\t)\n\t})\n\n\tit('strips quotes if necessary', () => {\n\t\tassert.deepEqual(\n\t\t\tparse(`\n#+include: \"./file1.org\"\n#+include: './file2.org'\n#+desc: it's good\n`),\n\t\t\t{\n\t\t\t\tinclude: ['./file1.org', './file2.org'],\n\t\t\t\tdesc: \"it's good\"\n\t\t\t}\n\t\t)\n\t})\n})\n"
  },
  {
    "path": "packages/metadata/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/next/README.org",
    "content": "* @orgajs/next\n\nNext.js integration is now maintained in a standalone repository:\n\n- [[https://github.com/orgapp/orga-next][orgapp/orga-next]]\n\nPackage name remains =@orgajs/next=.\n\nFor usage and setup instructions, see:\n\n- [[https://github.com/orgapp/orga-next/blob/main/README.org][README.org]]\n- [[https://orga.js.org/guides/next][Next.js guide]]\n"
  },
  {
    "path": "packages/node-loader/CHANGELOG.md",
    "content": "# @orgajs/node-loader\n\n## 1.1.5\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/orgx@2.6.1\n\n## 1.1.4\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/orgx@2.6.0\n\n## 1.1.3\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.2\n\n## 1.1.2\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.1\n\n## 1.1.1\n\n### Patch Changes\n\n- b73e6b3: fix builder\n\n## 1.1.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/orgx@2.5.0\n\n## 1.0.1\n\n### Patch Changes\n\n- Updated dependencies [e3ef3a5]\n  - @orgajs/orgx@2.4.1\n\n## 1.0.0\n\n### Major Changes\n\n- 351f690: introduce @orgajs/node-loader, @orgajs/esbuild, @orgajs/build\n\n  - @orgajs/node-loader : the nodejs loader for org-mode files\n  - @orgajs/esbuild : esbuild plugin\n  - @orgajs/build : static site generator, a.k.a orga-build\n\n### Patch Changes\n\n- Updated dependencies [351f690]\n  - @orgajs/orgx@2.4.0\n"
  },
  {
    "path": "packages/node-loader/index.js",
    "content": "/**\n * @import {LoadFnOutput, LoadHook, LoadHookContext} from 'node:module'\n * @import {ProcessorOptions} from '@orgajs/orgx'\n */\n\n/**\n * @typedef {Parameters<LoadHook>[2]} NextLoad\n *   Next.\n *\n * @typedef {ProcessorOptions} Options\n *   Configuration.\n *\n */\n\nimport fs from 'node:fs/promises'\nimport { createProcessor } from '@orgajs/orgx'\nimport { SourceMapGenerator } from 'source-map'\nimport { VFile } from 'vfile'\nimport { reporter } from 'vfile-reporter'\n\n/**\n * Create Node.js hooks to handle org files.\n *\n * @param {Readonly<Options> | null | undefined} [loaderOptions]\n *   Configuration (optional).\n * @returns\n *   Node.js hooks.\n */\nexport function createLoader(loaderOptions) {\n\tlet settings = configure(loaderOptions || {})\n\n\treturn { initialize, load }\n\n\t/**\n\t * @param {Readonly<Options> | null | undefined} options\n\t */\n\tasync function initialize(options) {\n\t\tsettings = configure({ ...loaderOptions, ...options })\n\t}\n\n\t/**\n\t * Load `file:` URLs to MD(X) files.\n\t *\n\t * @param {string} href\n\t *   URL.\n\t * @param {LoadHookContext} context\n\t *   Context.\n\t * @param {NextLoad} nextLoad\n\t *   Next or default `load` function.\n\t * @returns {Promise<LoadFnOutput>}\n\t *   Result.\n\t * @satisfies {LoadHook}\n\t */\n\tasync function load(href, context, nextLoad) {\n\t\tconst url = new URL(href)\n\t\tconst { compile } = settings\n\n\t\tif (url.protocol === 'file:' && /.org$/.test(url.pathname)) {\n\t\t\tconst value = await fs.readFile(url)\n\t\t\tconst file = await compile(new VFile({ value, path: url }))\n\t\t\tif (file.messages.length > 0) {\n\t\t\t\tconsole.error(reporter(file))\n\t\t\t}\n\n\t\t\tlet source = String(file)\n\t\t\tsource +=\n\t\t\t\t'\\n//# sourceMappingURL=data:application/json;base64,' +\n\t\t\t\tBuffer.from(JSON.stringify(file.map)).toString('base64') +\n\t\t\t\t'\\n'\n\n\t\t\treturn {\n\t\t\t\tformat: 'module',\n\t\t\t\tshortCircuit: true,\n\t\t\t\tsource\n\t\t\t}\n\t\t}\n\n\t\treturn nextLoad(href, context)\n\t}\n}\n\n/**\n * @param {Options} options\n */\nfunction configure(options) {\n\tconst processor = createProcessor({\n\t\tdevelopment: true,\n\t\t...options,\n\t\tSourceMapGenerator\n\t})\n\n\t/**\n\t * @param {import('vfile').Compatible} file\n\t */\n\tfunction compile(file) {\n\t\treturn processor.process(file)\n\t}\n\n\treturn { compile }\n}\n\nconst defaultLoader = createLoader()\n\n/**\n * Pass options to the loader.\n */\nexport const initialize = defaultLoader.initialize\n\n/**\n * Load `file:` URLs to org files.\n */\nexport const load = defaultLoader.load\n"
  },
  {
    "path": "packages/node-loader/package.json",
    "content": "{\n\t\"name\": \"@orgajs/node-loader\",\n\t\"version\": \"1.1.5\",\n\t\"description\": \"\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"scripts\": {},\n\t\"keywords\": [],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/node-loader\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"source-map\": \"^0.7.4\",\n\t\t\"vfile\": \"^6.0.3\",\n\t\t\"vfile-reporter\": \"^8.1.1\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^25.3.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/oast-to-hast/.projectile",
    "content": ""
  },
  {
    "path": "packages/oast-to-hast/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.5.3\n\n### Patch Changes\n\n- 850bcf9: fix: use native anchor for external links to prevent wouter pushState SecurityError\n\n## 4.5.2\n\n### Patch Changes\n\n- be20652: expose rehypePlugins in orga-build\n\n## 4.5.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - orga@4.7.1\n\n## 4.5.0\n\n### Minor Changes\n\n- 761c484: Preserve inline markup in quote and center blocks.\n\n### Patch Changes\n\n- Updated dependencies [761c484]\n  - orga@4.7.0\n\n## 4.4.3\n\n### Patch Changes\n\n- 68430c7: fix newline in paragraph\n\n## 4.4.2\n\n### Patch Changes\n\n- d8da621: fix invalid html structure with image/video\n\n## 4.4.1\n\n### Patch Changes\n\n- 20f5a03: fix: render video links as `<video controls>` elements\n\n## 4.4.0\n\n### Minor Changes\n\n- da20dcc: bug fix: correct definition list HTML output\n\n## 4.3.3\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - orga@4.6.0\n\n## 4.3.2\n\n### Patch Changes\n\n- Updated dependencies [60ad38f]\n  - orga@4.5.1\n\n## 4.3.1\n\n### Patch Changes\n\n- 7c3c600: fix react resolve issue\n\n## 4.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - orga@4.5.0\n\n## 4.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - orga@4.4.0\n\n## 4.1.3\n\n### Patch Changes\n\n- ab38e4b0: add ability to customize <a>'s target attribute\n\n## 4.1.2\n\n### Patch Changes\n\n- Updated dependencies [7cfff79a]\n  - orga@4.3.0\n\n## 4.1.1\n\n### Patch Changes\n\n- Updated dependencies [ac322714]\n  - orga@4.2.0\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - orga@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - orga@4.0.0\n\n## 3.2.1\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n- Updated dependencies [eeccc870]\n  - orga@3.2.1\n\n## 3.2.0\n\n### Minor Changes\n\n- 6c1ddb9f: add latex support\n\n### Patch Changes\n\n- Updated dependencies [6c1ddb9f]\n  - orga@3.2.0\n\n## 3.1.6\n\n### Patch Changes\n\n- Updated dependencies [4bde5155]\n  - orga@3.1.5\n\n## 3.1.5\n\n### Patch Changes\n\n- ae83a3b0: - affiliated keyword support for list\n  - `HTML_CONTAINER_CLASS` support in properties drawer\n  - remove complex regex from inline parsing\n- Updated dependencies [ae83a3b0]\n  - orga@3.1.4\n\n## 3.1.4\n\n### Patch Changes\n\n- Updated dependencies [09a3b5c6]\n  - orga@3.1.3\n\n## 3.1.3\n\n### Patch Changes\n\n- Updated dependencies [594bf16b]\n  - orga@3.1.2\n\n## 3.1.2\n\n### Patch Changes\n\n- 19156b8a: inject props into layout\n- Updated dependencies [19156b8a]\n  - orga@3.1.1\n\n## 3.1.1\n\n### Patch Changes\n\n- 7f209ff5: oast-to-hast: add `all` function to context\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - orga@3.1.0\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - orga@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - orga@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n\n# [2.5.0](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n\n## [2.4.9](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package oast-to-hast\n\n## [2.4.8](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package oast-to-hast\n\n## [2.4.7](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package oast-to-hast\n"
  },
  {
    "path": "packages/oast-to-hast/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/oast-to-hast/index.js",
    "content": "/**\n * @typedef {import('./lib/index.js').Options} Options\n */\n\nexport { handlers as defaultHandlers } from './lib/handlers/index.js'\n\nexport { toHast, toHast as default } from './lib/index.js'\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/block.js",
    "content": "import { parseHtml } from './html.js'\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Block} node\n * @returns {import('hast').Element|undefined}\n */\nexport function block(state, node) {\n\tconst name = node.name.toLowerCase()\n\n\t/**\n\t * Preserve inline markup for block types whose content is parsed into\n\t * block children by orga. Fallback to the raw value for externally-provided\n\t * trees that omit `children`.\n\t */\n\tconst parsedChildren = state.all(node)\n\n\tif (name === 'src') {\n\t\tconst lang = node.params?.[0]\n\t\t\t? `language-${node.params[0]}`\n\t\t\t: 'language-undefined'\n\t\treturn state.patch(node, {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'pre',\n\t\t\tproperties: {},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'element',\n\t\t\t\t\ttagName: 'code',\n\t\t\t\t\tproperties: { className: [lang] },\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\tvalue: node.value\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t})\n\t}\n\n\tif (name === 'quote') {\n\t\treturn state.patch(node, {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'blockquote',\n\t\t\tproperties: {},\n\t\t\tchildren:\n\t\t\t\tparsedChildren.length > 0\n\t\t\t\t\t? parsedChildren\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\tvalue: node.value\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t})\n\t}\n\n\tif (name === 'center') {\n\t\treturn state.patch(node, {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'center',\n\t\t\tproperties: {},\n\t\t\tchildren:\n\t\t\t\tparsedChildren.length > 0\n\t\t\t\t\t? parsedChildren\n\t\t\t\t\t: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\t\t\tvalue: node.value\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t})\n\t}\n\n\tif (name === 'export') {\n\t\tif (node.params[0].toLowerCase() === 'html') {\n\t\t\treturn state.patch(node, parseHtml(node.value))\n\t\t}\n\n\t\treturn {\n\t\t\t// @ts-expect-error: this is a special passthrough\n\t\t\ttype: (node.params[0] || 'raw').toLowerCase(),\n\t\t\tvalue: node.value\n\t\t}\n\t}\n\n\tif (name === 'comment') {\n\t\treturn undefined\n\t}\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'pre',\n\t\tproperties: { className: [name] },\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: node.value\n\t\t\t}\n\t\t]\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/document.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Document} node\n * @returns {import('hast').Root}\n */\nexport function document(state, node) {\n\treturn {\n\t\ttype: 'root',\n\t\tdata: node.properties,\n\t\tchildren: state.all(node)\n\t}\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/footnote.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').FootnoteReference} node\n * @returns {import('hast').Element}\n */\nexport function footnoteRef(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'sup',\n\t\tproperties: { id: `fnref-${node.label}` },\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'a',\n\t\t\t\tproperties: { href: `#fn-${node.label}` },\n\t\t\t\tchildren: [{ type: 'text', value: node.label }]\n\t\t\t}\n\t\t]\n\t})\n}\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Footnote} node\n * @returns {import('hast').Element}\n */\nexport function footnote(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'div',\n\t\tproperties: {\n\t\t\tid: `fn-${node.label}`,\n\t\t\tclassName: ['footnote'],\n\t\t\tdataLabel: node.label\n\t\t},\n\t\tchildren: state.all(node)\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/headline.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Headline} node\n * @returns {import('hast').Element}\n */\nexport function headline(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: `h${node.level}`,\n\t\tproperties: {},\n\t\tchildren: state.all(node)\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/hr.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').HorizontalRule} node\n * @returns {import('hast').Element}\n */\nexport function hr(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'hr',\n\t\tproperties: {},\n\t\tchildren: []\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/html.js",
    "content": "import { fromHtml } from 'hast-util-from-html'\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').HTML} node\n * @returns {import('hast').Element}\n */\nexport function html(state, node) {\n\treturn state.patch(node, parseHtml(node.value))\n}\n\n/**\n * @param {string} html\n * @returns {import('hast').Element}\n */\nexport function parseHtml(html) {\n\tconst hast = fromHtml(html, { fragment: true })\n\n\t/** @type {import('hast').Element} */\n\tconst result = {\n\t\ttype: 'element',\n\t\ttagName: 'div',\n\t\tproperties: {},\n\t\tchildren: []\n\t}\n\n\thast.children.forEach((child) => {\n\t\tif (\n\t\t\tchild.type === 'element' ||\n\t\t\tchild.type === 'text' ||\n\t\t\tchild.type === 'comment'\n\t\t) {\n\t\t\tresult.children.push(child)\n\t\t}\n\t})\n\n\treturn result\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/index.js",
    "content": "import { block } from './block.js'\nimport { document } from './document.js'\nimport { footnote, footnoteRef } from './footnote.js'\nimport { headline } from './headline.js'\nimport { hr } from './hr.js'\nimport { html } from './html.js'\nimport { keyword } from './keyword.js'\nimport { latex } from './latex.js'\nimport { link } from './link.js'\nimport { checkbox, list, item as listItem } from './list.js'\nimport { newline } from './newline.js'\nimport { paragraph } from './paragraph.js'\nimport { section } from './section.js'\nimport {\n\ttable,\n\tcell as tableCell,\n\thr as tableHr,\n\trow as tableRow\n} from './table.js'\nimport { text } from './text.js'\n\n/**\n * Default handlers for nodes.\n *\n * @satisfies {import('../state.js').Handlers}\n */\nexport const handlers = {\n\tdocument,\n\tkeyword,\n\theadline,\n\tsection,\n\tparagraph,\n\ttext,\n\tblock,\n\tlatex,\n\tlink,\n\tlist,\n\t'list.item': listItem,\n\t'list.item.tag': ignore,\n\t'list.item.bullet': ignore,\n\t'list.item.checkbox': checkbox,\n\t'link.path': ignore,\n\ttable,\n\t'table.row': tableRow,\n\t'table.cell': tableCell,\n\t'table.hr': tableHr,\n\thtml,\n\tjsx: passThrough,\n\tdrawer: ignore,\n\tpriority: ignore,\n\tplanning: ignore,\n\tfootnote,\n\t'footnote.reference': footnoteRef,\n\thr,\n\tnewline\n}\n\n/** @type {import('../state.js').Handler} */\nfunction ignore() {\n\treturn undefined\n}\n\n/** @type {import('../state.js').Handler} */\nfunction passThrough(_, node) {\n\treturn node\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/keyword.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Keyword} node\n * @returns {import('hast').Element|undefined}\n */\nexport function keyword(state, node) {\n\tif (node.key.toLowerCase() === 'select_tags') {\n\t\tconst tags = node.value\n\t\t\t.split(',')\n\t\t\t.map((tag) => tag.trim())\n\t\t\t.filter(Boolean)\n\t\tstate.options.selectTags = tags\n\t}\n\n\treturn undefined\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/latex.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Latex} node\n * @returns {import('hast').Element}\n */\nexport function latex(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'div',\n\t\tproperties: { className: ['math-display'] },\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: node.value\n\t\t\t}\n\t\t]\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/link.js",
    "content": "/**\n * @import { Element } from 'hast'\n */\n\nimport mime from 'mime'\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Link} node\n * @returns {Element}\n */\nexport function link(state, node) {\n\tconst type = mime.getType(node.path.value)\n\n\tif (type?.startsWith('image')) {\n\t\t/** @type {Element} */\n\t\tconst image = {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'img',\n\t\t\tproperties: {\n\t\t\t\tsrc: node.path.value,\n\t\t\t\ttarget: state.options.linkTarget\n\t\t\t},\n\t\t\tchildren: []\n\t\t}\n\t\t/** @type {Element|null} */\n\t\tlet cap = null\n\t\tconst c = node.attributes.caption\n\t\tif (c) {\n\t\t\tcap = {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figcaption',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tvalue: `${c}`\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t} else if (node.children.length > 0) {\n\t\t\tcap = {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figcaption',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: state.all(node)\n\t\t\t}\n\t\t}\n\t\tif (cap) {\n\t\t\treturn state.patch(node, {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figure',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: [image, cap]\n\t\t\t})\n\t\t}\n\n\t\treturn state.patch(node, image)\n\t}\n\n\tif (type?.startsWith('video')) {\n\t\t/** @type {Element} */\n\t\tconst video = {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'video',\n\t\t\tproperties: {\n\t\t\t\tsrc: node.path.value,\n\t\t\t\tcontrols: true\n\t\t\t},\n\t\t\tchildren: []\n\t\t}\n\t\t/** @type {Element|null} */\n\t\tlet cap = null\n\t\tconst c = node.attributes.caption\n\t\tif (c) {\n\t\t\tcap = {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figcaption',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tvalue: `${c}`\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t} else if (node.children.length > 0) {\n\t\t\tcap = {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figcaption',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: state.all(node)\n\t\t\t}\n\t\t}\n\t\tif (cap) {\n\t\t\treturn state.patch(node, {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'figure',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: [video, cap]\n\t\t\t})\n\t\t}\n\n\t\treturn state.patch(node, video)\n\t}\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'a',\n\t\tproperties: {\n\t\t\thref: state.options.linkHref(node),\n\t\t\ttarget: state.options.linkTarget\n\t\t},\n\t\tchildren: state.all(node)\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/list.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').List} node\n * @returns {import('hast').Element}\n */\nexport function list(state, node) {\n\tlet tagName = node.ordered ? 'ol' : 'ul'\n\tif (node.children.every((i) => i.type !== 'list.item' || i.tag)) {\n\t\ttagName = 'dl'\n\t}\n\n\tconst properties = state.getAttrHtml(node)\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: tagName,\n\t\tproperties: properties ?? {},\n\t\tchildren: state.all(node)\n\t})\n}\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').ListItem} node\n * @param {import('orga').Parent | undefined} parent\n * @returns {import('hast').ElementContent | import('hast').ElementContent[]}\n */\nexport function item(state, node, parent) {\n\tif (node.tag) {\n\t\t/** @type {import('hast').Element[]} */\n\t\tconst dtdd = [\n\t\t\t{\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'dt',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: [{ type: 'text', value: node.tag }]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: 'dd',\n\t\t\t\tproperties: {},\n\t\t\t\tchildren: state.all(node)\n\t\t\t}\n\t\t]\n\n\t\tconst allTagged = parent?.children?.every(\n\t\t\t(i) => i.type !== 'list.item' || i.tag\n\t\t)\n\n\t\tif (allTagged) {\n\t\t\t// Pure definition list: return [<dt>, <dd>] to be flattened into <dl>\n\t\t\treturn dtdd\n\t\t}\n\n\t\t// Definition item inside a mixed list: wrap in <li><dl>…</dl></li>\n\t\treturn state.patch(node, {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'li',\n\t\t\tproperties: {},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'element',\n\t\t\t\t\ttagName: 'dl',\n\t\t\t\t\tproperties: {},\n\t\t\t\t\tchildren: dtdd\n\t\t\t\t}\n\t\t\t]\n\t\t})\n\t}\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'li',\n\t\tproperties: {},\n\t\tchildren: state.all(node)\n\t})\n}\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').ListItemCheckbox} node\n * @returns {import('hast').Element}\n */\nexport function checkbox(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'input',\n\t\tproperties: {\n\t\t\ttype: 'checkbox',\n\t\t\tchecked: node.checked,\n\t\t\tdisabled: true\n\t\t},\n\t\tchildren: []\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/newline.js",
    "content": "/**\n * @param {import('../state.js').State} _state\n * @param {import('orga').Newline} _node\n * @param {import('orga').Parent | undefined} parent\n * @returns {import('hast').Text | undefined}\n */\nexport function newline(_state, _node, parent) {\n\t// In Org paragraphs, a single source newline is a soft break. For HTML\n\t// output, normalize it to a space so text remains readable.\n\tif (parent?.type === 'paragraph') {\n\t\treturn { type: 'text', value: ' ' }\n\t}\n\n\treturn undefined\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/paragraph.js",
    "content": "/**\n * Block-level HTML elements that are not allowed as descendants of <p>.\n * When a paragraph contains any of these, we must avoid wrapping in <p>.\n *\n * @see https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element\n */\nconst BLOCK_TAGS = new Set([\n\t'address',\n\t'article',\n\t'aside',\n\t'blockquote',\n\t'details',\n\t'dialog',\n\t'dd',\n\t'div',\n\t'dl',\n\t'dt',\n\t'fieldset',\n\t'figcaption',\n\t'figure',\n\t'footer',\n\t'form',\n\t'h1',\n\t'h2',\n\t'h3',\n\t'h4',\n\t'h5',\n\t'h6',\n\t'header',\n\t'hgroup',\n\t'hr',\n\t'li',\n\t'main',\n\t'nav',\n\t'ol',\n\t'p',\n\t'pre',\n\t'section',\n\t'summary',\n\t'table',\n\t'ul'\n])\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Paragraph} node\n * @returns {import('hast').Element}\n */\nexport function paragraph(state, node) {\n\tconst properties = state.getAttrHtml(node)\n\tconst children = state.all(node)\n\n\t// If any child is a block-level element (e.g. a <figure> from a media link\n\t// with caption), wrapping in <p> produces invalid HTML and causes hydration\n\t// errors in React. Unwrap single block children; use <div> for mixed content.\n\tconst hasBlock = children.some(\n\t\t(child) =>\n\t\t\tchild.type === 'element' &&\n\t\t\tBLOCK_TAGS.has(/** @type {import('hast').Element} */ (child).tagName)\n\t)\n\n\tif (hasBlock) {\n\t\tif (children.length === 1) {\n\t\t\treturn /** @type {import('hast').Element} */ (children[0])\n\t\t}\n\t\treturn state.patch(node, {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'div',\n\t\t\tproperties: properties ?? {},\n\t\t\tchildren\n\t\t})\n\t}\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'p',\n\t\tproperties: properties ?? {},\n\t\tchildren\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/section.js",
    "content": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Section} node\n * @returns {import('hast').Element|undefined}\n */\nexport function section(state, node) {\n\tconst headline = node.children.find((n) => n.type === 'headline')\n\n\tif (headline) {\n\t\tif (shouldSkip(state.options, headline.tags || [])) {\n\t\t\treturn undefined\n\t\t}\n\t}\n\n\tlet className = 'section'\n\tconst drawer = node.children.find((n) => n.type === 'drawer')\n\tif (drawer && drawer.name === 'PROPERTIES') {\n\t\tconst lines = drawer.value.split('\\n')\n\t\tlines.forEach((line) => {\n\t\t\tconst m = line.match(/:(\\w+):(.*)$/)\n\t\t\tif (m && m[1].toUpperCase() === 'HTML_CONTAINER_CLASS') {\n\t\t\t\tclassName = `${className} ${m[2].trim()}`\n\t\t\t}\n\t\t})\n\t}\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'div',\n\t\tproperties: { className: className.split(/\\s+/).filter(Boolean) },\n\t\tchildren: state.all(node)\n\t})\n}\n\n/**\n * @param {import('../state.js').Config} config\n * @param {string[]} tags\n * @returns {boolean}\n */\nfunction shouldSkip({ selectTags = [], excludeTags = [] }, tags) {\n\tif (selectTags.length > 0) {\n\t\treturn !tags.some((tag) => selectTags.includes(tag))\n\t}\n\n\tif (excludeTags.length > 0) {\n\t\treturn tags.some((tag) => excludeTags.includes(tag))\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/table.js",
    "content": "/**\n * @import {Element,ElementContent} from 'hast'\n * @import {Table,TableCell,TableRow} from 'orga'\n * @import {State} from '../state.js'\n */\n\n/**\n * @param {State} state\n * @param {Table} node\n * @returns {Element}\n */\nexport function table(state, node) {\n\tconst rows = state.all(node)\n\tconst hrIndex = rows.findIndex(\n\t\t(row) => row.type === 'element' && row.tagName === 'hr'\n\t)\n\n\t/** @type {ElementContent[]} */\n\tconst headRows = []\n\t/** @type {ElementContent[]} */\n\tconst bodyRows = []\n\trows.forEach((row, i) => {\n\t\tif (i < hrIndex) {\n\t\t\theadRows.push(row)\n\t\t} else if (i > hrIndex) {\n\t\t\tbodyRows.push(row)\n\t\t}\n\t})\n\n\t/** @type {ElementContent[]} */\n\tconst tableContent = []\n\n\tif (headRows.length > 0) {\n\t\ttableContent.push({\n\t\t\ttype: 'element',\n\t\t\ttagName: 'thead',\n\t\t\tproperties: {},\n\t\t\tchildren: headRows\n\t\t})\n\t}\n\n\tif (bodyRows.length > 0) {\n\t\ttableContent.push({\n\t\t\ttype: 'element',\n\t\t\ttagName: 'tbody',\n\t\t\tproperties: {},\n\t\t\tchildren: bodyRows\n\t\t})\n\t}\n\n\tconst caption = node.attributes.caption\n\tif (caption) {\n\t\ttableContent.push({\n\t\t\ttype: 'element',\n\t\t\ttagName: 'caption',\n\t\t\tproperties: {},\n\t\t\tchildren: [{ type: 'text', value: `${caption}` }]\n\t\t})\n\t}\n\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'table',\n\t\tproperties: {},\n\t\tchildren: tableContent\n\t})\n}\n\n/**\n * @param {State} state\n * @param {TableRow} node\n * @returns {Element}\n */\nexport function row(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'tr',\n\t\tproperties: {},\n\t\tchildren: state.all(node)\n\t})\n}\n\n/**\n * @param {State} state\n * @param {TableCell} node\n * @returns {Element}\n */\nexport function cell(state, node) {\n\treturn state.patch(node, {\n\t\ttype: 'element',\n\t\ttagName: 'td',\n\t\tproperties: {},\n\t\tchildren: state.all(node)\n\t})\n}\n\n/**\n * @returns {Element}\n */\nexport function hr() {\n\treturn {\n\t\ttype: 'element',\n\t\ttagName: 'hr',\n\t\tproperties: {},\n\t\tchildren: []\n\t}\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/text.js",
    "content": "/**\n * @import {Element,Text} from 'hast'\n *\n */\n\nconst wrapper = {\n\tbold: 'strong',\n\titalic: 'i',\n\tcode: 'code',\n\tverbatim: 'code',\n\tunderline: 'u',\n\tstrikeThrough: 'del',\n\tmath: 'span'\n}\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Text} node\n * @returns {Element|Text}\n */\nexport function text(state, node) {\n\t/** @type {Element|Text} */\n\tlet e = {\n\t\ttype: 'text',\n\t\tvalue: node.value\n\t}\n\tif (node.style) {\n\t\te = {\n\t\t\ttype: 'element',\n\t\t\ttagName: wrapper[node.style],\n\t\t\tproperties: {},\n\t\t\tchildren: [e]\n\t\t}\n\t\tif (node.style === 'math') {\n\t\t\te.properties.className = ['math-inline']\n\t\t}\n\t}\n\treturn state.patch(node, e)\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/index.js",
    "content": "/**\n * @typedef {import('hast').Nodes} HastNodes\n * @typedef {import('orga').Nodes} OastNodes\n * @typedef {Partial<import('./state.js').Config> | null | undefined} Options\n */\n\nimport { createState } from './state.js'\n\n/**\n * @param {OastNodes} tree\n *   oast tree.\n * @param {Options} [options]\n *   Configuration (optional).\n * @returns {HastNodes}\n *   hast tree.\n */\nexport function toHast(tree, options = {}) {\n\tconst state = createState(tree, options)\n\n\tconst node = state.one(tree)\n\tif (Array.isArray(node)) {\n\t\treturn { type: 'root', children: node }\n\t}\n\t// if (tree.type === 'document') {\n\t// \treturn {\n\t// \t\ttype: 'root',\n\t// \t\tdata: tree.properties,\n\t// \t\tchildren: node ? [node] : [],\n\t// \t}\n\t// }\n\treturn node || { type: 'root', children: [] }\n}\n"
  },
  {
    "path": "packages/oast-to-hast/lib/state.js",
    "content": "/**\n * @typedef {import('hast').Nodes} HastNodes\n\t @import {ElementContent as HastElementContent,Root as HastRoot} from 'hast'\n * @typedef {import('orga').Parent} OastParent\n * @typedef {import('orga').Nodes} OastNodes\n */\n\n/**\n * @typedef {Object} Config\n * @property {Handlers} handlers\n * @property {string} linkTarget\n * @property {(link: import('orga').Link) => string} linkHref\n * @property {string[]} selectTags=[]\n * @property {string[]} excludeTags=['noexport']\n */\n\n/**\n * @typedef {ReturnType<typeof createState>} State\n *\n * @callback Handler\n * @param {State} state\n * @param {any} node\n * @param {OastParent | undefined} parent\n * @returns {Array<HastElementContent> | HastElementContent | HastRoot | undefined}\n *   hast node.\n *\n * @typedef {Partial<Record<OastNodes['type'], Handler>>} Handlers\n *   Handle nodes.\n */\n\nimport { position } from 'unist-util-position'\nimport { handlers as defaultHandlers } from './handlers/index.js'\n\n/**\n * @param {OastNodes} _tree\n * @param {Partial<Config> | null | undefined} [options = {}]\n */\nexport function createState(_tree, options = {}) {\n\t/** @type {Handlers} */\n\tlet handlers = { ...defaultHandlers }\n\tif (options?.handlers) {\n\t\thandlers = { ...handlers, ...options.handlers }\n\t}\n\n\tconst state = {\n\t\tone,\n\t\tall,\n\t\thandlers,\n\t\tgetAttrHtml,\n\t\tpatch,\n\t\t/** @type {Config} */\n\t\toptions: {\n\t\t\thandlers,\n\t\t\tlinkTarget: '_self',\n\t\t\tselectTags: [],\n\t\t\texcludeTags: ['noexport'],\n\t\t\tlinkHref: defaultLinkHref,\n\t\t\t...options\n\t\t}\n\t}\n\n\treturn state\n\n\t/**\n\t * @param {OastNodes} parent\n\t * @returns {Array<HastElementContent>}\n\t */\n\tfunction all(parent) {\n\t\t/** @type {Array<HastElementContent>} */\n\t\tconst values = []\n\t\tif ('children' in parent) {\n\t\t\tparent.children.forEach((node) => {\n\t\t\t\tconst result = one(node, parent)\n\t\t\t\tif (!result) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tif (Array.isArray(result)) {\n\t\t\t\t\tvalues.push(...result)\n\t\t\t\t} else {\n\t\t\t\t\t// @ts-expect-error: can never be Root here\n\t\t\t\t\tvalues.push(result)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\treturn values\n\t}\n\n\t/**\n\t * @param {OastNodes} node\n\t * @param {OastParent | undefined} parent\n\t */\n\tfunction one(node, parent = undefined) {\n\t\tconst handle = handlers[node.type] || unkownHandler\n\t\treturn handle(state, node, parent)\n\t}\n\n\t/**\n\t * @param {OastNodes} node\n\t * @returns {Record<string, string> | undefined}\n\t */\n\tfunction getAttrHtml(node) {\n\t\tif ('properties' in node && 'attr_html' in node.properties) {\n\t\t\tconst a = node.properties.attr_html\n\t\t\tif (typeof a === 'string') return\n\t\t\tif (Array.isArray(a)) return\n\t\t\treturn a\n\t\t}\n\t}\n\n\t/**\n\t * @template {HastNodes} T\n\t * @param {OastNodes} from\n\t * @param {T} to\n\t * @returns {T}\n\t */\n\tfunction patch(from, to) {\n\t\tif (from.position) {\n\t\t\tto.position = position(from)\n\t\t}\n\t\treturn to\n\t}\n}\n\n/**\n * @param {import('orga').Link} link\n * @returns {string}\n */\nfunction defaultLinkHref(link) {\n\tconst protocol = link.path.protocol\n\tif (!protocol || protocol === 'internal' || protocol === 'file') {\n\t\treturn link.path.value\n\t}\n\tif (protocol === 'http' || protocol === 'https') {\n\t\treturn link.path.value\n\t}\n\treturn `${protocol}:${link.path.value}`\n}\n\n/** @type {Handler} */\nfunction unkownHandler(state, node) {\n\tif (node?.children) {\n\t\treturn {\n\t\t\ttype: 'element',\n\t\t\ttagName: 'div',\n\t\t\tproperties: {},\n\t\t\tchildren: state.all(node)\n\t\t}\n\t} else if ('value' in node) {\n\t\treturn { type: 'text', value: `${node.value}` }\n\t}\n\treturn undefined\n}\n"
  },
  {
    "path": "packages/oast-to-hast/package.json",
    "content": "{\n\t\"name\": \"oast-to-hast\",\n\t\"version\": \"4.5.3\",\n\t\"description\": \"Transform OAST to HAST\",\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"type\": \"module\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": \"https://github.com/orgapp/orgajs/tree/main/packages/oast-to-hast\",\n\t\"dependencies\": {\n\t\t\"hast-util-from-html\": \"^2.0.3\",\n\t\t\"mime\": \"^3.0.0\",\n\t\t\"orga\": \"workspace:^\",\n\t\t\"parse5\": \"^7.1.2\",\n\t\t\"unist-util-position\": \"^5.0.0\"\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"node --test tests/*.js\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/hast\": \"^3.0.4\",\n\t\t\"@types/mime\": \"^3.0.1\",\n\t\t\"@types/unist\": \"^3.0.3\",\n\t\t\"hastscript\": \"^9.0.0\"\n\t}\n}\n"
  },
  {
    "path": "packages/oast-to-hast/tests/block.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { parse } from 'orga'\nimport { toHast } from '../index.js'\n\ntest('quote block preserves inline markup', () => {\n\tconst oast = parse(`#+BEGIN_QUOTE\nBe *bold*, and if you must, be /italic/.\n#+END_QUOTE\n`)\n\n\tconst hast = removePosition(toHast(oast))\n\n\tassert.deepEqual(hast, {\n\t\ttype: 'root',\n\t\tdata: {},\n\t\tchildren: [\n\t\t\th('blockquote', [\n\t\t\t\t'Be ',\n\t\t\t\th('strong', 'bold'),\n\t\t\t\t', and if you must, be ',\n\t\t\t\th('i', 'italic'),\n\t\t\t\t'.'\n\t\t\t])\n\t\t]\n\t})\n})\n\nfunction removePosition(node) {\n\tif (!node || typeof node !== 'object') return node\n\tif (Array.isArray(node)) return node.map(removePosition)\n\tconst result = {}\n\tfor (const [key, value] of Object.entries(node)) {\n\t\tif (key === 'position') continue\n\t\tresult[key] = removePosition(value)\n\t}\n\treturn result\n}\n"
  },
  {
    "path": "packages/oast-to-hast/tests/classname.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { parse } from 'orga'\nimport { toHast } from '../index.js'\n\ntest('src blocks emit code.className as token array', () => {\n\tconst oast = parse(`#+begin_src javascript\nconsole.log('ok')\n#+end_src`)\n\tconst hast = toHast(oast)\n\tconst code = hast.children[0]?.children?.[0]\n\n\tassert.deepEqual(code?.tagName, 'code')\n\tassert.deepEqual(code?.properties?.className, ['language-javascript'])\n})\n\ntest('sections emit div.className as token array', () => {\n\tconst oast = parse(`* Heading\n:PROPERTIES:\n:HTML_CONTAINER_CLASS: foo bar\n:END:\nBody`)\n\tconst hast = toHast(oast)\n\tconst section = hast.children[0]\n\n\tassert.deepEqual(section?.tagName, 'div')\n\tassert.deepEqual(section?.properties?.className, ['section', 'foo', 'bar'])\n})\n"
  },
  {
    "path": "packages/oast-to-hast/tests/heading.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from '../index.js'\n\ntest('heading', async () => {\n\tconst hast = toHast({\n\t\ttype: 'headline',\n\t\tlevel: 3,\n\t\tchildren: [{ type: 'text', value: 'Hello' }]\n\t})\n\n\tassert.deepEqual(hast, h('h3', 'Hello'))\n})\n"
  },
  {
    "path": "packages/oast-to-hast/tests/list.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from '../index.js'\n\ntest('regular unordered list', () => {\n\tconst hast = toHast({\n\t\ttype: 'list',\n\t\tordered: false,\n\t\tindent: 0,\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\tchildren: [{ type: 'text', value: 'item one' }]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\tchildren: [{ type: 'text', value: 'item two' }]\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(hast, h('ul', [h('li', 'item one'), h('li', 'item two')]))\n})\n\ntest('pure definition list produces <dl> with flat <dt>/<dd> pairs (no <div> wrapper)', () => {\n\tconst hast = toHast({\n\t\ttype: 'list',\n\t\tordered: false,\n\t\tindent: 0,\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\ttag: 'word',\n\t\t\t\tchildren: [{ type: 'text', value: 'description.' }]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\ttag: 'another',\n\t\t\t\tchildren: [{ type: 'text', value: 'definition.' }]\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('dl', [\n\t\t\th('dt', 'word'),\n\t\t\th('dd', 'description.'),\n\t\t\th('dt', 'another'),\n\t\t\th('dd', 'definition.')\n\t\t])\n\t)\n})\n\ntest('pure definition list followed by a paragraph still produces <dl>', () => {\n\t// The parser appends a trailing newline node as a child of the list when\n\t// followed by a blank line + paragraph. It must not be mistaken for a\n\t// non-tagged item.\n\tconst hast = toHast({\n\t\ttype: 'list',\n\t\tordered: false,\n\t\tindent: 0,\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\ttag: 'hello',\n\t\t\t\tchildren: [{ type: 'text', value: 'this is greeting.' }]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\ttag: 'world',\n\t\t\t\tchildren: [{ type: 'text', value: 'this is the world.' }]\n\t\t\t},\n\t\t\t{ type: 'newline' }\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('dl', [\n\t\t\th('dt', 'hello'),\n\t\t\th('dd', 'this is greeting.'),\n\t\t\th('dt', 'world'),\n\t\t\th('dd', 'this is the world.')\n\t\t])\n\t)\n})\n\ntest('mixed list wraps definition items as <li><dl><dt>/<dd></dl></li>', () => {\n\tconst hast = toHast({\n\t\ttype: 'list',\n\t\tordered: false,\n\t\tindent: 0,\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\tchildren: [{ type: 'text', value: 'item one' }]\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'list.item',\n\t\t\t\tindent: 0,\n\t\t\t\ttag: 'word',\n\t\t\t\tchildren: [{ type: 'text', value: 'definition goes here.' }]\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('ul', [\n\t\t\th('li', 'item one'),\n\t\t\th('li', [h('dl', [h('dt', 'word'), h('dd', 'definition goes here.')])])\n\t\t])\n\t)\n})\n"
  },
  {
    "path": "packages/oast-to-hast/tests/paragraph.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from '../index.js'\n\ntest('paragraph with text', async () => {\n\tconst hast = toHast({\n\t\ttype: 'paragraph',\n\t\tchildren: [{ type: 'text', value: 'Hello' }]\n\t})\n\n\tassert.deepEqual(hast, h('p', 'Hello'))\n})\n\ntest('paragraph newline is rendered as a space', async () => {\n\tconst hast = toHast({\n\t\ttype: 'paragraph',\n\t\tchildren: [\n\t\t\t{ type: 'text', value: 'foo' },\n\t\t\t{ type: 'newline' },\n\t\t\t{ type: 'text', value: 'bar' }\n\t\t]\n\t})\n\n\tassert.deepEqual(hast, h('p', ['foo', ' ', 'bar']))\n})\n\ntest('paragraph mailto link keeps protocol in href', async () => {\n\tconst hast = toHast({\n\t\ttype: 'paragraph',\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'link',\n\t\t\t\tpath: { protocol: 'mailto', value: 'hi@unclex.net' },\n\t\t\t\tattributes: {},\n\t\t\t\tchildren: [{ type: 'text', value: 'send me an email' }]\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('p', [\n\t\t\th('a', { href: 'mailto:hi@unclex.net', target: '_self' }, [\n\t\t\t\t'send me an email'\n\t\t\t])\n\t\t])\n\t)\n})\n\ntest('paragraph with single media figure unwraps to figure', async () => {\n\t// A video link with a caption produces a <figure> from the link handler.\n\t// The paragraph handler must not wrap it in <p> (invalid HTML).\n\tconst hast = toHast({\n\t\ttype: 'paragraph',\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'link',\n\t\t\t\tpath: { value: 'demo.mp4' },\n\t\t\t\tattributes: { caption: 'A demo video' },\n\t\t\t\tchildren: []\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('figure', [\n\t\t\th('video', { src: 'demo.mp4', controls: true }),\n\t\t\th('figcaption', 'A demo video')\n\t\t])\n\t)\n})\n\ntest('paragraph with text and media figure wraps in div', async () => {\n\t// Mixed content: text + block-level element → use <div> instead of <p>.\n\tconst hast = toHast({\n\t\ttype: 'paragraph',\n\t\tchildren: [\n\t\t\t{ type: 'text', value: 'Caption: ' },\n\t\t\t{\n\t\t\t\ttype: 'link',\n\t\t\t\tpath: { value: 'demo.mp4' },\n\t\t\t\tattributes: { caption: 'A demo video' },\n\t\t\t\tchildren: []\n\t\t\t}\n\t\t]\n\t})\n\n\tassert.deepEqual(\n\t\thast,\n\t\th('div', [\n\t\t\t{ type: 'text', value: 'Caption: ' },\n\t\t\th('figure', [\n\t\t\t\th('video', { src: 'demo.mp4', controls: true }),\n\t\t\t\th('figcaption', 'A demo video')\n\t\t\t])\n\t\t])\n\t)\n})\n"
  },
  {
    "path": "packages/oast-to-hast/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/oast-to-prose/CHANGELOG.md",
    "content": "# oast-to-prose\n\n## 1.3.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 1.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n## 1.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n"
  },
  {
    "path": "packages/oast-to-prose/index.js",
    "content": "/**\n * @typedef {import('./lib/index.js').Options} Options\n */\n\nexport { schema, toProse } from './lib/index.js'\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/block.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Block} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function block(state, node) {\n\t// TODO: handle more block types\n\tstate.ignore('block.begin', 'block.end')\n\tconst n = state.schema.node('code', null, state.all(node))\n\tstate.unignore('block.begin', 'block.end')\n\treturn n\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/headline.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Headline} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function headline(state, node) {\n\tstate.ignore('newline')\n\tconst n = state.schema.node(\n\t\t'headline',\n\t\t{ level: node.level },\n\t\tstate.all(node)\n\t)\n\tstate.unignore('newline')\n\treturn n\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/index.js",
    "content": "import { block } from './block.js'\nimport { headline } from './headline.js'\nimport { link } from './link.js'\nimport { newline } from './newline.js'\nimport { paragraph } from './paragraph.js'\nimport { section } from './section.js'\nimport { stars } from './stars.js'\nimport { tags } from './tags.js'\nimport { text } from './text.js'\nimport { todo } from './todo.js'\n\n/* @type {import('../index.js').Handlers} */\nexport const handlers = {\n\tsection,\n\ttext,\n\tparagraph,\n\theadline,\n\tlink,\n\tblock,\n\tnewline,\n\ttodo,\n\tstars,\n\ttags\n}\n\nexport const ignore = ['link.path', 'emptyLine']\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/link.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Link} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function link(state, node) {\n\tstate.ignore('opening', 'closing')\n\tconst n = state.schema.node(\n\t\t'link',\n\t\t{\n\t\t\thref: node.path.value\n\t\t},\n\t\tstate.all(node)\n\t)\n\tstate.unignore('opening', 'closing')\n\treturn n\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/newline.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function newline(state) {\n\treturn state.schema.node('newline')\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/paragraph.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Paragraph} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function paragraph(state, node) {\n\tstate.inParagraph = true\n\tconst n = state.schema.node('paragraph', null, state.all(node))\n\tstate.inParagraph = false\n\treturn n\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/section.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Section} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function section(state, node) {\n\tconst n = state.schema.node('section', null, state.all(node))\n\treturn n\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/stars.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Stars} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function stars(state, node) {\n\treturn state.schema.node('stars', {\n\t\tlevel: node.level\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/tags.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Tags} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function tags(state, node) {\n\treturn node.tags.map((tag) =>\n\t\tstate.schema.node('tag', { tag }, state.schema.text(tag))\n\t)\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/text.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Text} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function text(state, node) {\n\treturn state.schema.text(node.value)\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/todo.js",
    "content": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Todo} node\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n */\nexport function todo(state, node) {\n\treturn state.schema.node('todo', {\n\t\tkeyword: node.keyword,\n\t\tactionable: node.actionable\n\t})\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/index.js",
    "content": "/**\n * @typedef {import('orga').Document} OastRoot\n * @typedef {import('orga').Content} OastContent\n * @typedef {import('orga').Parent} OastParent\n * @typedef {import('prosemirror-model').Node} ProseNode\n * @typedef {OastRoot | OastContent} OastNodes\n *\n * @callback Handler\n *   Handle a node.\n * @param {import('./state.js').State} state\n *   Info passed around.\n * @param {any} node\n *   oast node to handle.\n * @param {OastParent | null | undefined} parent\n *   Parent of `node`.\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n *   prose node.\n *\n * @typedef {Record<string, Handler>} Handlers\n *   Handle nodes.\n *\n * @typedef Options\n * @property {import('prosemirror-model').Schema} schema\n */\n\nimport { defaultSchema } from './schema.js'\nimport { createParseState } from './state.js'\n\nexport const schema = defaultSchema\n\n/**\n * @param {OastRoot} tree\n * @param {import('vfile').VFile} file\n * @param {Options | undefined | null} [options]\n * @returns {ProseNode}\n */\nexport function toProse(tree, file, options) {\n\tconst schema = options?.schema || defaultSchema\n\tconst state = createParseState(file, { schema })\n\tconst node = state.one(tree, null)\n\treturn schema.node('doc', null, node || undefined)\n}\n"
  },
  {
    "path": "packages/oast-to-prose/lib/schema.js",
    "content": "import { Schema } from 'prosemirror-model'\n\nexport const defaultSchema = new Schema({\n\tnodes: {\n\t\tdoc: {\n\t\t\tcontent: 'block+'\n\t\t},\n\t\tsection: {\n\t\t\tcontent: 'headline block*',\n\t\t\tgroup: 'block',\n\t\t\ttoDOM() {\n\t\t\t\treturn ['section', 0]\n\t\t\t}\n\t\t},\n\t\theadline: {\n\t\t\tattrs: { level: { default: 1 } },\n\t\t\tcontent: 'inline*',\n\t\t\tdefining: true,\n\t\t\tgroup: 'block',\n\t\t\t// atom: true,\n\t\t\tparseDOM: [\n\t\t\t\t{ tag: 'h1', attrs: { level: 1 } },\n\t\t\t\t{ tag: 'h2', attrs: { level: 2 } },\n\t\t\t\t{ tag: 'h3', attrs: { level: 3 } },\n\t\t\t\t{ tag: 'h4', attrs: { level: 4 } },\n\t\t\t\t{ tag: 'h5', attrs: { level: 5 } },\n\t\t\t\t{ tag: 'h6', attrs: { level: 6 } }\n\t\t\t],\n\t\t\ttoDOM(node) {\n\t\t\t\treturn [`h${node.attrs.level}`, 0]\n\t\t\t}\n\t\t},\n\t\ttodo: {\n\t\t\tgroup: 'inline',\n\t\t\tinline: true,\n\t\t\tattrs: {\n\t\t\t\tkeyword: {},\n\t\t\t\tactionable: {}\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\treturn [\n\t\t\t\t\t'span',\n\t\t\t\t\t{ class: 'org-todo', 'data-actionable': node.attrs.actionable },\n\t\t\t\t\tnode.attrs.keyword\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\tstars: {\n\t\t\tgroup: 'inline',\n\t\t\tinline: true,\n\t\t\tattrs: {\n\t\t\t\tlevel: {}\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\treturn [\n\t\t\t\t\t'span',\n\t\t\t\t\t{ class: 'org-stars', 'data-level': node.attrs.level },\n\t\t\t\t\t'*'.repeat(node.attrs.level)\n\t\t\t\t]\n\t\t\t}\n\t\t},\n\t\ttag: {\n\t\t\tcontent: 'text*',\n\t\t\tgroup: 'inline',\n\t\t\tinline: true,\n\t\t\ttoDOM() {\n\t\t\t\treturn ['span', { class: 'org-tag' }, 0]\n\t\t\t}\n\t\t},\n\t\tparagraph: {\n\t\t\tcontent: 'inline*',\n\t\t\tgroup: 'block',\n\t\t\tparseDOM: [{ tag: 'p' }],\n\t\t\ttoDOM() {\n\t\t\t\treturn ['p', 0]\n\t\t\t}\n\t\t},\n\t\ttext: {\n\t\t\tgroup: 'inline'\n\t\t},\n\t\tlink: {\n\t\t\tcontent: 'text*',\n\t\t\tgroup: 'inline',\n\t\t\tinline: true,\n\t\t\tattrs: {\n\t\t\t\thref: {},\n\t\t\t\ttitle: { default: null }\n\t\t\t},\n\t\t\tinclusive: false,\n\t\t\tparseDOM: [\n\t\t\t\t{\n\t\t\t\t\ttag: 'a[href]',\n\t\t\t\t\tgetAttrs(dom) {\n\t\t\t\t\t\tif (typeof dom === 'string') return {}\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\thref: dom.getAttribute('href'),\n\t\t\t\t\t\t\ttitle: dom.getAttribute('title')\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\ttoDOM(node) {\n\t\t\t\treturn ['a', node.attrs, 0]\n\t\t\t}\n\t\t},\n\t\tcode: {\n\t\t\tcontent: 'inline*',\n\t\t\tgroup: 'block',\n\t\t\tattrs: { params: {} },\n\t\t\ttoDOM() {\n\t\t\t\treturn ['pre', ['code', 0]]\n\t\t\t}\n\t\t},\n\t\tnewline: {\n\t\t\tinline: true,\n\t\t\tgroup: 'inline',\n\t\t\tselectable: false,\n\t\t\ttoDOM() {\n\t\t\t\treturn ['br']\n\t\t\t}\n\t\t}\n\t},\n\tmarks: {\n\t\traw: {\n\t\t\tattrs: {\n\t\t\t\ttype: {}\n\t\t\t},\n\t\t\ttoDOM(node) {\n\t\t\t\treturn [\n\t\t\t\t\t'code',\n\t\t\t\t\t{\n\t\t\t\t\t\tstyle: `border:1px solid red;before:${node.attrs.type}`,\n\t\t\t\t\t\t'data-node-type': node.attrs.type\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t}\n\t}\n})\n"
  },
  {
    "path": "packages/oast-to-prose/lib/state.js",
    "content": "/**\n * @typedef {import('orga').Document} OastRoot\n * @typedef {import('orga').Content} OastContent\n * @typedef {import('orga').Parent} OastParent\n * @typedef {import('prosemirror-model').Node} ProseNode\n * @typedef {OastRoot | OastContent} OastNodes\n *\n * @typedef HFields\n * @property {import('prosemirror-model').Schema} schema\n *   Schema to use.\n * @property {boolean} inParagraph\n *   Whether the current node is in a paragraph.\n * @property {(node: OastNodes, parent: OastParent | null | undefined) => ProseNode | Array<ProseNode> | null | undefined} one\n *   Transform an oast node to prose node.\n * @property {(node: OastNodes) => Array<ProseNode>} all\n *   Transform the children of an mdast parent to hast.\n * @property {import('./index.js').Handlers} handlers\n *   Applied handlers.\n * @property {(...types: string[]) => void} ignore\n * @property {(...types: string[]) => void} unignore\n * @property {string[]} ignored\n *\n * @typedef {HFields} State\n *\n * @typedef Options\n * @property {import('prosemirror-model').Schema} schema\n */\n\nimport { handlers, ignore } from './handlers/index.js'\n\n/**\n * @param {import('vfile').VFile} file\n * @param {Options} options\n * @returns {State}\n */\nexport function createParseState(file, options) {\n\t/** @type {State} */\n\tconst state = {\n\t\thandlers: { ...handlers },\n\t\tignored: [...ignore],\n\t\tschema: options.schema,\n\t\tinParagraph: false,\n\t\tignore(...types) {\n\t\t\tthis.ignored.push(...types)\n\t\t},\n\t\tunignore(...types) {\n\t\t\tthis.ignored = this.ignored.filter((type) => !types.includes(type))\n\t\t},\n\t\tone(node, parent) {\n\t\t\tif (this.ignored.includes(node.type)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst handler = this.handlers[node.type]\n\t\t\tif (handler) {\n\t\t\t\treturn handler(this, node, parent)\n\t\t\t}\n\t\t\treturn defaultUnknownHandler(this, node, file)\n\t\t},\n\t\tall(parent) {\n\t\t\t/** @type {Array<ProseNode>} */\n\t\t\tconst values = []\n\n\t\t\tif ('children' in parent) {\n\t\t\t\tconst nodes = parent.children\n\t\t\t\tlet index = -1\n\t\t\t\twhile (++index < nodes.length) {\n\t\t\t\t\tconst node = this.one(nodes[index], parent)\n\t\t\t\t\tif (node) {\n\t\t\t\t\t\tif (Array.isArray(node)) {\n\t\t\t\t\t\t\tvalues.push(...node)\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tvalues.push(node)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn values\n\t\t}\n\t}\n\n\treturn state\n}\n\n/**\n * Transform an unknown node.\n *\n * @param {State} state\n *   Info passed around.\n * @param {OastNodes} node\n *   Unknown aast node.\n * @param {import('vfile').VFile} file\n * @returns {ProseNode | Array<ProseNode> | null | undefined}\n *   Resulting pose node.\n */\nfunction defaultUnknownHandler(state, node, file) {\n\tconsole.log('unknown node', node)\n\tif ('value' in node) {\n\t\tconst raw = state.schema.text(\n\t\t\tgetRawContent(node, file) || 'cannot find raw',\n\t\t\t[state.schema.mark('raw', { type: node.type })]\n\t\t)\n\t\tif (!state.inParagraph) {\n\t\t\treturn state.schema.node('paragraph', null, [raw])\n\t\t}\n\t\treturn raw\n\t}\n\tif ('children' in node) {\n\t\treturn state.all(node)\n\t}\n\n\t// return state.schema.node('error', null, [\n\t//   state.schema.text(`unknown node: ${node.type}`),\n\t// ])\n}\n\n/**\n * @param {OastNodes} node\n *   Unknown aast node.\n * @param {import('vfile').VFile} file\n * @returns {string | null}\n */\nfunction getRawContent(node, file) {\n\tif (node.position) {\n\t\tconst content = file.value.slice(\n\t\t\tnode.position.start.offset,\n\t\t\tnode.position.end.offset\n\t\t)\n\t\tif (typeof content !== 'string') {\n\t\t\tthrow new Error('content is not a string')\n\t\t}\n\t\treturn content\n\t}\n\treturn null\n}\n"
  },
  {
    "path": "packages/oast-to-prose/package.json",
    "content": "{\n\t\"name\": \"oast-to-prose\",\n\t\"version\": \"1.3.1\",\n\t\"description\": \"Transform OAST to ProseMirror Document\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/oast-to-prose#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/oast-to-prose\"\n\t},\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"scripts\": {},\n\t\"keywords\": [],\n\t\"devDependencies\": {\n\t\t\"orga\": \"workspace:^\",\n\t\t\"vfile\": \"^6.0.3\"\n\t},\n\t\"dependencies\": {\n\t\t\"prosemirror-model\": \"^1.19.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/oast-to-prose/tests/text.js",
    "content": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { toProse } from '../lib/index.js'\n\ntest('test', () => {\n\tconst oast = {\n\t\ttype: 'document',\n\t\tchildren: [\n\t\t\t{\n\t\t\t\ttype: 'emptyLine'\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'section',\n\t\t\t\tchildren: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'paragraph',\n\t\t\t\t\t\tchildren: [\n\t\t\t\t\t\t\t{ type: 'text', value: 'hello world' },\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'newline'\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'emptyLine'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t}\n\tconst prose = toProse(oast)\n\tconsole.log({ prose })\n\tassert.strictEqual(1, 1)\n})\n"
  },
  {
    "path": "packages/oast-to-prose/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/orga/.projectile",
    "content": ""
  },
  {
    "path": "packages/orga/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.7.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - text-kit@4.5.1\n\n## 4.7.0\n\n### Minor Changes\n\n- 761c484: Preserve inline markup in quote and center blocks.\n\n## 4.6.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - text-kit@4.5.0\n\n## 4.5.1\n\n### Patch Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n\n## 4.5.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - text-kit@4.4.0\n\n## 4.4.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - text-kit@4.3.0\n\n## 4.3.0\n\n### Minor Changes\n\n- 7cfff79a: headline elements (stars, todo keywords and priority) end after the whitespaces\n\n## 4.2.0\n\n### Minor Changes\n\n- ac322714: implement editor\n\n### Patch Changes\n\n- Updated dependencies [ac322714]\n  - text-kit@4.2.0\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - text-kit@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - text-kit@4.0.0\n\n## 3.2.1\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n- Updated dependencies [eeccc870]\n  - text-kit@3.0.2\n\n## 3.2.0\n\n### Minor Changes\n\n- 6c1ddb9f: add latex support\n\n## 3.1.5\n\n### Patch Changes\n\n- 4bde5155: tidy up dependencies\n\n## 3.1.4\n\n### Patch Changes\n\n- ae83a3b0: - affiliated keyword support for list\n  - `HTML_CONTAINER_CLASS` support in properties drawer\n  - remove complex regex from inline parsing\n\n## 3.1.3\n\n### Patch Changes\n\n- 09a3b5c6: fix planning position issue\n\n## 3.1.2\n\n### Patch Changes\n\n- 594bf16b: ## @orgajs/orgx\n\n  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).\n\n  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:\n\n  - `@orgajs/loader`\n  - `@orgajs/next`\n  - `gatsby-plugin-orga`\n  - `gatsby-theme-orga-docs`\n  - `@orgajs/playground'`\n\n  `gatsby-transformer-orga` is still using the original compiler, since it has it's own ecosystem which requires some work to do a proper migration. That means the derivative packages around it are using the original compiler.\n\n  - `gatsby-theme-orga-posts`\n  - `gatsby-theme-orga-posts-core`\n\n  ## theme-ui support\n\n  `theme-ui` has `mdx` support builtin, and it's hard to do a clean extraction. So the package `@orgajs/theme-ui` is wrapping theme-ui, and provide orga specific tweaks. For gatsby, `gatsby-plugin-orga-theme-ui` is the equivalent of `gatsby-plugin-theme-ui`, but with orga support.\n\n## 3.1.1\n\n### Patch Changes\n\n- 19156b8a: inject props into layout\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - text-kit@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - text-kit@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))\n- fix headline tags parsing issue [#126](https://github.com/orgapp/orgajs/issues/126) ([71d7f82](https://github.com/orgapp/orgajs/commit/71d7f8277708fc72d3b5be01ed0f72233bf7057b))\n- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))\n- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))\n- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))\n- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))\n\n### Features\n\n- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))\n- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package orga\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package orga\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package orga\n"
  },
  {
    "path": "packages/orga/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/orga/README.org",
    "content": "* orga\n\nTurns org-mode content into AST.\n\n** Install\n\n#+BEGIN_SRC sh\n  npm install --save orga\n#+END_SRC\n\n** Usage\n\n#+BEGIN_SRC javascript\n  const { parse } = require('orga')\n  const ast = parse(`* TODO remember the milk    :shopping:`)\n#+END_SRC\n\n~ast~ is an object looks like this:\n\n#+BEGIN_SRC javascript\n{\n  type: 'document',\n  properties: {},\n  children: [\n    {\n      type: 'section',\n      level: 1,\n      properties: {},\n      children: [\n        {\n          type: 'headline',\n          actionable: true,\n          content: 'remember the milk',\n          children: [\n            {\n              type: 'stars',\n              level: 1,\n              position: {\n                start: { line: 1, column: 1 },\n                end: { line: 1, column: 2 }\n              },\n              parent: [Circular *1]\n            },\n            {\n              type: 'todo',\n              keyword: 'TODO',\n              actionable: true,\n              position: {\n                start: { line: 1, column: 3 },\n                end: { line: 1, column: 7 }\n              },\n              parent: [Circular *1]\n            },\n            {\n              type: 'text.plain',\n              value: 'remember the milk',\n              position: {\n                start: { line: 1, column: 8 },\n                end: { line: 1, column: 25 }\n              },\n              parent: [Circular *1]\n            },\n            {\n              type: 'tags',\n              tags: [ 'shopping' ],\n              position: {\n                start: { line: 1, column: 29 },\n                end: { line: 1, column: 39 }\n              },\n              parent: [Circular *1]\n            }\n          ],\n          level: 1,\n          position: {\n            start: { line: 1, column: 1 },\n            end: { line: 1, column: 39 }\n          },\n          keyword: 'TODO',\n          tags: [ 'shopping' ],\n          parent: [Circular *2]\n        }\n      ],\n      position: { start: { line: 1, column: 1 }, end: { line: 1, column: 39 } },\n      parent: [Circular *3]\n    }\n  ],\n  position: { start: { line: 1, column: 1 }, end: { line: 1, column: 39 } }\n}\n\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/package.json",
    "content": "{\n\t\"name\": \"orga\",\n\t\"version\": \"4.7.1\",\n\t\"description\": \"org-mode parser\",\n\t\"files\": [\n\t\t\"dist\"\n\t],\n\t\"main\": \"dist/index.js\",\n\t\"type\": \"module\",\n\t\"exports\": {\n\t\t\".\": \"./dist/index.js\",\n\t\t\"./todo\": \"./dist/todo.js\"\n\t},\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com:orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/orga\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"tsc --build --clean\",\n\t\t\"build\": \"tsc --build\",\n\t\t\"test\": \"node --test --no-warnings --import tsx \\\"src/**/*.test.ts\\\"\"\n\t},\n\t\"dependencies\": {\n\t\t\"date-fns\": \"^2.30.0\",\n\t\t\"date-fns-tz\": \"^2.0.0\",\n\t\t\"text-kit\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"@types/unist\": \"^3.0.3\",\n\t\t\"tsx\": \"^4.19.2\",\n\t\t\"typescript\": \"^5.9.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/affiliated keyword.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"nop\": \"code_block\"\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n      \"key\": \"NAME\",\n      \"value\": \"code_block\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 19,\n          \"offset\": 18\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"block\",\n      \"name\": \"SRC\",\n      \"params\": [\n        \"javascript\"\n      ],\n      \"value\": \"console.log('named code block')\",\n      \"attributes\": {\n        \"name\": \"code_block\"\n      },\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('named code block')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 42\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 32,\n              \"offset\": 73\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 19\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 10,\n          \"offset\": 83\n        }\n      },\n      \"data\": {\n        \"hash\": 3\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 84\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 84\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"keyword\",\n      \"key\": \"NAME\",\n      \"value\": \"code_block\",\n      \"position\": {\n        \"start\": {\n          \"line\": 6,\n          \"column\": 1,\n          \"offset\": 85\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 19,\n          \"offset\": 103\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 7,\n          \"column\": 1,\n          \"offset\": 104\n        },\n        \"end\": {\n          \"line\": 7,\n          \"column\": 1,\n          \"offset\": 104\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"block\",\n      \"name\": \"SRC\",\n      \"params\": [\n        \"javascript\"\n      ],\n      \"value\": \"console.log('no name')\",\n      \"attributes\": {},\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('no name')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 9,\n              \"column\": 1,\n              \"offset\": 128\n            },\n            \"end\": {\n              \"line\": 9,\n              \"column\": 23,\n              \"offset\": 150\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 8,\n          \"column\": 1,\n          \"offset\": 105\n        },\n        \"end\": {\n          \"line\": 10,\n          \"column\": 10,\n          \"offset\": 160\n        }\n      },\n      \"data\": {\n        \"hash\": 3\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 11,\n          \"column\": 1,\n          \"offset\": 161\n        },\n        \"end\": {\n          \"line\": 11,\n          \"column\": 1,\n          \"offset\": 161\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"keyword\",\n      \"key\": \"NOP\",\n      \"value\": \"code_block\",\n      \"position\": {\n        \"start\": {\n          \"line\": 12,\n          \"column\": 1,\n          \"offset\": 162\n        },\n        \"end\": {\n          \"line\": 12,\n          \"column\": 18,\n          \"offset\": 179\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"block\",\n      \"name\": \"SRC\",\n      \"params\": [\n        \"javascript\"\n      ],\n      \"value\": \"console.log('no name')\",\n      \"attributes\": {},\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('no name')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 14,\n              \"column\": 1,\n              \"offset\": 203\n            },\n            \"end\": {\n              \"line\": 14,\n              \"column\": 23,\n              \"offset\": 225\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 13,\n          \"column\": 1,\n          \"offset\": 180\n        },\n        \"end\": {\n          \"line\": 15,\n          \"column\": 11,\n          \"offset\": 236\n        }\n      },\n      \"data\": {\n        \"hash\": 3\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 15,\n      \"column\": 11,\n      \"offset\": 236\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/block/affiliated keyword.org",
    "content": "#+NAME: code_block\n#+BEGIN_SRC javascript\nconsole.log('named code block')\n#+END_SRC\n\n#+NAME: code_block\n\n#+BEGIN_SRC javascript\nconsole.log('no name')\n#+END_SRC\n\n#+NOP: code_block\n#+BEGIN_SRC javascript\nconsole.log('no name')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/export.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"html\",\n      \"value\": \"<h1>Hello</h1>\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 23,\n          \"offset\": 22\n        }\n      },\n      \"data\": {\n        \"hash\": 14\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 23\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 23\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"block\",\n      \"name\": \"EXPORT\",\n      \"params\": [\n        \"html\"\n      ],\n      \"value\": \"<p>world!</p>\",\n      \"attributes\": {},\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"<p>world!</p>\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 44\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 14,\n              \"offset\": 57\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 24\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 13,\n          \"offset\": 70\n        }\n      },\n      \"data\": {\n        \"hash\": 3\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 6,\n          \"column\": 1,\n          \"offset\": 71\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 2,\n          \"offset\": 72\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 6,\n      \"column\": 2,\n      \"offset\": 72\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/block/export.org",
    "content": "#+HTML: <h1>Hello</h1>\n\n#+BEGIN_EXPORT html\n<p>world!</p>\n#+END_EXPORT\n\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/missing begin.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('hello')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 21,\n              \"offset\": 20\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 21,\n              \"offset\": 20\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 21\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('world')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 21\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 21,\n              \"offset\": 41\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 21,\n              \"offset\": 41\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 42\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 42\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 11,\n      \"offset\": 52\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/block/missing begin.org",
    "content": "console.log('hello')\nconsole.log('world')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/missing end.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"#+BEGIN_SRC javascript\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 23,\n              \"offset\": 22\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 23,\n              \"offset\": 22\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 23\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('hello')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 23\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 21,\n              \"offset\": 43\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 21,\n              \"offset\": 43\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 44\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('world')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 44\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 21,\n              \"offset\": 64\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 21,\n              \"offset\": 64\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 22,\n              \"offset\": 65\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 22,\n          \"offset\": 65\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 22,\n      \"offset\": 65\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/block/missing end.org",
    "content": "#+BEGIN_SRC javascript\nconsole.log('hello')\nconsole.log('world')\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/standard.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"block\",\n      \"name\": \"SRC\",\n      \"params\": [\n        \"javascript\"\n      ],\n      \"value\": \"console.log('hello')\\nconsole.log('world')\",\n      \"attributes\": {},\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('hello')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 23\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 21,\n              \"offset\": 43\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"console.log('world')\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 44\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 21,\n              \"offset\": 64\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 11,\n          \"offset\": 75\n        }\n      },\n      \"data\": {\n        \"hash\": 3\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 4,\n      \"column\": 11,\n      \"offset\": 75\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/block/standard.org",
    "content": "#+BEGIN_SRC javascript\nconsole.log('hello')\nconsole.log('world')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/multiline.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"reference footnote \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 20,\n                  \"offset\": 19\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 26,\n                  \"offset\": 25\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            }\n          },\n          \"label\": \"1\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"emptyLine\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 18\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    },\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 7,\n              \"offset\": 33\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 34\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 59\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"And here is \",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 59\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 71\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"style\": \"bold\",\n              \"value\": \"another\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 71\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 22,\n                  \"offset\": 80\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \" line.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 22,\n                  \"offset\": 80\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 28,\n                  \"offset\": 86\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 28,\n                  \"offset\": 86\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 29,\n                  \"offset\": 87\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 8,\n              \"offset\": 34\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 29,\n              \"offset\": 87\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 27\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 29,\n          \"offset\": 87\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 4,\n      \"column\": 29,\n      \"offset\": 87\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/multiline.org",
    "content": "reference footnote [fn:1]\n\n[fn:1] Content of the footnote.\nAnd here is *another* line.\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/standard.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"reference footnote \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 20,\n                  \"offset\": 19\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 26,\n                  \"offset\": 25\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            }\n          },\n          \"label\": \"1\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"emptyLine\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 18\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    },\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 7,\n              \"offset\": 33\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 34\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 33,\n                  \"offset\": 59\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 8,\n              \"offset\": 34\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 33,\n              \"offset\": 59\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 27\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 33,\n          \"offset\": 59\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 33,\n      \"offset\": 59\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/standard.org",
    "content": "reference footnote [fn:1]\n\n[fn:1] Content of the footnote.\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by empty lines.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 7,\n              \"offset\": 6\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"And here is another line.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"emptyLine\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 18\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 8,\n              \"offset\": 7\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 58\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"still belongs to fn:1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 59\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 22,\n                  \"offset\": 80\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 22,\n                  \"offset\": 80\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 81\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"emptyLine\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 81\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 81\n                }\n              },\n              \"data\": {\n                \"hash\": 18\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 59\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 81\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 1,\n          \"offset\": 82\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 6,\n          \"column\": 1,\n          \"offset\": 82\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 1,\n          \"offset\": 82\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"This is not.\",\n          \"position\": {\n            \"start\": {\n              \"line\": 7,\n              \"column\": 1,\n              \"offset\": 83\n            },\n            \"end\": {\n              \"line\": 7,\n              \"column\": 13,\n              \"offset\": 95\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 7,\n              \"column\": 13,\n              \"offset\": 95\n            },\n            \"end\": {\n              \"line\": 7,\n              \"column\": 14,\n              \"offset\": 96\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 7,\n          \"column\": 1,\n          \"offset\": 83\n        },\n        \"end\": {\n          \"line\": 7,\n          \"column\": 14,\n          \"offset\": 96\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 7,\n      \"column\": 14,\n      \"offset\": 96\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by empty lines.org",
    "content": "[fn:1] Content of the footnote.\nAnd here is another line.\n\nstill belongs to fn:1\n\n\nThis is not.\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by footnote.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 7,\n              \"offset\": 6\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"And here is another line.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 8,\n              \"offset\": 7\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 58\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 58\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    },\n    {\n      \"type\": \"footnote\",\n      \"label\": \"2\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"2\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 58\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 7,\n              \"offset\": 64\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"another footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 65\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 25,\n                  \"offset\": 82\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 25,\n                  \"offset\": 82\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 26,\n                  \"offset\": 83\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 8,\n              \"offset\": 65\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 26,\n              \"offset\": 83\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 58\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 26,\n          \"offset\": 83\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 26,\n      \"offset\": 83\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by footnote.org",
    "content": "[fn:1] Content of the footnote.\nAnd here is another line.\n[fn:2] another footnote.\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by headline.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 7,\n              \"offset\": 6\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"And here is another line.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 32\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 26,\n                  \"offset\": 57\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 8,\n              \"offset\": 7\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 58\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 58\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 59\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"A Headline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 60\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 13,\n                  \"offset\": 70\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 58\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 14,\n              \"offset\": 71\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 58\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 14,\n          \"offset\": 71\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 14,\n      \"offset\": 71\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by headline.org",
    "content": "[fn:1] Content of the footnote.\nAnd here is another line.\n* A Headline\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/with block.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"reference footnote \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 20,\n                  \"offset\": 19\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 24,\n                  \"offset\": 23\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 25,\n                  \"offset\": 24\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 26,\n                  \"offset\": 25\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            }\n          },\n          \"label\": \"1\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"emptyLine\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 18\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    },\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"children\": [\n        {\n          \"type\": \"footnote.label\",\n          \"label\": \"1\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 7,\n              \"offset\": 33\n            }\n          },\n          \"data\": {\n            \"hash\": 37\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Content of the footnote.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 34\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 32,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 59\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 8,\n              \"offset\": 34\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 59\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        },\n        {\n          \"type\": \"block\",\n          \"name\": \"SRC\",\n          \"params\": [\n            \"javascript\"\n          ],\n          \"value\": \"console.log('footnote with code block')\",\n          \"attributes\": {},\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"console.log('footnote with code block')\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 82\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 40,\n                  \"offset\": 121\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 59\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 11,\n              \"offset\": 132\n            }\n          },\n          \"data\": {\n            \"hash\": 3\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 27\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 11,\n          \"offset\": 132\n        }\n      },\n      \"data\": {\n        \"hash\": 2\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 6,\n      \"column\": 11,\n      \"offset\": 132\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/with block.org",
    "content": "reference footnote [fn:1]\n\n[fn:1] Content of the footnote.\n#+BEGIN_SRC javascript\nconsole.log('footnote with code block')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/broken drawer.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 11,\n                  \"offset\": 10\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 11\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \":PROPERTIES:\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 11\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 13,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 13,\n                  \"offset\": 23\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 24\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"key1: value1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 24\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 13,\n                  \"offset\": 36\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 13,\n                  \"offset\": 36\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 37\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"key2: value2\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 37\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 49\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 49\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 50\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"emptyLine\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 50\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 50\n                }\n              },\n              \"data\": {\n                \"hash\": 18\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 11\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 50\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Paragraph\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 1,\n                  \"offset\": 51\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 10,\n                  \"offset\": 60\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 10,\n                  \"offset\": 60\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 11,\n                  \"offset\": 61\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 51\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 11,\n              \"offset\": 61\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 11,\n          \"offset\": 61\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 6,\n      \"column\": 11,\n      \"offset\": 61\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/broken drawer.org",
    "content": "* headline\n:PROPERTIES:\nkey1: value1\nkey2: value2\n\nParagraph\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/drawers.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {\n        \"category\": \"test\",\n        \"effort\": \"5\"\n      },\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline with properties\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 27,\n                  \"offset\": 26\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 27\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"drawer\",\n          \"name\": \"PROPERTIES\",\n          \"value\": \"\\n:CATEGORY: test\\n:Effort:   5\\n\",\n          \"children\": [\n            {\n              \"type\": \"drawer.begin\",\n              \"name\": \"PROPERTIES\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 27\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 13,\n                  \"offset\": 39\n                }\n              },\n              \"data\": {\n                \"hash\": 31\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 13,\n                  \"offset\": 39\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 40\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \":CATEGORY: test\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 40\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 16,\n                  \"offset\": 55\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 16,\n                  \"offset\": 55\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 56\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \":Effort:   5\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 56\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 68\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 13,\n                  \"offset\": 68\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 69\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"drawer.end\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 69\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 6,\n                  \"offset\": 74\n                }\n              },\n              \"data\": {\n                \"hash\": 32\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 6,\n              \"offset\": 74\n            }\n          },\n          \"data\": {\n            \"hash\": 5\n          }\n        },\n        {\n          \"type\": \"emptyLine\",\n          \"position\": {\n            \"start\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 75\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 75\n            }\n          },\n          \"data\": {\n            \"hash\": 18\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 7,\n          \"column\": 1,\n          \"offset\": 76\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 7,\n                  \"column\": 1,\n                  \"offset\": 76\n                },\n                \"end\": {\n                  \"line\": 7,\n                  \"column\": 2,\n                  \"offset\": 77\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline with drawer\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 7,\n                  \"column\": 3,\n                  \"offset\": 78\n                },\n                \"end\": {\n                  \"line\": 7,\n                  \"column\": 23,\n                  \"offset\": 98\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 7,\n              \"column\": 1,\n              \"offset\": 76\n            },\n            \"end\": {\n              \"line\": 8,\n              \"column\": 1,\n              \"offset\": 99\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"drawer\",\n          \"name\": \"LOG\",\n          \"value\": \"\\nhere are\\nsome log\\n\",\n          \"children\": [\n            {\n              \"type\": \"drawer.begin\",\n              \"name\": \"LOG\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 8,\n                  \"column\": 1,\n                  \"offset\": 99\n                },\n                \"end\": {\n                  \"line\": 8,\n                  \"column\": 6,\n                  \"offset\": 104\n                }\n              },\n              \"data\": {\n                \"hash\": 31\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 8,\n                  \"column\": 6,\n                  \"offset\": 104\n                },\n                \"end\": {\n                  \"line\": 9,\n                  \"column\": 1,\n                  \"offset\": 105\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"here are\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 9,\n                  \"column\": 1,\n                  \"offset\": 105\n                },\n                \"end\": {\n                  \"line\": 9,\n                  \"column\": 9,\n                  \"offset\": 113\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 9,\n                  \"column\": 9,\n                  \"offset\": 113\n                },\n                \"end\": {\n                  \"line\": 10,\n                  \"column\": 1,\n                  \"offset\": 114\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"some log\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 10,\n                  \"column\": 1,\n                  \"offset\": 114\n                },\n                \"end\": {\n                  \"line\": 10,\n                  \"column\": 9,\n                  \"offset\": 122\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 10,\n                  \"column\": 9,\n                  \"offset\": 122\n                },\n                \"end\": {\n                  \"line\": 11,\n                  \"column\": 1,\n                  \"offset\": 123\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"drawer.end\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 11,\n                  \"column\": 1,\n                  \"offset\": 123\n                },\n                \"end\": {\n                  \"line\": 11,\n                  \"column\": 6,\n                  \"offset\": 128\n                }\n              },\n              \"data\": {\n                \"hash\": 32\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 8,\n              \"column\": 1,\n              \"offset\": 99\n            },\n            \"end\": {\n              \"line\": 11,\n              \"column\": 6,\n              \"offset\": 128\n            }\n          },\n          \"data\": {\n            \"hash\": 5\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 7,\n          \"column\": 1,\n          \"offset\": 76\n        },\n        \"end\": {\n          \"line\": 11,\n          \"column\": 7,\n          \"offset\": 129\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 11,\n      \"column\": 7,\n      \"offset\": 129\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/drawers.org",
    "content": "* headline with properties\n:PROPERTIES:\n:CATEGORY: test\n:Effort:   5\n:END:\n\n* headline with drawer\n:LOG:\nhere are\nsome log\n:END:\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/keyword.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"todo\": \"TODO NEXT | DONE\"\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TODO\",\n      \"value\": \"TODO NEXT | DONE\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 25,\n          \"offset\": 24\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 25\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 25\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": true,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 26\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 27\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"todo\",\n              \"keyword\": \"TODO\",\n              \"actionable\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 28\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 7,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 26\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"with keyword\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 33\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 20,\n                  \"offset\": 45\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 46\n            }\n          },\n          \"keyword\": \"TODO\",\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 26\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 46\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": true,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 46\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 2,\n                  \"offset\": 47\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"todo\",\n              \"keyword\": \"NEXT\",\n              \"actionable\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 3,\n                  \"offset\": 48\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 7,\n                  \"offset\": 52\n                }\n              },\n              \"data\": {\n                \"hash\": 26\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"with keyword\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 8,\n                  \"offset\": 53\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 20,\n                  \"offset\": 65\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 46\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 66\n            }\n          },\n          \"keyword\": \"NEXT\",\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 46\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 66\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 66\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 67\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"todo\",\n              \"keyword\": \"DONE\",\n              \"actionable\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 68\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 7,\n                  \"offset\": 72\n                }\n              },\n              \"data\": {\n                \"hash\": 26\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"with keyword\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 8,\n                  \"offset\": 73\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 20,\n                  \"offset\": 85\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 66\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 21,\n              \"offset\": 86\n            }\n          },\n          \"keyword\": \"DONE\",\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 66\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 21,\n          \"offset\": 86\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 21,\n      \"offset\": 86\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/keyword.org",
    "content": "#+TODO: TODO NEXT | DONE\n\n* TODO with keyword\n* NEXT with keyword\n* DONE with keyword\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/nested.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline 1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 13,\n                  \"offset\": 12\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 13\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"paragraph\",\n          \"children\": [\n            {\n              \"type\": \"text\",\n              \"value\": \"Paragraph\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 13\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 22\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 22\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 13\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 23\n            }\n          },\n          \"data\": {\n            \"hash\": 13\n          }\n        },\n        {\n          \"type\": \"section\",\n          \"level\": 2,\n          \"properties\": {},\n          \"children\": [\n            {\n              \"type\": \"headline\",\n              \"actionable\": false,\n              \"children\": [\n                {\n                  \"type\": \"stars\",\n                  \"level\": 2,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 1,\n                      \"offset\": 23\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 3,\n                      \"offset\": 25\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 25\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"headline 1.1\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 4,\n                      \"offset\": 26\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 16,\n                      \"offset\": 38\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"level\": 2,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 23\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 39\n                }\n              },\n              \"data\": {\n                \"hash\": 12\n              }\n            },\n            {\n              \"type\": \"section\",\n              \"level\": 3,\n              \"properties\": {},\n              \"children\": [\n                {\n                  \"type\": \"headline\",\n                  \"actionable\": false,\n                  \"children\": [\n                    {\n                      \"type\": \"stars\",\n                      \"level\": 3,\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 1,\n                          \"offset\": 39\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 4,\n                          \"offset\": 42\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 25\n                      }\n                    },\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"headline 1.1.1\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 5,\n                          \"offset\": 43\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 19,\n                          \"offset\": 57\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    }\n                  ],\n                  \"level\": 3,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 1,\n                      \"offset\": 39\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 1,\n                      \"offset\": 58\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 12\n                  }\n                },\n                {\n                  \"type\": \"paragraph\",\n                  \"children\": [\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"content\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 1,\n                          \"offset\": 58\n                        },\n                        \"end\": {\n                          \"line\": 5,\n                          \"column\": 8,\n                          \"offset\": 65\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    },\n                    {\n                      \"type\": \"newline\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 8,\n                          \"offset\": 65\n                        },\n                        \"end\": {\n                          \"line\": 6,\n                          \"column\": 1,\n                          \"offset\": 66\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 17\n                      }\n                    },\n                    {\n                      \"type\": \"emptyLine\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 6,\n                          \"column\": 1,\n                          \"offset\": 66\n                        },\n                        \"end\": {\n                          \"line\": 6,\n                          \"column\": 1,\n                          \"offset\": 66\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 18\n                      }\n                    }\n                  ],\n                  \"attributes\": {},\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 1,\n                      \"offset\": 58\n                    },\n                    \"end\": {\n                      \"line\": 6,\n                      \"column\": 1,\n                      \"offset\": 66\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 13\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 39\n                },\n                \"end\": {\n                  \"line\": 7,\n                  \"column\": 1,\n                  \"offset\": 67\n                }\n              },\n              \"data\": {\n                \"hash\": 1\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 23\n            },\n            \"end\": {\n              \"line\": 7,\n              \"column\": 1,\n              \"offset\": 67\n            }\n          },\n          \"data\": {\n            \"hash\": 1\n          }\n        },\n        {\n          \"type\": \"section\",\n          \"level\": 2,\n          \"properties\": {},\n          \"children\": [\n            {\n              \"type\": \"headline\",\n              \"actionable\": false,\n              \"children\": [\n                {\n                  \"type\": \"stars\",\n                  \"level\": 2,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 7,\n                      \"column\": 1,\n                      \"offset\": 67\n                    },\n                    \"end\": {\n                      \"line\": 7,\n                      \"column\": 3,\n                      \"offset\": 69\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 25\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"headline 1.2\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 7,\n                      \"column\": 4,\n                      \"offset\": 70\n                    },\n                    \"end\": {\n                      \"line\": 7,\n                      \"column\": 16,\n                      \"offset\": 82\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"level\": 2,\n              \"position\": {\n                \"start\": {\n                  \"line\": 7,\n                  \"column\": 1,\n                  \"offset\": 67\n                },\n                \"end\": {\n                  \"line\": 8,\n                  \"column\": 1,\n                  \"offset\": 83\n                }\n              },\n              \"data\": {\n                \"hash\": 12\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 7,\n              \"column\": 1,\n              \"offset\": 67\n            },\n            \"end\": {\n              \"line\": 8,\n              \"column\": 1,\n              \"offset\": 83\n            }\n          },\n          \"data\": {\n            \"hash\": 1\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 8,\n          \"column\": 1,\n          \"offset\": 83\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 8,\n                  \"column\": 1,\n                  \"offset\": 83\n                },\n                \"end\": {\n                  \"line\": 8,\n                  \"column\": 2,\n                  \"offset\": 84\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline 2\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 8,\n                  \"column\": 3,\n                  \"offset\": 85\n                },\n                \"end\": {\n                  \"line\": 8,\n                  \"column\": 13,\n                  \"offset\": 95\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 8,\n              \"column\": 1,\n              \"offset\": 83\n            },\n            \"end\": {\n              \"line\": 9,\n              \"column\": 1,\n              \"offset\": 96\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"section\",\n          \"level\": 2,\n          \"properties\": {},\n          \"children\": [\n            {\n              \"type\": \"headline\",\n              \"actionable\": false,\n              \"children\": [\n                {\n                  \"type\": \"stars\",\n                  \"level\": 2,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 9,\n                      \"column\": 1,\n                      \"offset\": 96\n                    },\n                    \"end\": {\n                      \"line\": 9,\n                      \"column\": 3,\n                      \"offset\": 98\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 25\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"headline 2.2\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 9,\n                      \"column\": 4,\n                      \"offset\": 99\n                    },\n                    \"end\": {\n                      \"line\": 9,\n                      \"column\": 16,\n                      \"offset\": 111\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"level\": 2,\n              \"position\": {\n                \"start\": {\n                  \"line\": 9,\n                  \"column\": 1,\n                  \"offset\": 96\n                },\n                \"end\": {\n                  \"line\": 9,\n                  \"column\": 17,\n                  \"offset\": 112\n                }\n              },\n              \"data\": {\n                \"hash\": 12\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 9,\n              \"column\": 1,\n              \"offset\": 96\n            },\n            \"end\": {\n              \"line\": 9,\n              \"column\": 17,\n              \"offset\": 112\n            }\n          },\n          \"data\": {\n            \"hash\": 1\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 8,\n          \"column\": 1,\n          \"offset\": 83\n        },\n        \"end\": {\n          \"line\": 9,\n          \"column\": 17,\n          \"offset\": 112\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 9,\n      \"column\": 17,\n      \"offset\": 112\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/nested.org",
    "content": "* headline 1\nParagraph\n** headline 1.1\n*** headline 1.1.1\ncontent\n\n** headline 1.2\n* headline 2\n** headline 2.2\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/planning.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"with deadline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 16,\n                  \"offset\": 15\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 16\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"planning\",\n          \"keyword\": \"DEADLINE\",\n          \"timestamp\": {\n            \"date\": \"2021-08-19T12:00:00.000Z\"\n          },\n          \"children\": [\n            {\n              \"type\": \"planning.keyword\",\n              \"value\": \"DEADLINE\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 16\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 25\n                }\n              },\n              \"data\": {\n                \"hash\": 38\n              }\n            },\n            {\n              \"type\": \"planning.timestamp\",\n              \"value\": {\n                \"date\": \"2021-08-19T12:00:00.000Z\"\n              },\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 25\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 27,\n                  \"offset\": 42\n                }\n              },\n              \"data\": {\n                \"hash\": 39\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 16\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 27,\n              \"offset\": 42\n            }\n          },\n          \"data\": {\n            \"hash\": 6\n          }\n        },\n        {\n          \"type\": \"emptyLine\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 43\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 43\n            }\n          },\n          \"data\": {\n            \"hash\": 18\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 44\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 44\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 2,\n                  \"offset\": 45\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"with deadline and scheduled\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 3,\n                  \"offset\": 46\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 30,\n                  \"offset\": 73\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 44\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 74\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"planning\",\n          \"keyword\": \"DEADLINE\",\n          \"timestamp\": {\n            \"date\": \"2021-08-26T12:00:00.000Z\"\n          },\n          \"children\": [\n            {\n              \"type\": \"planning.keyword\",\n              \"value\": \"DEADLINE\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 74\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 10,\n                  \"offset\": 83\n                }\n              },\n              \"data\": {\n                \"hash\": 38\n              }\n            },\n            {\n              \"type\": \"planning.timestamp\",\n              \"value\": {\n                \"date\": \"2021-08-26T12:00:00.000Z\"\n              },\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 10,\n                  \"offset\": 83\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 28,\n                  \"offset\": 101\n                }\n              },\n              \"data\": {\n                \"hash\": 39\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 74\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 28,\n              \"offset\": 101\n            }\n          },\n          \"data\": {\n            \"hash\": 6\n          }\n        },\n        {\n          \"type\": \"planning\",\n          \"keyword\": \"SCHEDULED\",\n          \"timestamp\": {\n            \"date\": \"2021-08-02T12:00:00.000Z\"\n          },\n          \"children\": [\n            {\n              \"type\": \"planning.keyword\",\n              \"value\": \"SCHEDULED\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 28,\n                  \"offset\": 101\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 38,\n                  \"offset\": 111\n                }\n              },\n              \"data\": {\n                \"hash\": 38\n              }\n            },\n            {\n              \"type\": \"planning.timestamp\",\n              \"value\": {\n                \"date\": \"2021-08-02T12:00:00.000Z\"\n              },\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 38,\n                  \"offset\": 111\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 56,\n                  \"offset\": 129\n                }\n              },\n              \"data\": {\n                \"hash\": 39\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 28,\n              \"offset\": 101\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 56,\n              \"offset\": 129\n            }\n          },\n          \"data\": {\n            \"hash\": 6\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 44\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 56,\n          \"offset\": 129\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 56,\n      \"offset\": 129\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/planning.org",
    "content": "* with deadline\nDEADLINE: <2021-08-20 Fri>\n\n* with deadline and scheduled\nDEADLINE: <2021-08-27 Fri> SCHEDULED: <2021-08-03 Tue>\n"
  },
  {
    "path": "packages/orga/src/__tests__/headline/with tags.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": false,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"headline1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 12,\n                  \"offset\": 11\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 12\n            }\n          },\n          \"data\": {\n            \"hash\": 12\n          }\n        },\n        {\n          \"type\": \"section\",\n          \"level\": 2,\n          \"properties\": {},\n          \"children\": [\n            {\n              \"type\": \"headline\",\n              \"actionable\": false,\n              \"children\": [\n                {\n                  \"type\": \"stars\",\n                  \"level\": 2,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 1,\n                      \"offset\": 12\n                    },\n                    \"end\": {\n                      \"line\": 2,\n                      \"column\": 3,\n                      \"offset\": 14\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 25\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"headline2\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 4,\n                      \"offset\": 15\n                    },\n                    \"end\": {\n                      \"line\": 2,\n                      \"column\": 13,\n                      \"offset\": 24\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"tags\",\n                  \"tags\": [\n                    \"tag1\",\n                    \"tag2\"\n                  ],\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 14,\n                      \"offset\": 25\n                    },\n                    \"end\": {\n                      \"line\": 2,\n                      \"column\": 25,\n                      \"offset\": 36\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 28\n                  }\n                }\n              ],\n              \"level\": 2,\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 12\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 37\n                }\n              },\n              \"tags\": [\n                \"tag1\",\n                \"tag2\"\n              ],\n              \"data\": {\n                \"hash\": 12\n              }\n            },\n            {\n              \"type\": \"section\",\n              \"level\": 3,\n              \"properties\": {},\n              \"children\": [\n                {\n                  \"type\": \"headline\",\n                  \"actionable\": false,\n                  \"children\": [\n                    {\n                      \"type\": \"stars\",\n                      \"level\": 3,\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 1,\n                          \"offset\": 37\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 4,\n                          \"offset\": 40\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 25\n                      }\n                    },\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"headline3\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 5,\n                          \"offset\": 41\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 14,\n                          \"offset\": 50\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    },\n                    {\n                      \"type\": \"tags\",\n                      \"tags\": [\n                        \"#tag\",\n                        \"@tag\"\n                      ],\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 15,\n                          \"offset\": 51\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 26,\n                          \"offset\": 62\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 28\n                      }\n                    }\n                  ],\n                  \"level\": 3,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 1,\n                      \"offset\": 37\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 27,\n                      \"offset\": 63\n                    }\n                  },\n                  \"tags\": [\n                    \"#tag\",\n                    \"@tag\"\n                  ],\n                  \"data\": {\n                    \"hash\": 12\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 37\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 27,\n                  \"offset\": 63\n                }\n              },\n              \"data\": {\n                \"hash\": 1\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 12\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 27,\n              \"offset\": 63\n            }\n          },\n          \"data\": {\n            \"hash\": 1\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 27,\n          \"offset\": 63\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 27,\n      \"offset\": 63\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/headline/with tags.org",
    "content": "* headline1\n** headline2\t:tag1:tag2:\n*** headline3 :#tag:@tag:\n"
  },
  {
    "path": "packages/orga/src/__tests__/hr/standard.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"some text here\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 15,\n              \"offset\": 14\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 15,\n              \"offset\": 14\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 15\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 15\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    },\n    {\n      \"type\": \"hr\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 15\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 6,\n          \"offset\": 20\n        }\n      },\n      \"data\": {\n        \"hash\": 16\n      }\n    },\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"some other text here\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 21\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 21,\n              \"offset\": 41\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 21,\n              \"offset\": 41\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 42\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"some more\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 42\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 10,\n              \"offset\": 51\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 10,\n              \"offset\": 51\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 11,\n              \"offset\": 52\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 21\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 11,\n          \"offset\": 52\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 4,\n      \"column\": 11,\n      \"offset\": 52\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/hr/standard.org",
    "content": "some text here\n-----\nsome other text here\nsome more\n"
  },
  {
    "path": "packages/orga/src/__tests__/index.test.ts",
    "content": "import assert from 'node:assert'\nimport { promises as fs, lstatSync, readdirSync } from 'node:fs'\nimport * as path from 'node:path'\nimport { describe, it } from 'node:test'\nimport { parse } from '../index.js'\n\nconst specs: { name: string; input: string; output: string }[] = []\n// set to true for updating snapshots\nconst update = false\nconst __dirname = path.dirname(new URL(import.meta.url).pathname)\n\nconst readSpec = (dir: string = __dirname) => {\n\tconst files = readdirSync(dir)\n\tfor (const file of files) {\n\t\tconst abs = path.join(dir, file)\n\t\tif (lstatSync(abs).isDirectory()) {\n\t\t\treadSpec(abs)\n\t\t} else {\n\t\t\tif (file.endsWith('.org')) {\n\t\t\t\tconst name = path\n\t\t\t\t\t.relative(__dirname, abs)\n\t\t\t\t\t.split('/')\n\t\t\t\t\t.join(' ')\n\t\t\t\t\t.replace(/\\.org$/, '')\n\n\t\t\t\tspecs.push({\n\t\t\t\t\tname,\n\t\t\t\t\tinput: abs,\n\t\t\t\t\toutput: abs.replace(/\\.org$/, '.json')\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n}\n\nreadSpec()\n\nfunction removeUndefined(obj: any) {\n\tfor (const key in obj) {\n\t\tif (obj[key] === undefined) {\n\t\t\tdelete obj[key]\n\t\t} else if (Array.isArray(obj[key])) {\n\t\t\tfor (let i = 0; i < obj[key].length; i++) {\n\t\t\t\tremoveUndefined(obj[key][i])\n\t\t\t}\n\t\t} else if (typeof obj[key] === 'object') {\n\t\t\tremoveUndefined(obj[key])\n\t\t}\n\t}\n\treturn obj\n}\n\nconst dateReviver = (_key: string, value: any) => {\n\tif (typeof value === 'string') {\n\t\tconst isoDateRegex = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{3})?Z$/\n\t\tif (isoDateRegex.test(value)) {\n\t\t\treturn new Date(value)\n\t\t}\n\t}\n\treturn value\n}\n\ndescribe('parser', () => {\n\tspecs.forEach(({ name, input, output }) => {\n\t\tit(`${name}`, async () => {\n\t\t\tconst text = await fs.readFile(input, { encoding: 'utf8' })\n\t\t\tconst tree = parse(text, { timezone: 'Pacific/Auckland' })\n\t\t\tif (update) {\n\t\t\t\tawait fs.writeFile(output, JSON.stringify(tree, null, 2), 'utf8')\n\t\t\t} else {\n\t\t\t\tassert.deepStrictEqual(\n\t\t\t\t\tremoveUndefined(tree),\n\t\t\t\t\tJSON.parse(\n\t\t\t\t\t\tawait fs.readFile(output, { encoding: 'utf8' }),\n\t\t\t\t\t\tdateReviver\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t}\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/multiple todo.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"todo\": [\n      \"TODO NEXT | DONE\",\n      \"DRAFT PUBLISHED\",\n      \"BUG(b) FEATURE(f) | DONE(d)\"\n    ]\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TODO\",\n      \"value\": \"TODO NEXT | DONE\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 25,\n          \"offset\": 24\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TODO\",\n      \"value\": \"DRAFT PUBLISHED\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 25\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 24,\n          \"offset\": 48\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TODO\",\n      \"value\": \"BUG(b) FEATURE(f) | DONE(d)\",\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 49\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 36,\n          \"offset\": 84\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 85\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 85\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": true,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 86\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 87\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"todo\",\n              \"keyword\": \"DRAFT\",\n              \"actionable\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 88\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 8,\n                  \"offset\": 93\n                }\n              },\n              \"data\": {\n                \"hash\": 26\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Some Headline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 94\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 22,\n                  \"offset\": 107\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 86\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 23,\n              \"offset\": 108\n            }\n          },\n          \"keyword\": \"DRAFT\",\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 86\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 23,\n          \"offset\": 108\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 23,\n      \"offset\": 108\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/multiple todo.org",
    "content": "#+TODO: TODO NEXT | DONE\n#+TODO: DRAFT PUBLISHED\n#+TODO: BUG(b) FEATURE(f) | DONE(d)\n\n* DRAFT Some Headline\n"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/other.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"title\": \"this is the title\",\n    \"tags\": \"tag1 tag2\"\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TITLE\",\n      \"value\": \"this is the title\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 27,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TAGS\",\n      \"value\": \"tag1 tag2\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 27\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 18,\n          \"offset\": 44\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 45\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 45\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"hello\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 46\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 6,\n              \"offset\": 51\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 6,\n              \"offset\": 51\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 7,\n              \"offset\": 52\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 46\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 7,\n          \"offset\": 52\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 4,\n      \"column\": 7,\n      \"offset\": 52\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/other.org",
    "content": "#+TITLE: this is the title\n#+TAGS: tag1 tag2\n\nhello\n"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/todo.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"todo\": \"TODO NEXT | DONE\"\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n      \"key\": \"TODO\",\n      \"value\": \"TODO NEXT | DONE\",\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 25,\n          \"offset\": 24\n        }\n      },\n      \"data\": {\n        \"hash\": 36\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 25\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 25\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"properties\": {},\n      \"children\": [\n        {\n          \"type\": \"headline\",\n          \"actionable\": true,\n          \"children\": [\n            {\n              \"type\": \"stars\",\n              \"level\": 1,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 26\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 27\n                }\n              },\n              \"data\": {\n                \"hash\": 25\n              }\n            },\n            {\n              \"type\": \"todo\",\n              \"keyword\": \"NEXT\",\n              \"actionable\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 28\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 7,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 26\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Some Headline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 8,\n                  \"offset\": 33\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 21,\n                  \"offset\": 46\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            }\n          ],\n          \"level\": 1,\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 22,\n              \"offset\": 47\n            }\n          },\n          \"keyword\": \"NEXT\",\n          \"data\": {\n            \"hash\": 12\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 26\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 22,\n          \"offset\": 47\n        }\n      },\n      \"data\": {\n        \"hash\": 1\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 22,\n      \"offset\": 47\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/keyword/todo.org",
    "content": "#+TODO: TODO NEXT | DONE\n\n* NEXT Some Headline\n"
  },
  {
    "path": "packages/orga/src/__tests__/latex/does not match.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"\\\\begin{figure}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 15,\n              \"offset\": 14\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 15,\n              \"offset\": 14\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 15\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"x=\\\\sqrt{b}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 15\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 25\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 1,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 16,\n      \"offset\": 41\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/latex/does not match.org",
    "content": "\\begin{figure}\nx=\\sqrt{b}\n\\end{equation}\n"
  },
  {
    "path": "packages/orga/src/__tests__/latex/latex block.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"latex\",\n      \"name\": \"equation\",\n      \"value\": \"\\\\begin{equation}\\nx=\\\\sqrt{b}\\n\\\\end{equation}\",\n      \"children\": [\n        {\n          \"type\": \"latex.begin\",\n          \"name\": \"equation\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 17,\n              \"offset\": 16\n            }\n          },\n          \"data\": {\n            \"hash\": 33\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 17,\n              \"offset\": 16\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 17\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"x=\\\\sqrt{b}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 17\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 27\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 28\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"latex.end\",\n          \"name\": \"equation\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 28\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 16,\n              \"offset\": 43\n            }\n          },\n          \"data\": {\n            \"hash\": 34\n          }\n        }\n      ],\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 16,\n          \"offset\": 43\n        }\n      },\n      \"data\": {\n        \"hash\": 4\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 16,\n      \"offset\": 43\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/latex/latex block.org",
    "content": "\\begin{equation}\nx=\\sqrt{b}\n\\end{equation}\n"
  },
  {
    "path": "packages/orga/src/__tests__/latex/missing begin.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"x=\\\\sqrt{b}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 11,\n              \"offset\": 10\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 11,\n              \"offset\": 10\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 11\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 1,\n          \"offset\": 11\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 2,\n      \"column\": 16,\n      \"offset\": 26\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/latex/missing begin.org",
    "content": "x=\\sqrt{b}\n\\end{equation}\n"
  },
  {
    "path": "packages/orga/src/__tests__/latex/missing end.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"\\\\begin{equation}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 17,\n              \"offset\": 16\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 17,\n              \"offset\": 16\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 17\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"x=\\\\sqrt{b}\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 17\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 27\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 11,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 12,\n              \"offset\": 28\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 12,\n          \"offset\": 28\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 2,\n      \"column\": 12,\n      \"offset\": 28\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/latex/missing end.org",
    "content": "\\begin{equation}\nx=\\sqrt{b}\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/broken by empty line.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Apple is an American multinational technology company headquartered in\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 73,\n                  \"offset\": 72\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 73,\n                  \"offset\": 72\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 73\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"  Cupertino, California that designs, develops, and sells consumer electronics,\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 73\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 80,\n                  \"offset\": 152\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 80,\n                  \"offset\": 152\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 153\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"emptyLine\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 153\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 153\n                }\n              },\n              \"data\": {\n                \"hash\": 18\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 153\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 153\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 154\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 154\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    },\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"  computer software, and online services.\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 154\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 42,\n              \"offset\": 195\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 42,\n              \"offset\": 195\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 196\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 154\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 196\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    },\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 196\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 197\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 198\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 204\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 204\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 1,\n                  \"offset\": 205\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 196\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 205\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 1,\n                  \"offset\": 205\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 2,\n                  \"offset\": 206\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Banana\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 3,\n                  \"offset\": 207\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 9,\n                  \"offset\": 213\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 9,\n                  \"offset\": 213\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 10,\n                  \"offset\": 214\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 205\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 10,\n              \"offset\": 214\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 196\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 10,\n          \"offset\": 214\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 6,\n      \"column\": 10,\n      \"offset\": 214\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/broken by empty line.org",
    "content": "- Apple is an American multinational technology company headquartered in\n  Cupertino, California that designs, develops, and sells consumer electronics,\n\n  computer software, and online services.\n- Orange\n- Banana\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/descriptive.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"list.item.tag\",\n              \"value\": \"Apple\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                }\n              },\n              \"data\": {\n                \"hash\": 40\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"it's apple\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 12,\n                  \"offset\": 11\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 22,\n                  \"offset\": 21\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 22,\n                  \"offset\": 21\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 22\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 22\n            }\n          },\n          \"tag\": \"Apple\",\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 22\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 2,\n                  \"offset\": 23\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 3,\n                  \"offset\": 24\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 9,\n                  \"offset\": 30\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 9,\n                  \"offset\": 30\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"emptyLine\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 18\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 22\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 31\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 31\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 32\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 32\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    },\n    {\n      \"type\": \"emptyLine\",\n      \"position\": {\n        \"start\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 32\n        },\n        \"end\": {\n          \"line\": 4,\n          \"column\": 1,\n          \"offset\": 32\n        }\n      },\n      \"data\": {\n        \"hash\": 18\n      }\n    },\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 33\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 34\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"XBox\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 35\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 7,\n                  \"offset\": 39\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 7,\n                  \"offset\": 39\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 1,\n                  \"offset\": 40\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 33\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 40\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 1,\n                  \"offset\": 40\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 2,\n                  \"offset\": 41\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"list.item.tag\",\n              \"value\": \"Play Station\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 3,\n                  \"offset\": 42\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 15,\n                  \"offset\": 54\n                }\n              },\n              \"data\": {\n                \"hash\": 40\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"for the gamers\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 19,\n                  \"offset\": 58\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 33,\n                  \"offset\": 72\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 6,\n                  \"column\": 33,\n                  \"offset\": 72\n                },\n                \"end\": {\n                  \"line\": 6,\n                  \"column\": 34,\n                  \"offset\": 73\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 6,\n              \"column\": 1,\n              \"offset\": 40\n            },\n            \"end\": {\n              \"line\": 6,\n              \"column\": 34,\n              \"offset\": 73\n            }\n          },\n          \"tag\": \"Play Station\",\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 5,\n          \"column\": 1,\n          \"offset\": 33\n        },\n        \"end\": {\n          \"line\": 6,\n          \"column\": 34,\n          \"offset\": 73\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 6,\n      \"column\": 34,\n      \"offset\": 73\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/descriptive.org",
    "content": "- Apple :: it's apple\n- Orange\n\n\n- XBox\n- Play Station :: for the gamers\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/multiline.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Apple is an American multinational technology company headquartered in\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 73,\n                  \"offset\": 72\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 73,\n                  \"offset\": 72\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 73\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Cupertino, California that designs, develops, and sells consumer electronics,\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 73\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 78,\n                  \"offset\": 150\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 78,\n                  \"offset\": 150\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 151\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"computer software, and online services.\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 151\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 40,\n                  \"offset\": 190\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 40,\n                  \"offset\": 190\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 191\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 191\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 191\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 2,\n                  \"offset\": 192\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 3,\n                  \"offset\": 193\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 9,\n                  \"offset\": 199\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 9,\n                  \"offset\": 199\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 200\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 191\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 200\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 200\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 201\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"Banana\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 202\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 208\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 208\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 10,\n                  \"offset\": 209\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 200\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 10,\n              \"offset\": 209\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 10,\n          \"offset\": 209\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 10,\n      \"offset\": 209\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/multiline.org",
    "content": "- Apple is an American multinational technology company headquartered in\nCupertino, California that designs, develops, and sells consumer electronics,\ncomputer software, and online services.\n- Orange\n- Banana\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/nested.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": true,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"apple\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 4,\n                  \"offset\": 3\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 3,\n              \"offset\": 11\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list\",\n          \"indent\": 2,\n          \"ordered\": false,\n          \"children\": [\n            {\n              \"type\": \"list.item\",\n              \"indent\": 2,\n              \"children\": [\n                {\n                  \"type\": \"list.item.bullet\",\n                  \"indent\": 2,\n                  \"ordered\": false,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 3,\n                      \"offset\": 11\n                    },\n                    \"end\": {\n                      \"line\": 2,\n                      \"column\": 4,\n                      \"offset\": 12\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 42\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"iPhone\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 5,\n                      \"offset\": 13\n                    },\n                    \"end\": {\n                      \"line\": 2,\n                      \"column\": 11,\n                      \"offset\": 19\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"newline\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 2,\n                      \"column\": 11,\n                      \"offset\": 19\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 1,\n                      \"offset\": 20\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 17\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 3,\n                  \"offset\": 11\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 22\n                }\n              },\n              \"data\": {\n                \"hash\": 11\n              }\n            },\n            {\n              \"type\": \"list.item\",\n              \"indent\": 2,\n              \"children\": [\n                {\n                  \"type\": \"list.item.bullet\",\n                  \"indent\": 2,\n                  \"ordered\": false,\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 3,\n                      \"offset\": 22\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 4,\n                      \"offset\": 23\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 42\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"Mac\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 5,\n                      \"offset\": 24\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 8,\n                      \"offset\": 27\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"newline\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 8,\n                      \"offset\": 27\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 1,\n                      \"offset\": 28\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 17\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 22\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 28\n                }\n              },\n              \"data\": {\n                \"hash\": 11\n              }\n            }\n          ],\n          \"attributes\": {},\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 3,\n              \"offset\": 11\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 28\n            }\n          },\n          \"data\": {\n            \"hash\": 7\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 1,\n                  \"offset\": 28\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 3,\n                  \"offset\": 30\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"banana\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 4,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 10,\n                  \"offset\": 37\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 10,\n                  \"offset\": 37\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 38\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 28\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 38\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 1,\n                  \"offset\": 38\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 39\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 3,\n                  \"offset\": 40\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 46\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 9,\n                  \"offset\": 46\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 10,\n                  \"offset\": 47\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 38\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 10,\n              \"offset\": 47\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 10,\n          \"offset\": 47\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 10,\n      \"offset\": 47\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/nested.org",
    "content": "1. apple\n  - iPhone\n  - Mac\n5. banana\n- orange\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/ordered.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": true,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"apple\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 4,\n                  \"offset\": 3\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 9\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": true,\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 9\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 3,\n                  \"offset\": 11\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"banana\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 4,\n                  \"offset\": 12\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 18\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 10,\n                  \"offset\": 18\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 19\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 9\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 19\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 19\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 20\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 21\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 9,\n                  \"offset\": 27\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 9,\n                  \"offset\": 27\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 10,\n                  \"offset\": 28\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 19\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 10,\n              \"offset\": 28\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 10,\n          \"offset\": 28\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 10,\n      \"offset\": 28\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/ordered.org",
    "content": "1. apple\n5. banana\n- orange\n"
  },
  {
    "path": "packages/orga/src/__tests__/list/unordered.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"list\",\n      \"indent\": 0,\n      \"ordered\": false,\n      \"children\": [\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 1,\n                  \"offset\": 0\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"apple\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 3,\n                  \"offset\": 2\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 8\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 8\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 1,\n                  \"offset\": 8\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 2,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"banana\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 3,\n                  \"offset\": 10\n                },\n                \"end\": {\n                  \"line\": 2,\n                  \"column\": 9,\n                  \"offset\": 16\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 2,\n                  \"column\": 9,\n                  \"offset\": 16\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 17\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 8\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 17\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        },\n        {\n          \"type\": \"list.item\",\n          \"indent\": 0,\n          \"children\": [\n            {\n              \"type\": \"list.item.bullet\",\n              \"indent\": 0,\n              \"ordered\": false,\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 1,\n                  \"offset\": 17\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 18\n                }\n              },\n              \"data\": {\n                \"hash\": 42\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"orange\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 3,\n                  \"offset\": 19\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 9,\n                  \"offset\": 25\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"newline\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 9,\n                  \"offset\": 25\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 10,\n                  \"offset\": 26\n                }\n              },\n              \"data\": {\n                \"hash\": 17\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 17\n            },\n            \"end\": {\n              \"line\": 3,\n              \"column\": 10,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 11\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 3,\n          \"column\": 10,\n          \"offset\": 26\n        }\n      },\n      \"data\": {\n        \"hash\": 7\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 3,\n      \"column\": 10,\n      \"offset\": 26\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/list/unordered.org",
    "content": "- apple\n- banana\n- orange\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/anonymous footnote.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 6,\n                  \"offset\": 5\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"anonymous footnote\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 11,\n                  \"offset\": 10\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 29,\n                  \"offset\": 28\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 29,\n                  \"offset\": 28\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 30,\n              \"offset\": 29\n            }\n          },\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 30,\n              \"offset\": 29\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 31,\n              \"offset\": 30\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 31,\n              \"offset\": 30\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 32,\n              \"offset\": 31\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 32,\n          \"offset\": 31\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 32,\n      \"offset\": 31\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/anonymous footnote.org",
    "content": "with [fn::anonymous footnote].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote reference at the end.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with footnote at the end.\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 26,\n                  \"offset\": 25\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"2\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 31,\n                  \"offset\": 30\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 31,\n                  \"offset\": 30\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 32,\n              \"offset\": 31\n            }\n          },\n          \"label\": \"2\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 32,\n              \"offset\": 31\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 33,\n              \"offset\": 32\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 33,\n          \"offset\": 32\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 33,\n      \"offset\": 32\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote reference at the end.org",
    "content": "with footnote at the end.[fn:2]\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote refernece in the middle.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with footnote\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 14,\n              \"offset\": 13\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 14,\n                  \"offset\": 13\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"1\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 19,\n                  \"offset\": 18\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 19,\n                  \"offset\": 18\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 20,\n                  \"offset\": 19\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 14,\n              \"offset\": 13\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            }\n          },\n          \"label\": \"1\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \" in the middle.\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 20,\n              \"offset\": 19\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 35,\n              \"offset\": 34\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 35,\n              \"offset\": 34\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 36,\n              \"offset\": 35\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 36,\n          \"offset\": 35\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 36,\n      \"offset\": 35\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote refernece in the middle.org",
    "content": "with footnote[fn:1] in the middle.\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote without body.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with anonymous footnote without body\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 37,\n              \"offset\": 36\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 37,\n                  \"offset\": 36\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 41,\n                  \"offset\": 40\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 42,\n                  \"offset\": 41\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 43,\n                  \"offset\": 42\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 37,\n              \"offset\": 36\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 43,\n              \"offset\": 42\n            }\n          },\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 43,\n              \"offset\": 42\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 44,\n              \"offset\": 43\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 44,\n              \"offset\": 43\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 45,\n              \"offset\": 44\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 45,\n          \"offset\": 44\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 45,\n      \"offset\": 44\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/footnote without body.org",
    "content": "with anonymous footnote without body[fn::].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline footnote with style.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 6,\n                  \"offset\": 5\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"3\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 11,\n                  \"offset\": 10\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"inline footnote \",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 12,\n                  \"offset\": 11\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 28,\n                  \"offset\": 27\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"style\": \"italic\",\n              \"value\": \"with\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 28,\n                  \"offset\": 27\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 34,\n                  \"offset\": 33\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \" style\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 34,\n                  \"offset\": 33\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 40,\n                  \"offset\": 39\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 40,\n                  \"offset\": 39\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 41,\n                  \"offset\": 40\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 41,\n              \"offset\": 40\n            }\n          },\n          \"label\": \"3\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 41,\n              \"offset\": 40\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 42,\n              \"offset\": 41\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 42,\n              \"offset\": 41\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 43,\n              \"offset\": 42\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 43,\n          \"offset\": 42\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 43,\n      \"offset\": 42\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline footnote with style.org",
    "content": "with [fn:3:inline footnote /with/ style].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline footnote.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 6,\n                  \"offset\": 5\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"footnote.label\",\n              \"label\": \"3\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 11,\n                  \"offset\": 10\n                }\n              },\n              \"data\": {\n                \"hash\": 37\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"inline footnote\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 12,\n                  \"offset\": 11\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 27,\n                  \"offset\": 26\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 27,\n                  \"offset\": 26\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 28,\n                  \"offset\": 27\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 28,\n              \"offset\": 27\n            }\n          },\n          \"label\": \"3\",\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 28,\n              \"offset\": 27\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 29,\n              \"offset\": 28\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 29,\n              \"offset\": 28\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 30,\n              \"offset\": 29\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 30,\n          \"offset\": 29\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 30,\n      \"offset\": 29\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline footnote.org",
    "content": "with [fn:3:inline footnote].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline math.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"If \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 4,\n              \"offset\": 3\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"math\",\n          \"value\": \"a^2=b\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 4,\n              \"offset\": 3\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 13,\n              \"offset\": 12\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \" and \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 13,\n              \"offset\": 12\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 18,\n              \"offset\": 17\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"math\",\n          \"value\": \" b=2 \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 18,\n              \"offset\": 17\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 27,\n              \"offset\": 26\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", then the solution must be\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 27,\n              \"offset\": 26\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 54,\n              \"offset\": 53\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 54,\n              \"offset\": 53\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 54\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \"either \",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 54\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 8,\n              \"offset\": 61\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"math\",\n          \"value\": \" a=+\\\\sqrt{2} \",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 8,\n              \"offset\": 61\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 25,\n              \"offset\": 78\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \" or \",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 25,\n              \"offset\": 78\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 29,\n              \"offset\": 82\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"math\",\n          \"value\": \" a=-\\\\sqrt{2} \",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 29,\n              \"offset\": 82\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 46,\n              \"offset\": 99\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 46,\n              \"offset\": 99\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 47,\n              \"offset\": 100\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 47,\n              \"offset\": 100\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 48,\n              \"offset\": 101\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 2,\n          \"column\": 48,\n          \"offset\": 101\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 2,\n      \"column\": 48,\n      \"offset\": 101\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/inline math.org",
    "content": "If $$a^2=b$$ and \\( b=2 \\), then the solution must be\neither $$ a=+\\sqrt{2} $$ or \\[ a=-\\sqrt{2} \\].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/link with style.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"test \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"link\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 6,\n                  \"offset\": 5\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 7,\n                  \"offset\": 6\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"link.path\",\n              \"protocol\": \"https\",\n              \"value\": \"https://orga.js.org/\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 7,\n                  \"offset\": 6\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 29,\n                  \"offset\": 28\n                }\n              },\n              \"data\": {\n                \"hash\": 21\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"style\": \"bold\",\n              \"value\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 36,\n                  \"offset\": 35\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \" with \",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 36,\n                  \"offset\": 35\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 42,\n                  \"offset\": 41\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"style\": \"italic\",\n              \"value\": \"style\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 42,\n                  \"offset\": 41\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 49,\n                  \"offset\": 48\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 50,\n                  \"offset\": 49\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 51,\n                  \"offset\": 50\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 51,\n              \"offset\": 50\n            }\n          },\n          \"path\": {\n            \"protocol\": \"https\",\n            \"value\": \"https://orga.js.org/\"\n          },\n          \"attributes\": {},\n          \"data\": {\n            \"hash\": 20\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 51,\n              \"offset\": 50\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 52,\n              \"offset\": 51\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 52,\n              \"offset\": 51\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 53,\n              \"offset\": 52\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 53,\n          \"offset\": 52\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 53,\n      \"offset\": 52\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/link with style.org",
    "content": "test [[https://orga.js.org/][*link* with /style/]].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/link.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"it's a \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 8,\n              \"offset\": 7\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"link\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 8,\n                  \"offset\": 7\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"link.path\",\n              \"protocol\": \"https\",\n              \"value\": \"https://orga.js.org/\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 9,\n                  \"offset\": 8\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 31,\n                  \"offset\": 30\n                }\n              },\n              \"data\": {\n                \"hash\": 21\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 32,\n                  \"offset\": 31\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 36,\n                  \"offset\": 35\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"link\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 37,\n                  \"offset\": 36\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 38,\n                  \"offset\": 37\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 8,\n              \"offset\": 7\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 38,\n              \"offset\": 37\n            }\n          },\n          \"path\": {\n            \"protocol\": \"https\",\n            \"value\": \"https://orga.js.org/\"\n          },\n          \"attributes\": {},\n          \"data\": {\n            \"hash\": 20\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 38,\n              \"offset\": 37\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 39,\n              \"offset\": 38\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 39,\n              \"offset\": 38\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 40,\n              \"offset\": 39\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 40,\n          \"offset\": 39\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 40,\n      \"offset\": 39\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/link.org",
    "content": "it's a [[https://orga.js.org/][link]].\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/nested footnote.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"with \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"footnote.reference\",\n          \"children\": [\n            {\n              \"type\": \"opening\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 6,\n                  \"offset\": 5\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 10,\n                  \"offset\": 9\n                }\n              },\n              \"data\": {\n                \"hash\": 22\n              }\n            },\n            {\n              \"type\": \"text\",\n              \"value\": \"nested \",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 11,\n                  \"offset\": 10\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                }\n              },\n              \"data\": {\n                \"hash\": 19\n              }\n            },\n            {\n              \"type\": \"footnote.reference\",\n              \"children\": [\n                {\n                  \"type\": \"opening\",\n                  \"element\": \"footnote.reference\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 18,\n                      \"offset\": 17\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 22,\n                      \"offset\": 21\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 22\n                  }\n                },\n                {\n                  \"type\": \"footnote.label\",\n                  \"label\": \"1\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 22,\n                      \"offset\": 21\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 23,\n                      \"offset\": 22\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 37\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"footnote\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 24,\n                      \"offset\": 23\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 32,\n                      \"offset\": 31\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"closing\",\n                  \"element\": \"footnote.reference\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 32,\n                      \"offset\": 31\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 33,\n                      \"offset\": 32\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 23\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 33,\n                  \"offset\": 32\n                }\n              },\n              \"label\": \"1\",\n              \"data\": {\n                \"hash\": 24\n              }\n            },\n            {\n              \"type\": \"closing\",\n              \"element\": \"footnote.reference\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 33,\n                  \"offset\": 32\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 34,\n                  \"offset\": 33\n                }\n              },\n              \"data\": {\n                \"hash\": 23\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 34,\n              \"offset\": 33\n            }\n          },\n          \"data\": {\n            \"hash\": 24\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 34,\n              \"offset\": 33\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 35,\n              \"offset\": 34\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 35,\n          \"offset\": 34\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 35,\n      \"offset\": 34\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/nested footnote.org",
    "content": "with [fn::nested [fn:1:footnote]]\n"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/styled text.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n        {\n          \"type\": \"text\",\n          \"value\": \"text \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"bold\",\n          \"value\": \"bold\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 6,\n              \"offset\": 5\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 12,\n              \"offset\": 11\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 12,\n              \"offset\": 11\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 14,\n              \"offset\": 13\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"verbatim\",\n          \"value\": \"verbatim\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 14,\n              \"offset\": 13\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 24,\n              \"offset\": 23\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 24,\n              \"offset\": 23\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"italic\",\n          \"value\": \"italic\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 26,\n              \"offset\": 25\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 34,\n              \"offset\": 33\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 34,\n              \"offset\": 33\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 36,\n              \"offset\": 35\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"strikeThrough\",\n          \"value\": \"strike through\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 36,\n              \"offset\": 35\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 52,\n              \"offset\": 51\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 52,\n              \"offset\": 51\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 54,\n              \"offset\": 53\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"underline\",\n          \"value\": \"underline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 54,\n              \"offset\": 53\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 65,\n              \"offset\": 64\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \", \",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 65,\n              \"offset\": 64\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 67,\n              \"offset\": 66\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"style\": \"code\",\n          \"value\": \"code\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 67,\n              \"offset\": 66\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 73,\n              \"offset\": 72\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"text\",\n          \"value\": \".\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 73,\n              \"offset\": 72\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 74,\n              \"offset\": 73\n            }\n          },\n          \"data\": {\n            \"hash\": 19\n          }\n        },\n        {\n          \"type\": \"newline\",\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 74,\n              \"offset\": 73\n            },\n            \"end\": {\n              \"line\": 1,\n              \"column\": 75,\n              \"offset\": 74\n            }\n          },\n          \"data\": {\n            \"hash\": 17\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 1,\n          \"column\": 75,\n          \"offset\": 74\n        }\n      },\n      \"data\": {\n        \"hash\": 13\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 1,\n      \"column\": 75,\n      \"offset\": 74\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/paragraph/styled text.org",
    "content": "text *bold*, =verbatim=, /italic/, +strike through+, _underline_, ~code~.\n"
  },
  {
    "path": "packages/orga/src/__tests__/table/standard.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"table\",\n      \"children\": [\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Name         \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 2,\n                      \"offset\": 1\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 16,\n                      \"offset\": 15\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 16,\n                  \"offset\": 15\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 16,\n                  \"offset\": 15\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 17,\n                  \"offset\": 16\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Species    \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 17,\n                      \"offset\": 16\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 29,\n                      \"offset\": 28\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 17,\n                  \"offset\": 16\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 29,\n                  \"offset\": 28\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 29,\n                  \"offset\": 28\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Gender \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 30,\n                      \"offset\": 29\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 38,\n                      \"offset\": 37\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 30,\n                  \"offset\": 29\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 38,\n                  \"offset\": 37\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 38,\n                  \"offset\": 37\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 39,\n                  \"offset\": 38\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Role         \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 39,\n                      \"offset\": 38\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 53,\n                      \"offset\": 52\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 39,\n                  \"offset\": 38\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 53,\n                  \"offset\": 52\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 53,\n                  \"offset\": 52\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 54,\n                  \"offset\": 53\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 54\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.hr\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 54\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 54,\n              \"offset\": 107\n            }\n          },\n          \"data\": {\n            \"hash\": 43\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Bruce Wayne  \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 2,\n                      \"offset\": 109\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 16,\n                      \"offset\": 123\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 109\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 16,\n                  \"offset\": 123\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 16,\n                  \"offset\": 123\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 17,\n                  \"offset\": 124\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Human      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 17,\n                      \"offset\": 124\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 29,\n                      \"offset\": 136\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 17,\n                  \"offset\": 124\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 29,\n                  \"offset\": 136\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 29,\n                  \"offset\": 136\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 30,\n                  \"offset\": 137\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" M      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 30,\n                      \"offset\": 137\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 38,\n                      \"offset\": 145\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 30,\n                  \"offset\": 137\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 38,\n                  \"offset\": 145\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 38,\n                  \"offset\": 145\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 39,\n                  \"offset\": 146\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Batman       \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 39,\n                      \"offset\": 146\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 53,\n                      \"offset\": 160\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 39,\n                  \"offset\": 146\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 53,\n                  \"offset\": 160\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 53,\n                  \"offset\": 160\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 54,\n                  \"offset\": 161\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 108\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 162\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Clark Kent   \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 2,\n                      \"offset\": 163\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 16,\n                      \"offset\": 177\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 2,\n                  \"offset\": 163\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 16,\n                  \"offset\": 177\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 16,\n                  \"offset\": 177\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 17,\n                  \"offset\": 178\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Kryptonian \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 17,\n                      \"offset\": 178\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 29,\n                      \"offset\": 190\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 17,\n                  \"offset\": 178\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 29,\n                  \"offset\": 190\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 29,\n                  \"offset\": 190\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 30,\n                  \"offset\": 191\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" M      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 30,\n                      \"offset\": 191\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 38,\n                      \"offset\": 199\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 30,\n                  \"offset\": 191\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 38,\n                  \"offset\": 199\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 38,\n                  \"offset\": 199\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 39,\n                  \"offset\": 200\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Superman     \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 39,\n                      \"offset\": 200\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 53,\n                      \"offset\": 214\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 39,\n                  \"offset\": 200\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 53,\n                  \"offset\": 214\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 53,\n                  \"offset\": 214\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 54,\n                  \"offset\": 215\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 162\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 216\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Diana Prince \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 2,\n                      \"offset\": 217\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 16,\n                      \"offset\": 231\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 217\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 16,\n                  \"offset\": 231\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 16,\n                  \"offset\": 231\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 17,\n                  \"offset\": 232\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Amazonian  \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 17,\n                      \"offset\": 232\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 29,\n                      \"offset\": 244\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 17,\n                  \"offset\": 232\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 29,\n                  \"offset\": 244\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 29,\n                  \"offset\": 244\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 30,\n                  \"offset\": 245\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" F      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 30,\n                      \"offset\": 245\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 38,\n                      \"offset\": 253\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 30,\n                  \"offset\": 245\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 38,\n                  \"offset\": 253\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 38,\n                  \"offset\": 253\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 39,\n                  \"offset\": 254\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Wonder Woman \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 39,\n                      \"offset\": 254\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 53,\n                      \"offset\": 268\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 39,\n                  \"offset\": 254\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 53,\n                  \"offset\": 268\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 53,\n                  \"offset\": 268\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 54,\n                  \"offset\": 269\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 216\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 55,\n              \"offset\": 270\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 55,\n          \"offset\": 270\n        }\n      },\n      \"data\": {\n        \"hash\": 8\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 55,\n      \"offset\": 270\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/table/standard.org",
    "content": "| Name         | Species    | Gender | Role         |\n|--------------+------------+--------+--------------|\n| Bruce Wayne  | Human      | M      | Batman       |\n| Clark Kent   | Kryptonian | M      | Superman     |\n| Diana Prince | Amazonian  | F      | Wonder Woman |\n"
  },
  {
    "path": "packages/orga/src/__tests__/table/with inline styles.json",
    "content": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"table\",\n      \"children\": [\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Name           \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 2,\n                      \"offset\": 1\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 18,\n                      \"offset\": 17\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 2,\n                  \"offset\": 1\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 18,\n                  \"offset\": 17\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 19,\n                  \"offset\": 18\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Species      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 19,\n                      \"offset\": 18\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 33,\n                      \"offset\": 32\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 19,\n                  \"offset\": 18\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 33,\n                  \"offset\": 32\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 33,\n                  \"offset\": 32\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 34,\n                  \"offset\": 33\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Gender \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 34,\n                      \"offset\": 33\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 42,\n                      \"offset\": 41\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 34,\n                  \"offset\": 33\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 42,\n                  \"offset\": 41\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 42,\n                  \"offset\": 41\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 43,\n                  \"offset\": 42\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Role         \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 1,\n                      \"column\": 43,\n                      \"offset\": 42\n                    },\n                    \"end\": {\n                      \"line\": 1,\n                      \"column\": 57,\n                      \"offset\": 56\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 43,\n                  \"offset\": 42\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 57,\n                  \"offset\": 56\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 1,\n                  \"column\": 57,\n                  \"offset\": 56\n                },\n                \"end\": {\n                  \"line\": 1,\n                  \"column\": 58,\n                  \"offset\": 57\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 1,\n              \"column\": 1,\n              \"offset\": 0\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 58\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.hr\",\n          \"position\": {\n            \"start\": {\n              \"line\": 2,\n              \"column\": 1,\n              \"offset\": 58\n            },\n            \"end\": {\n              \"line\": 2,\n              \"column\": 58,\n              \"offset\": 115\n            }\n          },\n          \"data\": {\n            \"hash\": 43\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 2,\n                      \"offset\": 117\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 3,\n                      \"offset\": 118\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"bold\",\n                  \"value\": \"Bruce Wayne\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 3,\n                      \"offset\": 118\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 16,\n                      \"offset\": 131\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"  \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 16,\n                      \"offset\": 131\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 18,\n                      \"offset\": 133\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 2,\n                  \"offset\": 117\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 18,\n                  \"offset\": 133\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 18,\n                  \"offset\": 133\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 19,\n                  \"offset\": 134\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 19,\n                      \"offset\": 134\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 20,\n                      \"offset\": 135\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"strikeThrough\",\n                  \"value\": \"Bat\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 20,\n                      \"offset\": 135\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 25,\n                      \"offset\": 140\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \" Human  \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 25,\n                      \"offset\": 140\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 33,\n                      \"offset\": 148\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 19,\n                  \"offset\": 134\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 33,\n                  \"offset\": 148\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 33,\n                  \"offset\": 148\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 34,\n                  \"offset\": 149\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" M      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 34,\n                      \"offset\": 149\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 42,\n                      \"offset\": 157\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 34,\n                  \"offset\": 149\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 42,\n                  \"offset\": 157\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 42,\n                  \"offset\": 157\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 43,\n                  \"offset\": 158\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 43,\n                      \"offset\": 158\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 44,\n                      \"offset\": 159\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"link\",\n                  \"children\": [\n                    {\n                      \"type\": \"opening\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 44,\n                          \"offset\": 159\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 45,\n                          \"offset\": 160\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 22\n                      }\n                    },\n                    {\n                      \"type\": \"link.path\",\n                      \"protocol\": \"https\",\n                      \"value\": \"https://en.wikipedia.org/wiki/Batman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 45,\n                          \"offset\": 160\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 83,\n                          \"offset\": 198\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 21\n                      }\n                    },\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"Batman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 84,\n                          \"offset\": 199\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 90,\n                          \"offset\": 205\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    },\n                    {\n                      \"type\": \"closing\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 3,\n                          \"column\": 91,\n                          \"offset\": 206\n                        },\n                        \"end\": {\n                          \"line\": 3,\n                          \"column\": 92,\n                          \"offset\": 207\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 23\n                      }\n                    }\n                  ],\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 44,\n                      \"offset\": 159\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 92,\n                      \"offset\": 207\n                    }\n                  },\n                  \"path\": {\n                    \"protocol\": \"https\",\n                    \"value\": \"https://en.wikipedia.org/wiki/Batman\"\n                  },\n                  \"attributes\": {},\n                  \"data\": {\n                    \"hash\": 20\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"       \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 3,\n                      \"column\": 92,\n                      \"offset\": 207\n                    },\n                    \"end\": {\n                      \"line\": 3,\n                      \"column\": 99,\n                      \"offset\": 214\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 43,\n                  \"offset\": 158\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 99,\n                  \"offset\": 214\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 3,\n                  \"column\": 99,\n                  \"offset\": 214\n                },\n                \"end\": {\n                  \"line\": 3,\n                  \"column\": 100,\n                  \"offset\": 215\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 3,\n              \"column\": 1,\n              \"offset\": 116\n            },\n            \"end\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 216\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 2,\n                      \"offset\": 217\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 3,\n                      \"offset\": 218\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"underline\",\n                  \"value\": \"Clark Kent\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 3,\n                      \"offset\": 218\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 15,\n                      \"offset\": 230\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"   \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 15,\n                      \"offset\": 230\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 18,\n                      \"offset\": 233\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 2,\n                  \"offset\": 217\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 18,\n                  \"offset\": 233\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 18,\n                  \"offset\": 233\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 19,\n                  \"offset\": 234\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 19,\n                      \"offset\": 234\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 20,\n                      \"offset\": 235\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"verbatim\",\n                  \"value\": \"Kryptonian\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 20,\n                      \"offset\": 235\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 32,\n                      \"offset\": 247\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 32,\n                      \"offset\": 247\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 33,\n                      \"offset\": 248\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 19,\n                  \"offset\": 234\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 33,\n                  \"offset\": 248\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 33,\n                  \"offset\": 248\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 34,\n                  \"offset\": 249\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" M      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 34,\n                      \"offset\": 249\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 42,\n                      \"offset\": 257\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 34,\n                  \"offset\": 249\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 42,\n                  \"offset\": 257\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 42,\n                  \"offset\": 257\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 43,\n                  \"offset\": 258\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 43,\n                      \"offset\": 258\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 44,\n                      \"offset\": 259\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"link\",\n                  \"children\": [\n                    {\n                      \"type\": \"opening\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 44,\n                          \"offset\": 259\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 45,\n                          \"offset\": 260\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 22\n                      }\n                    },\n                    {\n                      \"type\": \"link.path\",\n                      \"protocol\": \"https\",\n                      \"value\": \"https://en.wikipedia.org/wiki/Superman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 45,\n                          \"offset\": 260\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 85,\n                          \"offset\": 300\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 21\n                      }\n                    },\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"Superman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 86,\n                          \"offset\": 301\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 94,\n                          \"offset\": 309\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    },\n                    {\n                      \"type\": \"closing\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 4,\n                          \"column\": 95,\n                          \"offset\": 310\n                        },\n                        \"end\": {\n                          \"line\": 4,\n                          \"column\": 96,\n                          \"offset\": 311\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 23\n                      }\n                    }\n                  ],\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 44,\n                      \"offset\": 259\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 96,\n                      \"offset\": 311\n                    }\n                  },\n                  \"path\": {\n                    \"protocol\": \"https\",\n                    \"value\": \"https://en.wikipedia.org/wiki/Superman\"\n                  },\n                  \"attributes\": {},\n                  \"data\": {\n                    \"hash\": 20\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"     \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 4,\n                      \"column\": 96,\n                      \"offset\": 311\n                    },\n                    \"end\": {\n                      \"line\": 4,\n                      \"column\": 101,\n                      \"offset\": 316\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 43,\n                  \"offset\": 258\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 101,\n                  \"offset\": 316\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 4,\n                  \"column\": 101,\n                  \"offset\": 316\n                },\n                \"end\": {\n                  \"line\": 4,\n                  \"column\": 102,\n                  \"offset\": 317\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 4,\n              \"column\": 1,\n              \"offset\": 216\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 318\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        },\n        {\n          \"type\": \"table.row\",\n          \"children\": [\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 2,\n                      \"offset\": 319\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 3,\n                      \"offset\": 320\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"italic\",\n                  \"value\": \"Diana Prince\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 3,\n                      \"offset\": 320\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 17,\n                      \"offset\": 334\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 17,\n                      \"offset\": 334\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 18,\n                      \"offset\": 335\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 2,\n                  \"offset\": 319\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 18,\n                  \"offset\": 335\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 18,\n                  \"offset\": 335\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 19,\n                  \"offset\": 336\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 19,\n                      \"offset\": 336\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 20,\n                      \"offset\": 337\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"style\": \"code\",\n                  \"value\": \"Amazonian\",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 20,\n                      \"offset\": 337\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 31,\n                      \"offset\": 348\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \"  \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 31,\n                      \"offset\": 348\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 33,\n                      \"offset\": 350\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 19,\n                  \"offset\": 336\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 33,\n                  \"offset\": 350\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 33,\n                  \"offset\": 350\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 34,\n                  \"offset\": 351\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" F      \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 34,\n                      \"offset\": 351\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 42,\n                      \"offset\": 359\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 34,\n                  \"offset\": 351\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 42,\n                  \"offset\": 359\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 42,\n                  \"offset\": 359\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 43,\n                  \"offset\": 360\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            },\n            {\n              \"type\": \"table.cell\",\n              \"children\": [\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 43,\n                      \"offset\": 360\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 44,\n                      \"offset\": 361\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                },\n                {\n                  \"type\": \"link\",\n                  \"children\": [\n                    {\n                      \"type\": \"opening\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 44,\n                          \"offset\": 361\n                        },\n                        \"end\": {\n                          \"line\": 5,\n                          \"column\": 45,\n                          \"offset\": 362\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 22\n                      }\n                    },\n                    {\n                      \"type\": \"link.path\",\n                      \"protocol\": \"https\",\n                      \"value\": \"https://en.wikipedia.org/wiki/Wonder_Woman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 45,\n                          \"offset\": 362\n                        },\n                        \"end\": {\n                          \"line\": 5,\n                          \"column\": 89,\n                          \"offset\": 406\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 21\n                      }\n                    },\n                    {\n                      \"type\": \"text\",\n                      \"value\": \"Wonder Woman\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 90,\n                          \"offset\": 407\n                        },\n                        \"end\": {\n                          \"line\": 5,\n                          \"column\": 102,\n                          \"offset\": 419\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 19\n                      }\n                    },\n                    {\n                      \"type\": \"closing\",\n                      \"element\": \"link\",\n                      \"position\": {\n                        \"start\": {\n                          \"line\": 5,\n                          \"column\": 103,\n                          \"offset\": 420\n                        },\n                        \"end\": {\n                          \"line\": 5,\n                          \"column\": 104,\n                          \"offset\": 421\n                        }\n                      },\n                      \"data\": {\n                        \"hash\": 23\n                      }\n                    }\n                  ],\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 44,\n                      \"offset\": 361\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 104,\n                      \"offset\": 421\n                    }\n                  },\n                  \"path\": {\n                    \"protocol\": \"https\",\n                    \"value\": \"https://en.wikipedia.org/wiki/Wonder_Woman\"\n                  },\n                  \"attributes\": {},\n                  \"data\": {\n                    \"hash\": 20\n                  }\n                },\n                {\n                  \"type\": \"text\",\n                  \"value\": \" \",\n                  \"position\": {\n                    \"start\": {\n                      \"line\": 5,\n                      \"column\": 104,\n                      \"offset\": 421\n                    },\n                    \"end\": {\n                      \"line\": 5,\n                      \"column\": 105,\n                      \"offset\": 422\n                    }\n                  },\n                  \"data\": {\n                    \"hash\": 19\n                  }\n                }\n              ],\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 43,\n                  \"offset\": 360\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 105,\n                  \"offset\": 422\n                }\n              },\n              \"data\": {\n                \"hash\": 10\n              }\n            },\n            {\n              \"type\": \"table.columnSeparator\",\n              \"position\": {\n                \"start\": {\n                  \"line\": 5,\n                  \"column\": 105,\n                  \"offset\": 422\n                },\n                \"end\": {\n                  \"line\": 5,\n                  \"column\": 106,\n                  \"offset\": 423\n                }\n              },\n              \"data\": {\n                \"hash\": 44\n              }\n            }\n          ],\n          \"position\": {\n            \"start\": {\n              \"line\": 5,\n              \"column\": 1,\n              \"offset\": 318\n            },\n            \"end\": {\n              \"line\": 5,\n              \"column\": 107,\n              \"offset\": 424\n            }\n          },\n          \"data\": {\n            \"hash\": 9\n          }\n        }\n      ],\n      \"attributes\": {},\n      \"position\": {\n        \"start\": {\n          \"line\": 1,\n          \"column\": 1,\n          \"offset\": 0\n        },\n        \"end\": {\n          \"line\": 5,\n          \"column\": 107,\n          \"offset\": 424\n        }\n      },\n      \"data\": {\n        \"hash\": 8\n      }\n    }\n  ],\n  \"position\": {\n    \"start\": {\n      \"line\": 1,\n      \"column\": 1,\n      \"offset\": 0\n    },\n    \"end\": {\n      \"line\": 5,\n      \"column\": 107,\n      \"offset\": 424\n    }\n  }\n}"
  },
  {
    "path": "packages/orga/src/__tests__/table/with inline styles.org",
    "content": "| Name           | Species      | Gender | Role         |\n|----------------+--------------+--------+--------------|\n| *Bruce Wayne*  | +Bat+ Human  | M      | [[https://en.wikipedia.org/wiki/Batman][Batman]]       |\n| _Clark Kent_   | =Kryptonian= | M      | [[https://en.wikipedia.org/wiki/Superman][Superman]]     |\n| /Diana Prince/ | ~Amazonian~  | F      | [[https://en.wikipedia.org/wiki/Wonder_Woman][Wonder Woman]] |\n"
  },
  {
    "path": "packages/orga/src/index.ts",
    "content": "import {\n\tdefaultLexerOptions,\n\tdefaultParserOptions,\n\ttype LexerOptions,\n\ttype Options\n} from './options.js'\nimport { parser as _parser, type Parser } from './parse/index.js'\nimport { parse as parseTimestamp } from './timestamp.js'\nimport { todoManager } from './todo.js'\nimport { tokenize as _tokenize, type Lexer } from './tokenize/index.js'\nimport type { Document, Settings } from './types.js'\n\nexport * from './types.js'\nexport { parseTimestamp, type Options as ParseOptions, type Parser }\n\nexport const tokenize = (\n\ttext: string,\n\toptions: Partial<LexerOptions> = {}\n): Lexer => {\n\treturn _tokenize(text, { ...defaultLexerOptions, ...options })\n}\n\nexport const parse = (\n\ttext: string,\n\toptions: Partial<Options> = {}\n): Document => {\n\tconst parser = makeParser(text, options)\n\treturn parser.parse()\n}\n\nexport function makeParser(text: string, options: Partial<Options> = {}) {\n\tconst { range, ..._options } = { ...defaultParserOptions, ...options }\n\tconst todo = todoManager(...getTodo(options.settings))\n\tconst start = range?.start\n\tconst lexer = tokenize(text, {\n\t\t..._options,\n\t\ttodo,\n\t\trange: start ? { start, end: Infinity } : undefined\n\t})\n\treturn _parser(lexer, { ..._options, range })\n}\n\nexport function getSettings(text: string): Settings {\n\t// Stop when seeing a non-keyword, non-empty line.\n\tconst settings: Settings = {}\n\tconst lexer = tokenize(text)\n\n\tlet token = lexer.peek()\n\twhile (token) {\n\t\tif (token.type === 'keyword') {\n\t\t\tconst k = (token.key as string).toLowerCase()\n\t\t\tconst v = (token.value as string).trim()\n\n\t\t\t// Handle multiple values for the same key (like multiple #+todo: lines)\n\t\t\tconst existing = settings[k]\n\t\t\tif (existing) {\n\t\t\t\tif (Array.isArray(existing)) {\n\t\t\t\t\texisting.push(v)\n\t\t\t\t} else if (typeof existing === 'string') {\n\t\t\t\t\tsettings[k] = [existing, v]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsettings[k] = v\n\t\t\t}\n\t\t\tlexer.eat()\n\t\t} else if (token.type === 'newline' || token.type === 'emptyLine') {\n\t\t\tlexer.eat()\n\t\t} else {\n\t\t\t// Hit non-keyword content - stop collecting\n\t\t\tbreak\n\t\t}\n\t\ttoken = lexer.peek()\n\t}\n\n\treturn settings\n}\n\nfunction getTodo(settings: Settings) {\n\tconst todo = settings?.todo\n\tif (Array.isArray(todo)) return todo\n\tif (typeof todo === 'string') return [todo]\n\treturn ['TODO DONE']\n}\n"
  },
  {
    "path": "packages/orga/src/nodes.ts",
    "content": "let i = 0\nexport const nodeIdMap: Record<string, number> = Object.freeze({\n\tdocument: i++,\n\tsection: i++,\n\tfootnote: i++,\n\tblock: i++,\n\tlatex: i++,\n\tdrawer: i++,\n\tplanning: i++,\n\tlist: i++,\n\ttable: i++,\n\t'table.row': i++,\n\t'table.cell': i++,\n\t'list.item': i++,\n\theadline: i++,\n\tparagraph: i++,\n\thtml: i++,\n\tjsx: i++,\n\thr: i++,\n\tnewline: i++,\n\temptyLine: i++,\n\ttext: i++,\n\tlink: i++,\n\t'link.path': i++,\n\topening: i++,\n\tclosing: i++,\n\t'footnote.reference': i++,\n\tstars: i++,\n\ttodo: i++,\n\tpriority: i++,\n\ttags: i++,\n\t'block.begin': i++,\n\t'block.end': i++,\n\t'drawer.begin': i++,\n\t'drawer.end': i++,\n\t'latex.begin': i++,\n\t'latex.end': i++,\n\tcomment: i++,\n\tkeyword: i++,\n\t'footnote.label': i++,\n\t'planning.keyword': i++,\n\t'planning.timestamp': i++,\n\t'list.item.tag': i++,\n\t'list.item.checkbox': i++,\n\t'list.item.bullet': i++,\n\t'table.hr': i++,\n\t'table.columnSeparator': i++\n})\n"
  },
  {
    "path": "packages/orga/src/options.ts",
    "content": "import type { Range } from 'text-kit'\nimport { defaultTodoManager, type TodoManager } from './todo.js'\nimport type { Settings } from './types.js'\n\nexport interface LexerOptions {\n\ttimezone: string\n\trange?: Partial<Range>\n\ttodo: TodoManager\n}\n\nexport interface ParserOptions {\n\tflat: boolean\n\trange?: Partial<Range>\n\tsettings?: Settings\n}\n\nexport interface Options {\n\ttimezone: string\n\trange?: Partial<Range>\n\tsettings?: Settings\n\tflat: boolean\n}\n\nexport const defaultParserOptions: ParserOptions = {\n\tflat: false\n}\n\nexport const defaultLexerOptions: LexerOptions = {\n\ttimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n\ttodo: defaultTodoManager\n}\n\nexport const defaultOptions: Options = {\n\ttimezone: defaultLexerOptions.timezone,\n\tflat: defaultParserOptions.flat\n}\n"
  },
  {
    "path": "packages/orga/src/parse/_parseSymbols.ts",
    "content": "import type { Primitive } from '../types.js'\nimport primitive from './_primitive.js'\n\nexport default (text: string): { [key: string]: Primitive } => {\n\tlet t = text\n\tconst result = {}\n\twhile (t.length > 0) {\n\t\tconst m = t.match(/^:\\w+/)\n\t\tif (!m) break\n\n\t\tconst key = m[0].substring(1)\n\t\tt = t.slice(m[0].length)\n\n\t\tconst end = t.match(/\\s(:\\w+)/)\n\t\tconst index = end ? end.index + 1 : t.length\n\t\tconst value = t.substring(0, index).trim()\n\t\tt = t.slice(index)\n\n\t\tresult[key] = primitive(value)\n\t}\n\n\treturn result\n}\n"
  },
  {
    "path": "packages/orga/src/parse/_primitive.ts",
    "content": "import type { Primitive } from '../types.js'\n\nexport default (value: string): Primitive => {\n\tconst num = Number(value)\n\tif (!Number.isNaN(num)) return num\n\tif (value.toLowerCase() === 'true') return true\n\tif (value.toLowerCase() === 'false') return false\n\treturn value\n}\n"
  },
  {
    "path": "packages/orga/src/parse/_utils.ts",
    "content": "const COMMON_IMAGE_EXTENSIONS = [\n\t'apng',\n\t'avif',\n\t'gif',\n\t'jpeg',\n\t'jpg',\n\t'jfif',\n\t'pjpeg',\n\t'pjp',\n\t'png',\n\t'svg',\n\t'webp',\n\t'bmp',\n\t'ico',\n\t'cur',\n\t'tif',\n\t'tiff'\n]\n\nexport const isImage = (path: string) => {\n\tconst ext = path.toLowerCase().split('.').pop()\n\treturn COMMON_IMAGE_EXTENSIONS.includes(ext)\n}\n"
  },
  {
    "path": "packages/orga/src/parse/block.ts",
    "content": "import type { BlockBegin, BlockEnd } from '../types.js'\nimport type { Action, Handler } from './index.js'\n\nconst block: Action = (begin: BlockBegin, ctx): Handler => {\n\tctx.save()\n\tconst contentStart = begin.position.end\n\tconst blockName = begin.name.toLowerCase()\n\n\tconst block = ctx.enter({\n\t\ttype: 'block',\n\t\tname: begin.name,\n\t\tparams: begin.params,\n\t\tvalue: '',\n\t\tattributes: { ...ctx.attributes },\n\t\tchildren: []\n\t})\n\tctx.lexer.eat()\n\n\t/*\n\t * find the indentation of the block and apply it to\n\t * the rest of the block.\n\t *\n\t * The indentation of the first non-blank line is used as standard.\n\t * The following lines use the lesser one between its own\n\t * indentation and the standard. Leading and trailing blank lines\n\t * are omitted.\n\t */\n\tconst align = (content: string) => {\n\t\tlet indent = -1\n\t\treturn content\n\t\t\t.trimEnd()\n\t\t\t.split('\\n')\n\t\t\t.map((line) => {\n\t\t\t\tconst _indent = line.search(/\\S/)\n\t\t\t\tif (indent === -1) {\n\t\t\t\t\tindent = _indent\n\t\t\t\t}\n\t\t\t\tif (indent === -1) return ''\n\t\t\t\tlet result = line.substring(Math.min(_indent, indent))\n\n\t\t\t\t// remove escaping char ,\n\t\t\t\tif (block.name.toLowerCase() === 'src' && block.params[0] === 'org') {\n\t\t\t\t\tresult = result.replace(/^(\\s*),/, '$1')\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t})\n\t\t\t.join('\\n')\n\t\t\t.trim()\n\t}\n\n\treturn {\n\t\tname: 'block',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'block.end',\n\t\t\t\taction: (token: BlockEnd, context) => {\n\t\t\t\t\tconst lexer = context.lexer\n\t\t\t\t\tif (token.name.toLowerCase() !== blockName) return 'next'\n\t\t\t\t\tblock.value = align(\n\t\t\t\t\t\tlexer.substring({\n\t\t\t\t\t\t\tstart: contentStart,\n\t\t\t\t\t\t\tend: token.position.start\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tlexer.eat()\n\t\t\t\t\tcontext.exit('block')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: ['stars', 'EOF'],\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tcontext.restore()\n\t\t\t\t\tcontext.lexer.modify((t) => ({\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tvalue: context.lexer.substring(t.position),\n\t\t\t\t\t\tposition: t.position\n\t\t\t\t\t}))\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ test: 'newline', action: (_, { discard }) => discard() },\n\t\t\t{ test: /./, action: (_, { consume }) => consume() }\n\t\t]\n\t}\n}\n\nexport default block\n"
  },
  {
    "path": "packages/orga/src/parse/context.ts",
    "content": "import type { Node, Parent, Point } from 'unist'\nimport { nodeIdMap } from '../nodes.js'\nimport type { ParserOptions } from '../options.js'\nimport type { Lexer } from '../tokenize/index.js'\nimport {\n\ttype Attributes,\n\ttype Document,\n\tisSection,\n\ttype Properties\n} from '../types.js'\nimport type { Predicate } from './index.js'\nimport { not, test } from './index.js'\n\n/**\n * Exclude `todo` from settings when initializing document properties.\n * The `todo` setting is only used for TodoManager initialization (for tokenization),\n * not for document properties. Properties.todo should be discovered fresh during parsing.\n */\nfunction initialProperties(settings: Properties | undefined): Properties {\n\tif (!settings) return {}\n\tconst { todo, ...rest } = settings\n\treturn rest\n}\n\ninterface Snapshot {\n\tstack: Parent[]\n\tsavePoint: number\n\tlevel: number\n\tattributes: Attributes\n}\n\nexport interface Context {\n\t// control\n\t// -\n\tenter: <N extends Parent>(node: N) => N\n\texit: (predicate: Predicate, strict?: boolean) => Parent | void\n\tattach: (node: Node) => void\n\tsave: () => void\n\trestore: () => void\n\taddProp: (key: string, value: string) => void\n\n\t// syntactic sugar\n\t// -\n\texitTo: (predicate: Predicate) => void\n\texitAll: (predicate: Predicate) => void\n\t/** shorthand for lexer.eat and push it **/\n\tconsume: () => void\n\t/** shorthand for lexer.eat **/\n\tdiscard: () => void\n\twithin: (predicate: Predicate) => boolean\n\n\t// state\n\tattributes: Attributes\n\treadonly parent: Parent\n\treadonly level: number\n\treadonly tree: Document\n\treadonly lexer: Lexer\n\treadonly state: string\n\treadonly options: ParserOptions\n}\n\nfunction point(d: Point): Point {\n\treturn { ...d }\n}\n\nexport function createContext(lexer: Lexer, options: ParserOptions): Context {\n\tlet stack: Parent[] = []\n\tlet snapshot: Snapshot | undefined\n\n\tfunction enter<N extends Parent>(node: N): N {\n\t\tconst start = lexer.peek()?.position?.start ||\n\t\t\tlexer.peek(-1)?.position?.end || { line: 1, column: 1, offset: 0 }\n\n\t\t// @ts-expect-error will add the end later\n\t\tnode.position = { start: point(start) }\n\t\tstack.push(node)\n\t\treturn node\n\t}\n\n\tconst tree = enter({\n\t\ttype: 'document',\n\t\tproperties: initialProperties(options.settings),\n\t\tchildren: []\n\t}) as Document\n\n\tconst pop = () => {\n\t\tconst node = stack.pop()\n\n\t\tconst end = lexer.peek()?.position?.start ||\n\t\t\tlexer.peek(-1)?.position?.end || { line: 1, column: 1, offset: 0 }\n\t\tnode.position.end = point(end)\n\n\t\tif (!node) {\n\t\t\tthrow new Error('unexpected empty stack')\n\t\t}\n\t\t// attach to tree\n\t\tif (stack.length > 0) {\n\t\t\tattach(node)\n\t\t}\n\t\treturn node\n\t}\n\n\tfunction exit(predicate: Predicate, strict = true) {\n\t\tif (stack.length === 0) return // never exit the root\n\t\tconst last = stack[stack.length - 1]\n\t\tif (test(last, predicate)) {\n\t\t\treturn pop()\n\t\t}\n\t\tif (strict) {\n\t\t\tthrow new Error(\n\t\t\t\t`\ncan not strictly exit ${predicate},\nactual: ${last.type}\nlocation: line: ${last.position.start.line}, column: ${last.position.start.column}\n`.trim()\n\t\t\t)\n\t\t}\n\t}\n\n\tfunction exitTo(predicate: Predicate) {\n\t\texitAll(not(predicate))\n\t}\n\n\tfunction exitAll(predicate: Predicate) {\n\t\tif (exit(predicate, false)) {\n\t\t\texitAll(predicate)\n\t\t}\n\t}\n\n\tfunction getLevel(): number {\n\t\tlet index = stack.length - 1\n\t\twhile (index > 0) {\n\t\t\tconst node = stack[index]\n\t\t\tif (isSection(node)) {\n\t\t\t\treturn node.level\n\t\t\t}\n\t\t\tindex -= 1\n\t\t}\n\t\treturn 0\n\t}\n\n\t/**\n\t * attach a node to the current tree, adding data.hash\n\t */\n\tfunction attach(node: Node) {\n\t\tif (!node) return\n\t\tif (stack.length === 0) {\n\t\t\tthrow new Error('unexpected empty stack')\n\t\t}\n\t\tconst parent = stack[stack.length - 1]\n\t\tnode.data = { hash: hash(node.type) }\n\t\tparent.children.push(node)\n\t}\n\n\treturn {\n\t\toptions,\n\t\tattributes: {},\n\t\tenter,\n\t\texit,\n\t\texitAll,\n\t\texitTo,\n\t\tattach,\n\t\taddProp: function (key, value) {\n\t\t\tconst k = key.toLowerCase().trim()\n\t\t\tconst v = value.trim()\n\t\t\tconst existing = tree.properties[k]\n\t\t\tif (existing) {\n\t\t\t\tif (Array.isArray(existing)) {\n\t\t\t\t\texisting.push(v)\n\t\t\t\t}\n\t\t\t\tif (typeof existing === 'string') {\n\t\t\t\t\ttree.properties[k] = [existing, v]\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\ttree.properties[k] = v\n\t\t\t}\n\t\t},\n\n\t\tconsume: function () {\n\t\t\tattach(lexer.eat())\n\t\t},\n\t\tdiscard: function () {\n\t\t\tlexer.eat()\n\t\t},\n\t\twithin: function (predicate: Predicate) {\n\t\t\treturn test(this.parent, predicate)\n\t\t},\n\n\t\tsave: function () {\n\t\t\tconst level = this.level\n\t\t\tconst attributes = this.attributes\n\t\t\tsnapshot = {\n\t\t\t\tstack: [...stack],\n\t\t\t\tlevel,\n\t\t\t\tattributes: { ...attributes },\n\t\t\t\tsavePoint: lexer.save()\n\t\t\t}\n\t\t},\n\n\t\trestore: function () {\n\t\t\tif (snapshot === undefined) return\n\t\t\tthis.attributes = { ...snapshot.attributes }\n\t\t\tstack = [...snapshot.stack]\n\t\t\tlexer.restore(snapshot.savePoint)\n\t\t},\n\n\t\tget parent() {\n\t\t\treturn stack[stack.length - 1]\n\t\t},\n\n\t\tget tree() {\n\t\t\treturn tree\n\t\t},\n\n\t\tget lexer() {\n\t\t\treturn lexer\n\t\t},\n\n\t\tget level() {\n\t\t\treturn getLevel()\n\t\t},\n\n\t\tget state() {\n\t\t\tconst token = lexer.peek()\n\t\t\tconst lines = [`lexer: ${lexer.save()}`]\n\t\t\tlines.push(`token: ${token ? token.type : 'EOF'}`)\n\t\t\tif (token) {\n\t\t\t\tlines.push(`content: ${lexer.substring(token.position)}`)\n\t\t\t}\n\t\t\tlines.push(`stack:   ${stack.map((n) => n.type).join(' > ')}`)\n\t\t\treturn lines.join('\\n')\n\t\t}\n\t}\n\n\tfunction hash(type: string, value = 0) {\n\t\tconst typeHash = nodeIdMap[type]\n\t\tlet baseHash = 0\n\t\tif (stack.length > 0) {\n\t\t\tbaseHash = stack[stack.length - 1].data?.hash ?? 0\n\t\t}\n\t\treturn (baseHash + (baseHash << 8) + typeHash + (value << 4)) | 0\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/parse/drawer.ts",
    "content": "import type { DrawerBegin, Section } from '../types.js'\nimport type { Action } from './index.js'\n\nconst drawer: Action = (begin: DrawerBegin, context) => {\n\tcontext.save()\n\tconst drawer = context.enter({\n\t\ttype: 'drawer',\n\t\tname: begin.name,\n\t\tvalue: '',\n\t\tchildren: []\n\t})\n\tcontext.consume()\n\n\tconst contentStart = begin.position.end\n\n\treturn {\n\t\tname: 'drawer',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: ['stars', 'EOF'],\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tcontext.restore()\n\t\t\t\t\tcontext.lexer.modify((t) => ({\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tvalue: context.lexer.substring(t.position),\n\t\t\t\t\t\tposition: t.position\n\t\t\t\t\t}))\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'drawer.end',\n\t\t\t\taction: (token, context) => {\n\t\t\t\t\tcontext.consume()\n\t\t\t\t\tdrawer.value = context.lexer.substring({\n\t\t\t\t\t\tstart: contentStart,\n\t\t\t\t\t\tend: token.position.start\n\t\t\t\t\t})\n\n\t\t\t\t\tcontext.exit('drawer')\n\t\t\t\t\tcontext.lexer.eat('newline')\n\n\t\t\t\t\tif (drawer.name.toLowerCase() === 'properties') {\n\t\t\t\t\t\tconst section = context.parent as Section\n\t\t\t\t\t\tsection.properties = drawer.value\n\t\t\t\t\t\t\t.split('\\n')\n\t\t\t\t\t\t\t.reduce((accu, current) => {\n\t\t\t\t\t\t\t\tconst m = current.match(/\\s*:(.+?):\\s*(.+)\\s*$/)\n\t\t\t\t\t\t\t\tif (m) {\n\t\t\t\t\t\t\t\t\treturn { ...accu, [m[1].toLowerCase()]: m[2] }\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn accu\n\t\t\t\t\t\t\t}, section.properties)\n\t\t\t\t\t}\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, { consume }) => consume()\n\t\t\t}\n\t\t]\n\t}\n}\n\nexport default drawer\n"
  },
  {
    "path": "packages/orga/src/parse/footnote.ts",
    "content": "import type { FootnoteLabel } from '../types.js'\nimport type { Action } from './index.js'\n\nconst Footnote: Action = (token: FootnoteLabel, { enter, exitTo, consume }) => {\n\texitTo('document')\n\tenter({\n\t\ttype: 'footnote',\n\t\tlabel: token.label,\n\t\tchildren: []\n\t})\n\tconsume()\n}\n\nexport default Footnote\n"
  },
  {
    "path": "packages/orga/src/parse/headline.ts",
    "content": "import type { Headline, Priority, Stars, Tags, Todo } from '../types.js'\nimport { isPhrasingContent } from '../utils.js'\nimport type { Action } from './index.js'\nimport phrasingContent from './phrasing.js'\n\nconst headline: Action = (token: Stars, context) => {\n\tconst { enter } = context\n\n\tconst headline: Headline = enter({\n\t\ttype: 'headline',\n\t\tactionable: false,\n\t\tchildren: [],\n\t\tlevel: token.level || context.level\n\t})\n\n\treturn {\n\t\tname: 'headline',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: ['newline', 'EOF'],\n\t\t\t\taction: (_, { exit, discard }) => {\n\t\t\t\t\tdiscard()\n\t\t\t\t\texit(headline.type)\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'todo',\n\t\t\t\taction: (token: Todo) => {\n\t\t\t\t\theadline.keyword = token.keyword\n\t\t\t\t\theadline.actionable = token.actionable\n\t\t\t\t\treturn 'next'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'tags',\n\t\t\t\taction: (token: Tags) => {\n\t\t\t\t\theadline.tags = token.tags\n\t\t\t\t\treturn 'next'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'priority',\n\t\t\t\taction: (token: Priority) => {\n\t\t\t\t\theadline.priority = token.value\n\t\t\t\t\treturn 'next'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: isPhrasingContent,\n\t\t\t\taction: phrasingContent\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, { attach, lexer }) => {\n\t\t\t\t\tattach(lexer.eat())\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nexport default headline\n"
  },
  {
    "path": "packages/orga/src/parse/index.ts",
    "content": "import type { Node } from 'unist'\nimport type { ParserOptions } from '../options.js'\nimport type { Lexer } from '../tokenize/index.js'\nimport type { Document, Parent, Settings, Token } from '../types.js'\nimport { isPhrasingContent } from '../utils.js'\nimport block from './block.js'\nimport { type Context, createContext } from './context.js'\nimport footnote from './footnote.js'\nimport keyword from './keyword.js'\nimport latex from './latex.js'\nimport list from './list.js'\nimport paragraph from './paragraph.js'\nimport section from './section.js'\nimport table from './table.js'\n\nexport type Parse = (lexer: Lexer) => Parent | undefined\n\n/*\n * break: pop handler stack, go to next handler\n * next: go to next rule in the current handler\n * finish | void: finish current handler, skip the upcoming rules\n */\ntype FlowControl = 'break' | 'next' | 'finish'\n\nexport type Action = (\n\ttoken: Token,\n\tcontext: Context\n) => FlowControl | Handler | void\n\nexport type Predicate = string | 'EOF' | RegExp | ((token: Node) => boolean)\n\nexport function test(node: Node, predicate: Predicate) {\n\treturn toFunc(predicate)(node)\n}\n\nexport function not(test: Predicate): Predicate {\n\treturn (token) => !toFunc(test)(token)\n}\n\nexport function toFunc(test: Predicate): (token: Node) => boolean {\n\tif (typeof test === 'function') {\n\t\treturn (token) => token && test(token)\n\t}\n\tif (test === 'EOF') {\n\t\treturn (token) => {\n\t\t\treturn token === undefined\n\t\t}\n\t}\n\tif (typeof test === 'string') {\n\t\treturn (token) => token && test === token.type\n\t}\n\treturn (token) => token && test.test(token.type)\n}\n\ntype Rule = { test: Predicate | Predicate[]; action: Action | Handler }\n\nexport interface Handler {\n\tname: string\n\trules: Rule[]\n\teof?: (context: Context) => void\n}\n\nconst main: Handler = {\n\tname: 'main',\n\trules: [\n\t\t{\n\t\t\ttest: 'emptyLine',\n\t\t\taction: function (_, context) {\n\t\t\t\tconst { consume, exit } = context\n\t\t\t\tcontext.attributes = {}\n\t\t\t\texit('footnote', false)\n\t\t\t\tconsume()\n\t\t\t}\n\t\t},\n\t\t{ test: 'newline', action: (_, { discard }) => discard() },\n\t\t{ test: 'stars', action: section },\n\t\t{ test: 'keyword', action: keyword },\n\t\t{ test: 'list.item.bullet', action: list },\n\t\t{ test: 'block.begin', action: block },\n\t\t{ test: 'latex.begin', action: latex },\n\t\t{ test: /^table\\./, action: table },\n\t\t{\n\t\t\ttest: 'hr',\n\t\t\taction: (token, { lexer, attach }) => {\n\t\t\t\tlexer.eat()\n\t\t\t\tattach(token)\n\t\t\t}\n\t\t},\n\t\t{ test: isPhrasingContent, action: paragraph },\n\t\t{ test: 'footnote.label', action: footnote },\n\t\t// catch all\n\t\t{\n\t\t\ttest: /.*/,\n\t\t\taction: (_, { lexer }) => {\n\t\t\t\tlexer.eat()\n\t\t\t}\n\t\t},\n\t\t{ test: 'EOF', action: () => 'break' }\n\t]\n}\n\nexport interface Parser {\n\tadvance: () => Document | number\n\tparse: () => Document\n\tfinish: () => Document\n\treadonly settings?: Settings\n}\n\nexport function parser(lexer: Lexer, options: ParserOptions): Parser {\n\tconst context = createContext(lexer, options)\n\tconst end = lexer.toOffset(options.range?.end || Infinity)\n\tconst handlerStack: Handler[] = [main]\n\tlet lexerLocation = lexer.save()\n\tlet maxStaleIterations = 10\n\n\treturn {\n\t\tadvance,\n\t\tparse() {\n\t\t\tfor (;;) {\n\t\t\t\tconst tree = advance()\n\t\t\t\tif (typeof tree === 'number') continue\n\t\t\t\treturn tree\n\t\t\t}\n\t\t},\n\t\tfinish,\n\t\tget settings() {\n\t\t\treturn context.tree.properties\n\t\t}\n\t}\n\n\tfunction handler() {\n\t\treturn handlerStack.length > 0\n\t\t\t? handlerStack[handlerStack.length - 1]\n\t\t\t: undefined\n\t}\n\n\tfunction advance() {\n\t\tif (!handler() && lexer.now >= end) {\n\t\t\treturn finish()\n\t\t}\n\n\t\t// prevent infinit loop\n\t\tif (maxStaleIterations === 0) {\n\t\t\tthrow new Error(`it's stuck. \\n${context.state}`)\n\t\t}\n\n\t\tlet nothingMatches = true\n\n\t\tfor (const { test: _test, action } of handler().rules) {\n\t\t\tconst token = lexer.peek()\n\t\t\tconst predicates = Array.isArray(_test) ? _test : [_test]\n\t\t\tif (!predicates.some((p) => test(token, p))) continue\n\t\t\tnothingMatches = false\n\n\t\t\tif (typeof action !== 'function') {\n\t\t\t\thandlerStack.push(action)\n\t\t\t\treturn advance()\n\t\t\t}\n\n\t\t\tconst control = action(token, context)\n\n\t\t\tif (typeof control === 'object') {\n\t\t\t\thandlerStack.push(control)\n\t\t\t\treturn advance()\n\t\t\t}\n\n\t\t\tif (control === 'break') {\n\t\t\t\thandlerStack.pop()\n\t\t\t\t// if (handlerStack.length === 0) {\n\t\t\t\t//   throw new Error('can not pop the root handler')\n\t\t\t\t// }\n\n\t\t\t\t// return the offset if the block is finished\n\t\t\t\tif (lexer.peek() && context.parent.type === 'document') {\n\t\t\t\t\treturn lexer.peek().position.start.offset\n\t\t\t\t}\n\t\t\t\treturn advance()\n\t\t\t}\n\t\t\tif (control === 'next') {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tbreak\n\t\t}\n\n\t\tif (nothingMatches) {\n\t\t\thandlerStack.pop()\n\t\t\treturn advance()\n\t\t}\n\n\t\tif (lexer.save() === lexerLocation) {\n\t\t\tmaxStaleIterations -= 1\n\t\t} else {\n\t\t\tlexerLocation = lexer.save()\n\t\t\tmaxStaleIterations = 10\n\t\t}\n\n\t\treturn advance()\n\t}\n\n\tfunction finish() {\n\t\tcontext.exitTo('document')\n\t\tcontext.exit('document')\n\t\t// algin the end position\n\t\tcontext.tree.position.end = lexer.toPoint(lexer.now)\n\t\treturn context.tree\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/parse/keyword.ts",
    "content": "import type { HTML, JSX, Keyword, Primitive } from '../types.js'\nimport parseSymbols from './_parseSymbols.js'\nimport _primitive from './_primitive.js'\nimport type { Action } from './index.js'\n\nconst AFFILIATED_KEYWORDS = ['caption', 'header', 'name', 'plot', 'results']\n\nconst keyword: Action = (token: Keyword, context) => {\n\tconst { attach, lexer, addProp } = context\n\tconst key = token.key.toLowerCase()\n\tconst { value } = token\n\n\tif (key === 'html') {\n\t\tattach({ type: 'html', value, position: token.position } as HTML)\n\t} else if (key === 'jsx') {\n\t\tattach({ type: 'jsx', value, position: token.position } as JSX)\n\t} else {\n\t\tif (AFFILIATED_KEYWORDS.includes(key)) {\n\t\t\tcontext.attributes[key] = _primitive(value)\n\t\t} else if (key.startsWith('attr_')) {\n\t\t\tcontext.attributes[key] = {\n\t\t\t\t...(context.attributes[key] as { [key: string]: Primitive }),\n\t\t\t\t...parseSymbols(value)\n\t\t\t}\n\t\t} else {\n\t\t\taddProp(key, value)\n\t\t}\n\t\tif (key === 'todo') {\n\t\t\tlexer.todo.add(value)\n\t\t}\n\t\tattach(token)\n\t}\n\n\t// if (AFFILIATED_KEYWORDS.includes(key)) {\n\t//   context.attributes[key] = _primitive(value)\n\t// } else if (key.startsWith('attr_')) {\n\t//   context.attributes[key] = {\n\t//     ...(context.attributes[key] as { [key: string]: Primitive }),\n\t//     ...parseSymbols(value),\n\t//   }\n\t// } else if (key === 'todo') {\n\t//   lexer.addInBufferTodoKeywords(value)\n\t// } else if (key === 'html') {\n\t//   push({ type: 'html', value } as HTML)\n\t// } else if (key === 'jsx') {\n\t//   push({ type: 'jsx', value } as JSX)\n\t// } else {\n\t//   addProp(key, value)\n\t// }\n\n\tlexer.eat()\n}\n\nexport default keyword\n\n// export default (context: Context) => {\n//   const { push, lexer } = context\n//   const token = lexer.peek()\n//   if (token.type !== 'keyword') return\n\n//   lexer.eat()\n// }\n"
  },
  {
    "path": "packages/orga/src/parse/latex.ts",
    "content": "import type { LatexBegin, LatexEnd } from '../types.js'\nimport type { Action, Handler } from './index.js'\n\nconst latex: Action = (begin: LatexBegin, context): Handler => {\n\tcontext.save()\n\tconst contentStart = begin.position.start\n\tconst envName = begin.name.toLowerCase()\n\n\tconst latexBlock = context.enter({\n\t\ttype: 'latex',\n\t\tname: begin.name,\n\t\tvalue: '',\n\t\tchildren: []\n\t})\n\tcontext.attach(context.lexer.eat())\n\n\t/*\n\t * find the indentation of the block and apply it to\n\t * the rest of the block.\n\t *\n\t * The indentation of the first non-blank line is used as standard.\n\t * The following lines use the lesser one between its own\n\t * indentation and the standard. Leading and trailing blank lines\n\t * are omitted.\n\t */\n\tconst align = (content: string) => {\n\t\tlet indent = -1\n\t\treturn content\n\t\t\t.trimEnd()\n\t\t\t.split('\\n')\n\t\t\t.map((line) => {\n\t\t\t\tconst _indent = line.search(/\\S/)\n\t\t\t\tif (indent === -1) {\n\t\t\t\t\tindent = _indent\n\t\t\t\t}\n\t\t\t\tif (indent === -1) return ''\n\t\t\t\tconst result = line.substring(Math.min(_indent, indent))\n\t\t\t\treturn result\n\t\t\t})\n\t\t\t.join('\\n')\n\t\t\t.trim()\n\t}\n\n\treturn {\n\t\tname: 'latex',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'latex.end',\n\t\t\t\taction: (token: LatexEnd, context) => {\n\t\t\t\t\tif (token.name.toLowerCase() !== envName) return 'next'\n\t\t\t\t\tlatexBlock.value = align(\n\t\t\t\t\t\tcontext.lexer.substring({\n\t\t\t\t\t\t\tstart: contentStart,\n\t\t\t\t\t\t\tend: token.position.end\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t\tcontext.attach(context.lexer.eat())\n\t\t\t\t\tcontext.lexer.eat('newline')\n\t\t\t\t\tcontext.exit('latex')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: ['stars', 'EOF'],\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tcontext.restore()\n\t\t\t\t\tcontext.lexer.modify((t) => ({\n\t\t\t\t\t\ttype: 'text',\n\t\t\t\t\t\tvalue: context.lexer.substring(t.position),\n\t\t\t\t\t\tposition: t.position\n\t\t\t\t\t}))\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ test: /./, action: (_, context) => context.attach(context.lexer.eat()) }\n\t\t]\n\t}\n}\n\nexport default latex\n"
  },
  {
    "path": "packages/orga/src/parse/list.ts",
    "content": "import type { ListItem, ListItemBullet, ListItemTag } from '../types.js'\nimport { isPhrasingContent } from '../utils.js'\nimport type { Action, Handler } from './index.js'\nimport phrasingContent from './phrasing.js'\n\nconst listItem: Action = (token: ListItemBullet, { enter, consume }) => {\n\tconst item: ListItem = enter({\n\t\ttype: 'list.item',\n\t\tindent: token.indent,\n\t\tchildren: []\n\t})\n\tconsume()\n\n\treturn {\n\t\tname: 'list item',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'emptyLine',\n\t\t\t\taction: (_, { exit, consume }) => {\n\t\t\t\t\tconsume()\n\t\t\t\t\texit(item.type)\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ test: 'newline', action: (_, { consume }) => consume() },\n\t\t\t{\n\t\t\t\ttest: 'list.item.tag',\n\t\t\t\taction: (token: ListItemTag, { consume }) => {\n\t\t\t\t\titem.tag = token.value\n\t\t\t\t\tconsume()\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'list.item.checkbox',\n\t\t\t\taction: (_, { consume }) => {\n\t\t\t\t\tconsume()\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ test: isPhrasingContent, action: phrasingContent },\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, { exit }) => {\n\t\t\t\t\texit('list.item')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nconst list: Action = (token: ListItemBullet, context) => {\n\tcontext.enter({\n\t\ttype: 'list',\n\t\tindent: token.indent,\n\t\tordered: token.ordered,\n\t\tchildren: [],\n\t\tattributes: context.attributes\n\t})\n\tcontext.attributes = {}\n\n\tconst indent = token.indent\n\n\tconst handler: Handler = {\n\t\tname: 'list',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'stars',\n\t\t\t\taction: (_, { exit }) => {\n\t\t\t\t\texit('list')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: ['emptyLine', 'newline'],\n\t\t\t\taction: (_, { exit, consume }) => {\n\t\t\t\t\tconsume()\n\t\t\t\t\texit('list')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'list.item.bullet',\n\t\t\t\taction: (token: ListItemBullet, context) => {\n\t\t\t\t\tconst { exit } = context\n\n\t\t\t\t\tif (indent > token.indent) {\n\t\t\t\t\t\texit('list')\n\t\t\t\t\t\treturn 'break'\n\t\t\t\t\t} else if (indent === token.indent) {\n\t\t\t\t\t\treturn listItem(token, context)\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn list(token, context)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, { exit }) => {\n\t\t\t\t\texit('list')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n\n\treturn handler\n}\n\nexport default list\n"
  },
  {
    "path": "packages/orga/src/parse/paragraph.ts",
    "content": "import { isParagraph, type Opening, type PhrasingContent } from '../types.js'\nimport { clone, isPhrasingContent } from '../utils.js'\nimport { isImage } from './_utils.js'\nimport type { Context } from './context.js'\nimport type { Action } from './index.js'\nimport phrasingContent from './phrasing.js'\n\nconst isWhitespaces = (node: PhrasingContent) => {\n\treturn (\n\t\t(node.type === 'text' && node.value.trim().length === 0) ||\n\t\tnode.type === 'newline' ||\n\t\tnode.type === 'emptyLine'\n\t)\n}\n\nconst paragraph: Action = () => {\n\tconst makeSureParagraph = (context: Context) => {\n\t\tconst parent = context.parent\n\t\tif (parent.type === 'paragraph') return\n\t\tcontext.save()\n\t\tcontext.enter({\n\t\t\ttype: 'paragraph',\n\t\t\tchildren: [],\n\t\t\tattributes: clone(context.attributes)\n\t\t})\n\t\tcontext.attributes = {}\n\t}\n\n\tconst exitPragraph = (context: Context) => {\n\t\tconst paragraph = context.parent\n\t\tif (!isParagraph(paragraph)) return\n\t\tif (\n\t\t\tparagraph.children.length === 0 ||\n\t\t\tparagraph.children.every(isWhitespaces)\n\t\t) {\n\t\t\tcontext.restore()\n\t\t} else {\n\t\t\t// TODO: should we do this?\n\t\t\t// exitTo('paragraph')\n\t\t\tcontext.exit('paragraph')\n\t\t}\n\t}\n\n\treturn {\n\t\tname: 'paragraph',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'emptyLine',\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tcontext.consume()\n\t\t\t\t\texitPragraph(context)\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'newline',\n\t\t\t\taction: (_, { consume }) => consume()\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'opening',\n\t\t\t\taction: (token: Opening, context) => {\n\t\t\t\t\tif (token.element === 'link') {\n\t\t\t\t\t\tconst next = context.lexer.peek(1)\n\t\t\t\t\t\tif (next.type === 'link.path' && isImage(next.value)) {\n\t\t\t\t\t\t\texitPragraph(context)\n\t\t\t\t\t\t\treturn phrasingContent\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tmakeSureParagraph(context)\n\t\t\t\t\treturn phrasingContent\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: isPhrasingContent,\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tmakeSureParagraph(context)\n\t\t\t\t\treturn phrasingContent\n\t\t\t\t}\n\t\t\t},\n\t\t\t// catch all\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\texitPragraph(context)\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nexport default paragraph\n"
  },
  {
    "path": "packages/orga/src/parse/phrasing.ts",
    "content": "import {\n\ttype Closing,\n\ttype FootnoteLabel,\n\tisFootnoteReference,\n\tisLink,\n\ttype LinkPath,\n\ttype Opening\n} from '../types.js'\nimport type { Handler } from './index.js'\n\nconst phrasingContent: Handler = {\n\tname: 'inline',\n\trules: [\n\t\t{\n\t\t\ttest: 'opening',\n\t\t\taction: (token: Opening, { enter, consume }) => {\n\t\t\t\tenter({\n\t\t\t\t\ttype: token.element,\n\t\t\t\t\tchildren: []\n\t\t\t\t})\n\t\t\t\tconsume()\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: 'closing',\n\t\t\taction: (token: Closing, { exit, consume }) => {\n\t\t\t\tconsume()\n\t\t\t\texit(token.element)\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: 'link.path',\n\t\t\taction: (token: LinkPath, context) => {\n\t\t\t\tconst { parent, consume, attributes } = context\n\t\t\t\tif (!isLink(parent)) {\n\t\t\t\t\tthrow new Error('expect parent to be link')\n\t\t\t\t}\n\t\t\t\tparent.path = {\n\t\t\t\t\tprotocol: token.protocol,\n\t\t\t\t\tvalue: token.value,\n\t\t\t\t\tsearch: token.search\n\t\t\t\t}\n\t\t\t\tparent.attributes = attributes\n\t\t\t\tcontext.attributes = {}\n\t\t\t\tconsume()\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: 'footnote.label',\n\t\t\taction: (token: FootnoteLabel, { parent, consume }) => {\n\t\t\t\tif (!isFootnoteReference(parent)) {\n\t\t\t\t\tthrow new Error('expect parent to be footnote reference')\n\t\t\t\t}\n\t\t\t\tparent.label = token.label\n\t\t\t\tconsume()\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: 'text',\n\t\t\taction: (_, { consume }) => {\n\t\t\t\tconsume()\n\t\t\t}\n\t\t}\n\t]\n}\n\nexport default phrasingContent\n"
  },
  {
    "path": "packages/orga/src/parse/planning.ts",
    "content": "import type { PlanningKeyword } from '../types.js'\nimport drawer from './drawer.js'\nimport type { Handler } from './index.js'\n\nconst planning: Handler = {\n\tname: 'planning',\n\trules: [\n\t\t{\n\t\t\ttest: 'planning.keyword',\n\t\t\taction: (keyword: PlanningKeyword, context) => {\n\t\t\t\tconst { lexer, enter, attach, exit } = context\n\t\t\t\tconst { eat, eatAll, peek } = lexer\n\t\t\t\tconst timestamp = peek(1)\n\t\t\t\tif (!timestamp || timestamp.type !== 'planning.timestamp') {\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t\tenter({\n\t\t\t\t\ttype: 'planning',\n\t\t\t\t\tkeyword: keyword.value,\n\t\t\t\t\ttimestamp: timestamp.value,\n\t\t\t\t\tchildren: []\n\t\t\t\t})\n\n\t\t\t\tattach(eat()) // keyword\n\t\t\t\tattach(eat()) // timestamp\n\t\t\t\texit('planning')\n\n\t\t\t\tif (eatAll('newline') > 1) {\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: 'drawer.begin',\n\t\t\taction: (token, context) => {\n\t\t\t\treturn drawer(token, context)\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\ttest: /.*/,\n\t\t\taction: () => {\n\t\t\t\treturn 'break'\n\t\t\t}\n\t\t}\n\t]\n}\n\nexport default planning\n"
  },
  {
    "path": "packages/orga/src/parse/section.ts",
    "content": "import type { Stars } from '../types.js'\nimport drawer from './drawer.js'\nimport headline from './headline.js'\nimport type { Action } from './index.js'\nimport planning from './planning.js'\n\nconst section: Action = (token: Stars, context) => {\n\tconst {\n\t\tenter,\n\t\texit,\n\t\texitTo,\n\t\toptions: { flat }\n\t} = context\n\n\t// stars break footnote\n\texit('footnote', false)\n\n\tif (!flat) {\n\t\tconst level = token.level\n\n\t\tif (level <= context.level) {\n\t\t\texitTo('section')\n\t\t\texit('section')\n\t\t\treturn\n\t\t}\n\n\t\tenter({\n\t\t\ttype: 'section',\n\t\t\tlevel: level,\n\t\t\tproperties: {},\n\t\t\tchildren: []\n\t\t})\n\t}\n\n\tlet headlineProcessed = false\n\n\treturn {\n\t\tname: 'section',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'stars',\n\t\t\t\taction: (token: Stars, context) => {\n\t\t\t\t\tif (headlineProcessed) return 'break'\n\t\t\t\t\theadlineProcessed = true\n\t\t\t\t\treturn headline(token, context)\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'planning.keyword',\n\t\t\t\taction: planning\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: 'drawer.begin',\n\t\t\t\taction: drawer\n\t\t\t}\n\t\t]\n\t}\n}\n\nexport default section\n"
  },
  {
    "path": "packages/orga/src/parse/table.ts",
    "content": "import { isPhrasingContent } from '../utils.js'\nimport type { Action } from './index.js'\nimport phrasingContent from './phrasing.js'\n\nconst tableCell: Action = (_, { enter }) => {\n\tenter({\n\t\ttype: 'table.cell',\n\t\tchildren: []\n\t})\n\n\treturn {\n\t\tname: 'table cell',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: ['newline', 'table.columnSeparator'],\n\t\t\t\taction: (_, { exit }) => {\n\t\t\t\t\texit('table.cell')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: isPhrasingContent,\n\t\t\t\taction: phrasingContent\n\t\t\t},\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, { exit }) => {\n\t\t\t\t\texit('table.cell')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nconst tableRow: Action = (_, { enter, lexer }) => {\n\tenter({\n\t\ttype: 'table.row',\n\t\tchildren: []\n\t})\n\n\t// consume()\n\tlexer.eat()\n\n\treturn {\n\t\tname: 'table row',\n\t\trules: [\n\t\t\t{\n\t\t\t\ttest: 'newline',\n\t\t\t\taction: (_, { exit, discard }) => {\n\t\t\t\t\tdiscard()\n\t\t\t\t\texit('table.row')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ test: 'table.columnSeparator', action: (_, { consume }) => consume() },\n\t\t\t{ test: isPhrasingContent, action: tableCell }\n\t\t]\n\t}\n}\n\nconst table: Action = (_, context) => {\n\tcontext.enter({\n\t\ttype: 'table',\n\t\tchildren: [],\n\t\tattributes: {}\n\t})\n\n\treturn {\n\t\tname: 'table',\n\t\trules: [\n\t\t\t{ test: 'table.columnSeparator', action: tableRow },\n\t\t\t{ test: 'table.hr', action: (_, context) => context.consume() },\n\t\t\t{ test: 'newline', action: (_, context) => context.discard() },\n\t\t\t{\n\t\t\t\ttest: /.*/,\n\t\t\t\taction: (_, context) => {\n\t\t\t\t\tcontext.exitTo('table')\n\t\t\t\t\tcontext.exit('table')\n\t\t\t\t\treturn 'break'\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n\nexport default table\n"
  },
  {
    "path": "packages/orga/src/position.ts",
    "content": "import type { Point, Position } from 'unist'\n\nexport const isEqual = (p1: Point, p2: Point) => {\n\treturn p1.line === p2.line && p1.column === p2.column\n}\n\nexport const isGreaterOrEqual = (p1: Point, p2: Point) => {\n\treturn isEqual(p1, p2) || before(p1)(p2)\n}\n\nconst compare = (p1: Point, p2: Point): boolean => {\n\tif (p1.line > p2.line) return true\n\tif (p1.line === p2.line && p1.column > p2.column) return true\n\treturn false\n}\n\nexport const after = (p1: Point) => (p2: Point) => {\n\treturn compare(p2, p1)\n}\n\nexport const before = (p1: Point) => (p2: Point) => {\n\treturn compare(p1, p2)\n}\n\nexport const isEmpty = (position: Position) => {\n\treturn !position || isEqual(position.start, position.end)\n}\n"
  },
  {
    "path": "packages/orga/src/timestamp.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { parse } from './timestamp'\n\nconst p = (text: string) => {\n\treturn parse(text, { timezone: 'Pacific/Auckland' })\n}\n\ndescribe('timestamp', () => {\n\tit('can parse timestamps', () => {\n\t\tassert.deepEqual(p('[2021-04-24 Sat]'), {\n\t\t\tdate: new Date('2021-04-23T12:00:00.000Z'),\n\t\t\tend: undefined\n\t\t})\n\t\tassert.deepEqual(p('<2021-04-24 Sat>'), {\n\t\t\tdate: new Date('2021-04-23T12:00:00.000Z'),\n\t\t\tend: undefined\n\t\t})\n\t\tassert.deepEqual(p('<2021-04-24 Sat 19:15>'), {\n\t\t\tdate: new Date('2021-04-24T07:15:00.000Z'),\n\t\t\tend: undefined\n\t\t})\n\t\tassert.deepEqual(p('<2021-04-24 Sat 19:15-22:00>'), {\n\t\t\tdate: new Date('2021-04-24T07:15:00.000Z'),\n\t\t\tend: new Date('2021-04-24T10:00:00.000Z')\n\t\t})\n\t\tassert.deepEqual(p('<2019-08-19 Mon>--<2019-08-20 Tue>'), {\n\t\t\tdate: new Date('2019-08-18T12:00:00.000Z'),\n\t\t\tend: new Date('2019-08-19T12:00:00.000Z')\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/timestamp.ts",
    "content": "import { zonedTimeToUtc } from 'date-fns-tz'\nimport { read } from 'text-kit'\nimport type { Timestamp } from './types.js'\n\nexport const parse = (\n\tinput: string,\n\t{ timezone = Intl.DateTimeFormat().resolvedOptions().timeZone } = {}\n): Timestamp | undefined => {\n\tconst { match, eat, getChar, jump } = read(input)\n\n\teat('whitespaces')\n\tconst timestamp = () => {\n\t\t// opening\n\t\tconst opening = eat(/[<[]/g)\n\t\tif (!opening) return\n\t\tconst _active = opening.value === '<'\n\n\t\t// date\n\t\tconst { value: _date } = eat(/\\d{4}-\\d{2}-\\d{2}/)\n\t\tlet date = _date\n\n\t\teat('whitespaces')\n\n\t\tlet end: string | undefined\n\n\t\t// day\n\t\tconst { value: _day } = eat(/[a-zA-Z]+/)\n\t\teat('whitespaces')\n\n\t\t// time\n\t\tconst time = match(/(\\d{2}:\\d{2})(?:-(\\d{2}:\\d{2}))?/)\n\t\tif (time) {\n\t\t\tdate = `${_date} ${time.result[1]}`\n\t\t\tif (time.result[2]) {\n\t\t\t\tend = `${_date} ${time.result[2]}`\n\t\t\t}\n\t\t\tjump(time.position.end)\n\t\t}\n\n\t\t// closing\n\t\tconst closing = getChar()\n\t\tif (\n\t\t\t(opening.value === '[' && closing === ']') ||\n\t\t\t(opening.value === '<' && closing === '>')\n\t\t) {\n\t\t\teat('char')\n\t\t\treturn {\n\t\t\t\tdate: zonedTimeToUtc(date, timezone),\n\t\t\t\tend: end ? zonedTimeToUtc(end, timezone) : undefined\n\t\t\t}\n\t\t}\n\n\t\t// opening closing does not match\n\t}\n\n\tconst ts = timestamp()\n\tif (!ts) return\n\n\tif (!ts.end) {\n\t\tconst doubleDash = eat(/--/)\n\t\tif (doubleDash) {\n\t\t\tconst end = timestamp()\n\t\t\tif (end) {\n\t\t\t\tts.end = end.date\n\t\t\t}\n\t\t}\n\t}\n\n\treturn ts\n}\n"
  },
  {
    "path": "packages/orga/src/todo.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { parseTodoKeywords } from './todo.ts'\n\ndescribe('todo manager', () => {\n\tit('works', () => {\n\t\tconst t = parseTodoKeywords('TODO NEXT | DONE')\n\t\tassert.deepEqual(t.keywords, ['TODO', 'NEXT', 'DONE'])\n\t\tassert.equal(t.next('TODO'), 'NEXT')\n\t\tassert.equal(t.next('NEXT'), 'DONE')\n\t\tassert.equal(t.next('DONE'), 'TODO')\n\t\tassert.equal(t.next('TODO', true), 'DONE')\n\t\tassert.equal(t.next('NEXT', true), 'TODO')\n\t\tassert.equal(t.next('DONE', true), 'NEXT')\n\t\tassert.equal(t.next('MISSING'), undefined)\n\t\tassert.equal(t.actionable('TODO'), true)\n\t\tassert.equal(t.actionable('NEXT'), true)\n\t\tassert.equal(t.actionable('DONE'), false)\n\t\tassert.equal(t.actionable('MISSING'), false)\n\t})\n\n\tit('last one as done without |', () => {\n\t\tconst t = parseTodoKeywords('TODO NEXT DONE')\n\t\tassert.deepEqual(t.keywords, ['TODO', 'NEXT', 'DONE'])\n\t\tassert.equal(t.next('TODO'), 'NEXT')\n\t\tassert.equal(t.next('NEXT'), 'DONE')\n\t\tassert.equal(t.next('DONE'), 'TODO')\n\t\tassert.equal(t.next('TODO', true), 'DONE')\n\t\tassert.equal(t.next('NEXT', true), 'TODO')\n\t\tassert.equal(t.next('DONE', true), 'NEXT')\n\t\tassert.equal(t.next('MISSING'), undefined)\n\t\tassert.equal(t.actionable('TODO'), true)\n\t\tassert.equal(t.actionable('NEXT'), true)\n\t\tassert.equal(t.actionable('DONE'), false)\n\t\tassert.equal(t.actionable('MISSING'), false)\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/todo.ts",
    "content": "export interface TodoKeywordSet {\n\tnext: (value: string, reverse?: boolean) => string | undefined\n\tactionable: (value: string) => boolean\n\tincludes: (value: string) => boolean\n\treadonly keywords: string[]\n}\n\nexport const defaultTodoManager = todoManager('TODO DONE')\n\nexport interface TodoManager extends TodoKeywordSet {\n\tadd: (todo: string) => void\n}\n\n/**\n * A simple todo list manager that allows cycling through keywords.\n * Keywords before the pipe '|' are considered actionable.\n * Keywords after the pipe are considered non-actionable.\n *\n * Example usage:\n *   todo('todo doing | done cancelled')\n *   // Cycles through: todo -> doing -> done -> cancelled -> todo ...\n *\n * @param value A string of space-separated keywords with an optional pipe '|'.\n */\nexport function parseTodoKeywords(value: string): TodoKeywordSet {\n\tconst keywords = value.trim().split(' ').filter(Boolean)\n\n\tlet divider = keywords.indexOf('|')\n\tif (divider === -1) divider = keywords.length - 1\n\n\treturn {\n\t\tnext,\n\t\tactionable,\n\t\tincludes: (v: string) => keywords.includes(v),\n\t\tget keywords() {\n\t\t\treturn keywords.filter((k) => k !== '|')\n\t\t}\n\t}\n\n\t/**\n\t * Get the next keyword in the list, circularly.\n\t * @returns The next keyword or undefined if not found.\n\t */\n\tfunction next(value: string, reverse = false) {\n\t\tconst index = keywords.indexOf(value)\n\t\tif (index === -1) return undefined\n\t\tconst nextIndex = _next(index, reverse)\n\t\treturn keywords[nextIndex]\n\t}\n\n\tfunction _next(idx: number, reverse: boolean) {\n\t\tconst offset = reverse ? -1 : 1\n\t\tlet nextIndex = idx + offset\n\t\tif (nextIndex < 0) nextIndex = keywords.length - 1\n\t\tif (nextIndex >= keywords.length) nextIndex = 0\n\t\t// skip the divider\n\t\tif (keywords[nextIndex] === '|') {\n\t\t\treturn _next(nextIndex, reverse)\n\t\t}\n\t\treturn nextIndex\n\t}\n\n\tfunction actionable(value: string) {\n\t\tconst index = keywords.indexOf(value)\n\t\tif (index !== -1 && index < divider) return true\n\t\treturn false\n\t}\n}\n\nexport function todoManager(...keywords: string[]): TodoManager {\n\tconst todos: TodoKeywordSet[] = keywords.map(parseTodoKeywords)\n\n\treturn {\n\t\tnext,\n\t\tactionable,\n\t\tincludes,\n\t\tadd,\n\t\tget keywords() {\n\t\t\treturn todos.flatMap((t) => t.keywords)\n\t\t}\n\t}\n\n\tfunction next(value: string, reverse = false) {\n\t\tfor (const todoSet of todos) {\n\t\t\tif (todoSet.includes(value)) {\n\t\t\t\tconst nextKeyword = todoSet.next(value, reverse)\n\t\t\t\tif (nextKeyword) return nextKeyword\n\t\t\t}\n\t\t}\n\t\treturn undefined\n\t}\n\n\tfunction actionable(value: string) {\n\t\tfor (const todoSet of todos) {\n\t\t\tif (todoSet.includes(value)) {\n\t\t\t\treturn todoSet.actionable(value)\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction includes(value: string) {\n\t\tfor (const todoSet of todos) {\n\t\t\tif (todoSet.includes(value)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn false\n\t}\n\n\tfunction add(todo: string) {\n\t\ttodos.push(parseTodoKeywords(todo))\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/__tests__/debug.ts",
    "content": "import { inspect } from 'node:util'\nimport chalk from 'chalk'\nimport { read } from 'text-kit'\nimport { tokenize } from '../index'\n\nexport default (text: string): void => {\n\tconst { substring } = read(text)\n\tconst tokens = tokenize(text).all()\n\tconst data = tokens.map((token) => ({\n\t\t...token,\n\t\t_content: substring(token.position)\n\t}))\n\n\tconst lines = [\n\t\tchalk.red('** DEBUG **'),\n\t\tchalk.red('> text:'),\n\t\tchalk.gray(text),\n\t\tchalk.red('> tokens:')\n\t].join('\\n')\n\n\tconsole.log(lines, inspect(data, false, null, true))\n\t// console.log(inspect(data, false, null, true))\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/__tests__/tok.ts",
    "content": "import { read } from 'text-kit'\nimport { defaultLexerOptions, type LexerOptions } from '../../options'\nimport { tokenize } from '../index'\n\nexport default (text: string, options: Partial<LexerOptions> = {}) => {\n\tconst { substring } = read(text)\n\tconst tokens = tokenize(text, { ...defaultLexerOptions, ...options }).all()\n\treturn tokens.map(({ position, ...token }) => ({\n\t\t...token,\n\t\t_text: position ? substring(position.start, position.end) : ''\n\t}))\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/blank.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize blanks', () => {\n\tit('could handle blanks', () => {\n\t\tassert.deepEqual(tokenize(''), [])\n\t\tassert.deepEqual(tokenize(' '), [\n\t\t\t{\n\t\t\t\t_text: ' ',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('    '), [\n\t\t\t{\n\t\t\t\t_text: '    ',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('\\t'), [\n\t\t\t{\n\t\t\t\t_text: '\\t',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' \\t'), [\n\t\t\t{\n\t\t\t\t_text: ' \\t',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('\\t '), [\n\t\t\t{\n\t\t\t\t_text: '\\t ',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' \\t  '), [\n\t\t\t{\n\t\t\t\t_text: ' \\t  ',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not blanks', () => {\n\t\tassert.deepEqual(tokenize(' a '), [\n\t\t\t{\n\t\t\t\t_text: ' a ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' a '\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/block.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize block', () => {\n\tit('knows block begins', () => {\n\t\tassert.deepEqual(tokenize('#+BEGIN_SRC swift'), [\n\t\t\t{\n\t\t\t\t_text: '#+BEGIN_SRC swift',\n\t\t\t\tname: 'SRC',\n\t\t\t\tparams: ['swift'],\n\t\t\t\ttype: 'block.begin'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('#+begin_src swift'), [\n\t\t\t{\n\t\t\t\t_text: '#+begin_src swift',\n\t\t\t\tname: 'src',\n\t\t\t\tparams: ['swift'],\n\t\t\t\ttype: 'block.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+begin_example'), [\n\t\t\t{\n\t\t\t\t_text: '#+begin_example',\n\t\t\t\tname: 'example',\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'block.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+begin_ex😀mple'), [\n\t\t\t{\n\t\t\t\t_text: '#+begin_ex😀mple',\n\t\t\t\tname: 'ex😀mple',\n\t\t\t\tparams: [],\n\t\t\t\ttype: 'block.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+begin_src swift :tangle code.swift'), [\n\t\t\t{\n\t\t\t\t_text: '#+begin_src swift :tangle code.swift',\n\t\t\t\tname: 'src',\n\t\t\t\tparams: ['swift', ':tangle', 'code.swift'],\n\t\t\t\ttype: 'block.begin'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not block begins', () => {\n\t\tassert.deepEqual(tokenize('#+begi😀n_src swift'), [\n\t\t\t{\n\t\t\t\t_text: '#+begi😀n_src swift',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '#+begi😀n_src swift'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows block ends', () => {\n\t\tassert.deepEqual(tokenize('#+END_SRC'), [\n\t\t\t{\n\t\t\t\t_text: '#+END_SRC',\n\t\t\t\tname: 'SRC',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  #+END_SRC'), [\n\t\t\t{\n\t\t\t\t_text: '#+END_SRC',\n\t\t\t\tname: 'SRC',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+end_src'), [\n\t\t\t{\n\t\t\t\t_text: '#+end_src',\n\t\t\t\tname: 'src',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+end_SRC'), [\n\t\t\t{\n\t\t\t\t_text: '#+end_SRC',\n\t\t\t\tname: 'SRC',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+end_S😀RC'), [\n\t\t\t{\n\t\t\t\t_text: '#+end_S😀RC',\n\t\t\t\tname: 'S😀RC',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+end_SRC '), [\n\t\t\t{\n\t\t\t\t_text: '#+end_SRC ',\n\t\t\t\tname: 'SRC',\n\t\t\t\ttype: 'block.end'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not block ends', () => {\n\t\tassert.deepEqual(tokenize('#+end_src param'), [\n\t\t\t{\n\t\t\t\t_text: '#+end_src param',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '#+end_src param'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/block.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default (reader: Reader): Token[] | undefined => {\n\tconst { match, eat, endOfLine, jump } = reader\n\tconst ws = eat('whitespaces')\n\n\tconst b = match(/#\\+begin_([^\\s\\n]+)\\s*(.*)$/imy, { end: endOfLine() })\n\tif (b) {\n\t\teat('line')\n\t\tconst params = b.result[2]\n\t\t\t.split(' ')\n\t\t\t.map((p) => p.trim())\n\t\t\t.filter(String)\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'block.begin',\n\t\t\t\tname: b.result[1],\n\t\t\t\tparams,\n\t\t\t\tposition: { ...b.position }\n\t\t\t}\n\t\t]\n\t}\n\n\tconst e = match(/#\\+end_([^\\s\\n]+)\\s*$/imy, { end: endOfLine() })\n\tif (e) {\n\t\treader.eat('line')\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'block.end',\n\t\t\t\tname: e.result[1],\n\t\t\t\tposition: { ...e.position }\n\t\t\t}\n\t\t]\n\t}\n\n\tws && jump(ws.position.start)\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/comment.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize comment', () => {\n\tit('knows comments', () => {\n\t\tassert.deepEqual(tokenize('# a comment'), [\n\t\t\t{\n\t\t\t\t_text: '# a comment',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('# '), [\n\t\t\t{\n\t\t\t\t_text: '# ',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: ''\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('# a comment😯'), [\n\t\t\t{\n\t\t\t\t_text: '# a comment😯',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment😯'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' # a comment'), [\n\t\t\t{\n\t\t\t\t_text: '# a comment',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  \\t  # a comment'), [\n\t\t\t{\n\t\t\t\t_text: '# a comment',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#   a comment'), [\n\t\t\t{\n\t\t\t\t_text: '#   a comment',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#    \\t a comment'), [\n\t\t\t{\n\t\t\t\t_text: '#    \t a comment',\n\t\t\t\ttype: 'comment',\n\t\t\t\tvalue: 'a comment'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not comments', () => {\n\t\tassert.deepEqual(tokenize('#not a comment'), [\n\t\t\t{\n\t\t\t\t_text: '#not a comment',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '#not a comment'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  #not a comment'), [\n\t\t\t{\n\t\t\t\t_text: '  #not a comment',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '  #not a comment'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/comment.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default ({ match, eat, jump }: Reader): Token | undefined => {\n\tconst ws = eat('whitespaces')\n\tif (match(/^#\\s/y)) {\n\t\tconst comment = match(/^#\\s+(.*)$/my)\n\t\tif (comment) {\n\t\t\teat('line')\n\t\t\treturn {\n\t\t\t\ttype: 'comment',\n\t\t\t\tposition: comment.position,\n\t\t\t\tvalue: comment.result[1]\n\t\t\t}\n\t\t}\n\t}\n\tws && jump(ws.position.start)\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/drawer.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize drawer', () => {\n\tit('knows drawer begins', () => {\n\t\tassert.deepEqual(tokenize(':PROPERTIES:'), [\n\t\t\t{\n\t\t\t\t_text: ':PROPERTIES:',\n\t\t\t\tname: 'PROPERTIES',\n\t\t\t\ttype: 'drawer.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :properties:'), [\n\t\t\t{\n\t\t\t\t_text: ':properties:',\n\t\t\t\tname: 'properties',\n\t\t\t\ttype: 'drawer.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :properties:  '), [\n\t\t\t{\n\t\t\t\t_text: ':properties:',\n\t\t\t\tname: 'properties',\n\t\t\t\ttype: 'drawer.begin'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :prop_erties:  '), [\n\t\t\t{\n\t\t\t\t_text: ':prop_erties:',\n\t\t\t\tname: 'prop_erties',\n\t\t\t\ttype: 'drawer.begin'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not drawer begins', () => {\n\t\tassert.deepEqual(tokenize('PROPERTIES:'), [\n\t\t\t{\n\t\t\t\t_text: 'PROPERTIES:',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'PROPERTIES:'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(':PROPERTIES'), [\n\t\t\t{\n\t\t\t\t_text: ':PROPERTIES',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ':PROPERTIES'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(':PR OPERTIES:'), [\n\t\t\t{\n\t\t\t\t_text: ':PR OPERTIES:',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ':PR OPERTIES:'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows drawer ends', () => {\n\t\tassert.deepEqual(tokenize(':END:'), [\n\t\t\t{\n\t\t\t\t_text: ':END:',\n\t\t\t\ttype: 'drawer.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :end:'), [\n\t\t\t{\n\t\t\t\t_text: ':end:',\n\t\t\t\ttype: 'drawer.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :end:  '), [\n\t\t\t{\n\t\t\t\t_text: ':end:',\n\t\t\t\ttype: 'drawer.end'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  :end:  '), [\n\t\t\t{\n\t\t\t\t_text: ':end:',\n\t\t\t\ttype: 'drawer.end'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not drawer ends', () => {\n\t\tassert.deepEqual(tokenize('END:'), [\n\t\t\t{\n\t\t\t\t_text: 'END:',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'END:'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(':END'), [\n\t\t\t{\n\t\t\t\t_text: ':END',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ':END'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(':ENDed'), [\n\t\t\t{\n\t\t\t\t_text: ':ENDed',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ':ENDed'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/drawer.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default (reader: Reader): Token[] => {\n\tconst { match, jump, eat } = reader\n\tconst ws = eat('whitespaces')\n\n\tconst drawerReg = /:(\\w+):(?=[ \\t]*$)/my\n\tconst m = match(drawerReg)\n\tif (m) {\n\t\tjump(m.position.end)\n\t\tconst name = m.result[1]\n\t\teat('whitespaces')\n\t\tif (name.toLowerCase() === 'end') {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'drawer.end',\n\t\t\t\t\tposition: m.position\n\t\t\t\t}\n\t\t\t]\n\t\t} else {\n\t\t\treturn [\n\t\t\t\t{\n\t\t\t\t\ttype: 'drawer.begin',\n\t\t\t\t\tname,\n\t\t\t\t\tposition: m.position\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t}\n\n\tws && jump(ws.position.start)\n\treturn []\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/empty.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default function ({ isStartOfLine, getLine, eat }: Reader): Token[] {\n\tconst tokens: Token[] = []\n\twhile (isStartOfLine()) {\n\t\tconst l = getLine()\n\t\tif (l === null || l.replace(/\\s/g, '').length > 0) break\n\t\tconst line = eat('line')\n\t\tif (!line) break\n\n\t\ttokens.push({\n\t\t\ttype: 'emptyLine',\n\t\t\tposition: line.position\n\t\t})\n\n\t\tconst nl = eat('newline')\n\t\tif (!nl) break\n\t\ttokens.push({\n\t\t\ttype: 'newline',\n\t\t\tposition: nl.position\n\t\t})\n\t}\n\treturn tokens\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/footnote.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize footnote', () => {\n\tit('knows footnotes', () => {\n\t\tassert.deepEqual(tokenize('[fn:1] a footnote'), [\n\t\t\t{\n\t\t\t\t_text: '[fn:1]',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'a footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'a footnote'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('[fn:word] a footnote'), [\n\t\t\t{\n\t\t\t\t_text: '[fn:word]',\n\t\t\t\tlabel: 'word',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'a footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'a footnote'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('[fn:word_] a footnote'), [\n\t\t\t{\n\t\t\t\t_text: '[fn:word_]',\n\t\t\t\tlabel: 'word_',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'a footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'a footnote'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('[fn:wor1d_] a footnote'), [\n\t\t\t{\n\t\t\t\t_text: '[fn:wor1d_]',\n\t\t\t\tlabel: 'wor1d_',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'a footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'a footnote'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not footnotes', () => {\n\t\tassert.deepEqual(tokenize('[fn:1]: not a footnote'), [\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '1',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ': not a footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ': not a footnote'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' [fn:1] not a footnote with space prefix'), [\n\t\t\t{\n\t\t\t\t_text: ' ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '1',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' not a footnote with space prefix',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' not a footnote with space prefix'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('[[fn:1] not a footnote with extra ['), [\n\t\t\t{\n\t\t\t\t_text: '[',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '['\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '1',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' not a footnote with extra [',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' not a footnote with extra ['\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('\\t[fn:1] not a footnote with a tab prefix'), [\n\t\t\t{\n\t\t\t\t_text: '\\t',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '\\t'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '1',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' not a footnote with a tab prefix',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' not a footnote with a tab prefix'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/footnote.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\nimport { tokenize as tokenizeInline } from './inline/index.js'\n\nexport default (reader: Reader): Token[] | undefined => {\n\tconst { isStartOfLine, match, jump, eat } = reader\n\tif (!isStartOfLine()) return\n\tlet tokens: Token[] = []\n\tconst m = match(/^\\[fn:([^\\]]+)\\](?=\\s)/y)\n\tif (!m) return []\n\ttokens.push({\n\t\ttype: 'footnote.label',\n\t\tlabel: m.result[1],\n\t\tposition: m.position\n\t})\n\tjump(m.position.end)\n\teat('whitespaces')\n\n\ttokens = tokens.concat(tokenizeInline(reader))\n\n\treturn tokens\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/headline.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize headline', () => {\n\tit('knows headlines', () => {\n\t\tassert.deepEqual(tokenize('** a headline'), [\n\t\t\t{ _text: '**', level: 2, type: 'stars' },\n\t\t\t{ _text: 'a headline', type: 'text', value: 'a headline' }\n\t\t])\n\n\t\tassert.deepEqual(tokenize('** _headline_'), [\n\t\t\t{ _text: '**', level: 2, type: 'stars' },\n\t\t\t{\n\t\t\t\t_text: '_headline_',\n\t\t\t\tstyle: 'underline',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'headline'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('**   a headline'), [\n\t\t\t{ _text: '**', level: 2, type: 'stars' },\n\t\t\t{ _text: 'a headline', type: 'text', value: 'a headline' }\n\t\t])\n\n\t\tassert.deepEqual(tokenize('***** a headline'), [\n\t\t\t{ _text: '*****', level: 5, type: 'stars' },\n\t\t\t{ _text: 'a headline', type: 'text', value: 'a headline' }\n\t\t])\n\n\t\tassert.deepEqual(tokenize('* a 😀line'), [\n\t\t\t{ _text: '*', level: 1, type: 'stars' },\n\t\t\t{ _text: 'a 😀line', type: 'text', value: 'a 😀line' }\n\t\t])\n\n\t\tassert.deepEqual(tokenize('* TODO [#A] a headline     :tag1:tag2:'), [\n\t\t\t{ _text: '*', level: 1, type: 'stars' },\n\t\t\t{\n\t\t\t\t_text: 'TODO',\n\t\t\t\tactionable: true,\n\t\t\t\tkeyword: 'TODO',\n\t\t\t\ttype: 'todo'\n\t\t\t},\n\t\t\t{ _text: '[#A]', type: 'priority', value: '[#A]' },\n\t\t\t{ _text: 'a headline', type: 'text', value: 'a headline' },\n\t\t\t{\n\t\t\t\t_text: ':tag1:tag2:',\n\t\t\t\ttags: ['tag1', 'tag2'],\n\t\t\t\ttype: 'tags'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(\n\t\t\ttokenize(\n\t\t\t\t'* TODO [#A] a headline :tag1:123:#hash:@at:org-mode:under_score:98%:'\n\t\t\t),\n\t\t\t[\n\t\t\t\t{ _text: '*', level: 1, type: 'stars' },\n\t\t\t\t{\n\t\t\t\t\t_text: 'TODO',\n\t\t\t\t\tactionable: true,\n\t\t\t\t\tkeyword: 'TODO',\n\t\t\t\t\ttype: 'todo'\n\t\t\t\t},\n\t\t\t\t{ _text: '[#A]', type: 'priority', value: '[#A]' },\n\t\t\t\t{ _text: 'a headline', type: 'text', value: 'a headline' },\n\t\t\t\t{\n\t\t\t\t\t_text: ':tag1:123:#hash:@at:org-mode:under_score:98%:',\n\t\t\t\t\ttags: [\n\t\t\t\t\t\t'tag1',\n\t\t\t\t\t\t'123',\n\t\t\t\t\t\t'#hash',\n\t\t\t\t\t\t'@at',\n\t\t\t\t\t\t'org-mode',\n\t\t\t\t\t\t'under_score',\n\t\t\t\t\t\t'98%'\n\t\t\t\t\t],\n\t\t\t\t\ttype: 'tags'\n\t\t\t\t}\n\t\t\t]\n\t\t)\n\t})\n\n\tit('knows these are not headlines', () => {\n\t\tassert.deepEqual(tokenize('*not a headline'), [\n\t\t\t{ _text: '*not a headline', type: 'text', value: '*not a headline' }\n\t\t])\n\n\t\tassert.deepEqual(tokenize(' * not a headline'), [\n\t\t\t{ _text: ' * not a headline', type: 'text', value: ' * not a headline' }\n\t\t])\n\t\tassert.deepEqual(tokenize('*_* not a headline'), [\n\t\t\t{ _text: '*_*', style: 'bold', type: 'text', value: '_' },\n\t\t\t{ _text: ' not a headline', type: 'text', value: ' not a headline' }\n\t\t])\n\t\tassert.deepEqual(tokenize('not a headline'), [\n\t\t\t{ _text: 'not a headline', type: 'text', value: 'not a headline' }\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/headline.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { TodoKeywordSet } from '../todo.js'\nimport type { Token } from '../types.js'\nimport { tokenize } from './inline/index.js'\n\nexport default (todo: TodoKeywordSet) =>\n\t(reader: Reader): Token[] | undefined => {\n\t\tconst { isStartOfLine, match, now, eol, eat, jump, substring, endOfLine } =\n\t\t\treader\n\n\t\tif (!isStartOfLine() || !match(/^\\*+[ \\t]+/my)) return\n\n\t\t// TODO: cache this, for performance sake\n\t\tconst todos = todo.keywords\n\n\t\tlet buffer: Token[] = []\n\n\t\tconst stars = eat(/^\\*+(?=[ \\t])/)\n\t\tif (!stars) throw Error('not gonna happen')\n\t\tbuffer.push({\n\t\t\ttype: 'stars',\n\t\t\tlevel: stars.value.length,\n\t\t\tposition: {\n\t\t\t\tstart: stars.position.start,\n\t\t\t\tend: eat('whitespaces').position.start\n\t\t\t}\n\t\t})\n\t\tconst keyword = eat(\n\t\t\tRegExp(`${todos.map(encodeURIComponent).join('|')}(?=[ \\t])`, 'y')\n\t\t)\n\t\tif (keyword) {\n\t\t\tbuffer.push({\n\t\t\t\ttype: 'todo',\n\t\t\t\tkeyword: keyword.value,\n\t\t\t\tactionable: todo.actionable(keyword.value),\n\t\t\t\tposition: {\n\t\t\t\t\tstart: keyword.position.start,\n\t\t\t\t\tend: eat('whitespaces').position.start\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tconst priority = eat(/^\\[#(A|B|C)\\](?=[ \\t])/y)\n\t\tif (priority) {\n\t\t\tbuffer.push({\n\t\t\t\ttype: 'priority',\n\t\t\t\t...priority,\n\t\t\t\tposition: {\n\t\t\t\t\tstart: priority.position.start,\n\t\t\t\t\tend: eat('whitespaces').position.start\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\tconst tags = match(/[ \\t]+(:(?:[\\w@_#%-]+:)+)[ \\t]*$/m, {\n\t\t\tend: endOfLine()\n\t\t})\n\t\tlet contentEnd = eol(now().line)\n\t\tif (tags) {\n\t\t\tcontentEnd = tags.position.start\n\t\t}\n\n\t\tconst r = reader.read({ end: contentEnd })\n\t\tconst tokens = tokenize(r)\n\t\tjump(r.now())\n\n\t\tbuffer = buffer.concat(tokens)\n\n\t\tif (tags) {\n\t\t\teat('whitespaces')\n\t\t\tconst tagsPosition = { start: now(), end: tags.position.end }\n\t\t\tconst s = substring(tagsPosition.start, tagsPosition.end)\n\t\t\tbuffer.push({\n\t\t\t\ttype: 'tags',\n\t\t\t\ttags: s\n\t\t\t\t\t.split(':')\n\t\t\t\t\t.map((t) => t.trim())\n\t\t\t\t\t.filter(Boolean),\n\t\t\t\tposition: { start: now(), end: tags.position.end }\n\t\t\t})\n\t\t\tjump(tags.position.end)\n\t\t}\n\t\treturn buffer\n\t}\n"
  },
  {
    "path": "packages/orga/src/tokenize/hr.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize hr', () => {\n\tit('knows horizontal rules', () => {\n\t\tassert.deepEqual(tokenize('-----'), [\n\t\t\t{\n\t\t\t\t_text: '-----',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('------'), [\n\t\t\t{\n\t\t\t\t_text: '------',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('--------'), [\n\t\t\t{\n\t\t\t\t_text: '--------',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  -----'), [\n\t\t\t{\n\t\t\t\t_text: '  -----',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('-----   '), [\n\t\t\t{\n\t\t\t\t_text: '-----   ',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  -----   '), [\n\t\t\t{\n\t\t\t\t_text: '  -----   ',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  -----  \\t '), [\n\t\t\t{\n\t\t\t\t_text: '  -----  \t ',\n\t\t\t\ttype: 'hr'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not horizontal rules', () => {\n\t\tassert.deepEqual(tokenize('----'), [\n\t\t\t{\n\t\t\t\t_text: '----',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '----'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('- ----'), [\n\t\t\t{\n\t\t\t\t_text: '-',\n\t\t\t\tindent: 0,\n\t\t\t\tordered: false,\n\t\t\t\ttype: 'list.item.bullet'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '----',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '----'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('-----a'), [\n\t\t\t{\n\t\t\t\t_text: '-----a',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '-----a'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('_-----'), [\n\t\t\t{\n\t\t\t\t_text: '_-----',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '_-----'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('-----    a'), [\n\t\t\t{\n\t\t\t\t_text: '-----    a',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '-----    a'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/hr.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default ({ eat }: Reader): Token | undefined => {\n\tconst hr = eat(/^\\s*-{5,}\\s*$/my)\n\tif (hr) {\n\t\treturn {\n\t\t\ttype: 'hr',\n\t\t\tposition: hr.position\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/index.ts",
    "content": "import { type Reader, read } from 'text-kit'\nimport type { Point, Position } from 'unist'\nimport type { LexerOptions } from '../options.js'\nimport type { TodoManager } from '../todo.js'\nimport type { Token } from '../types.js'\nimport block from './block.js'\nimport comment from './comment.js'\nimport drawer from './drawer.js'\nimport emptyLines from './empty.js'\nimport footnote from './footnote.js'\nimport headline from './headline.js'\nimport hr from './hr.js'\nimport { tokenize as inlineTok } from './inline/index.js'\nimport keyword from './keyword.js'\nimport latex from './latex.js'\nimport listItem from './list.js'\nimport planning from './planning.js'\nimport table from './table.js'\n\nconst PLANNING_KEYWORDS = ['DEADLINE', 'SCHEDULED', 'CLOSED']\n\nexport interface Lexer {\n\teat: (type?: string) => Token | undefined\n\teatAll: (type: string) => number\n\tpeek: (offset?: number) => Token | undefined\n\tmatch: (cond: RegExp | string, offset?: number) => boolean\n\tall: () => Token[]\n\tsave: () => number\n\trestore: (point: number) => void\n\tsubstring: (position: Position) => string\n\t/** Modify the next token (or the token at the given offset). */\n\tmodify(f: (t: Token) => Token, offset?: number): void\n\treadonly now: number\n\ttoOffset: (point: Point | number) => number\n\ttoPoint: (point: number) => Point\n\treadonly todo: TodoManager\n}\n\nexport type Tokenizer = (reader: Reader) => Token[] | Token | undefined\n\nexport const tokenize = (text: string, options: LexerOptions): Lexer => {\n\tconst { timezone, range, todo } = options\n\tconst reader = read(text, range)\n\tconst { getChar } = reader\n\n\tlet tokens: Token[] = []\n\n\tlet cursor = 0\n\n\tconst tokenizers: Tokenizer[] = [\n\t\t({ getChar, eat }) =>\n\t\t\tgetChar() === '\\n' && {\n\t\t\t\ttype: 'newline',\n\t\t\t\tposition: eat('char').position\n\t\t\t},\n\t\theadline(todo),\n\t\tdrawer,\n\t\tplanning({ keywords: PLANNING_KEYWORDS, timezone }),\n\t\tkeyword,\n\t\tblock,\n\t\tlatex,\n\t\tlistItem,\n\t\tcomment,\n\t\ttable,\n\t\thr,\n\t\tfootnote\n\t]\n\n\tfunction tok(): Token[] {\n\t\tconst all = emptyLines(reader)\n\n\t\t// eat('whitespaces')\n\n\t\tif (!getChar()) return all\n\n\t\tfor (const t of tokenizers) {\n\t\t\tconst result = t(reader)\n\t\t\tif (!result) continue\n\t\t\tconst tokens = Array.isArray(result) ? result : [result]\n\t\t\tif (tokens.length > 0) {\n\t\t\t\treturn [...all, ...tokens]\n\t\t\t}\n\t\t}\n\n\t\t// last resort\n\t\tconst currentLine = reader.read({ end: reader.endOfLine() })\n\t\tconst inlineTokens = inlineTok(currentLine)\n\t\treader.jump(currentLine.now())\n\t\treturn [...all, ...inlineTokens]\n\t}\n\n\tconst peek = (offset = 0): Token | undefined => {\n\t\tconst pos = cursor + offset\n\t\tif (pos >= tokens.length) {\n\t\t\ttokens = tokens.concat(tok())\n\t\t}\n\t\treturn tokens[pos]\n\t}\n\n\tconst modify = (f: (t: Token) => Token, offset = 0): void => {\n\t\tconst pos = cursor + offset\n\t\tconst token = peek(offset)\n\t\tif (token !== undefined) {\n\t\t\ttokens[pos] = f(token)\n\t\t}\n\t}\n\n\tconst _eat = (type: string | undefined = undefined): Token | undefined => {\n\t\tconst t = peek()\n\t\tif (!t) return undefined\n\t\tif (!type || type === t.type) {\n\t\t\tcursor += 1\n\t\t\treturn t\n\t\t}\n\t\treturn undefined\n\t}\n\n\treturn {\n\t\tpeek,\n\t\teat: _eat,\n\t\teatAll(type: string): number {\n\t\t\tlet count = 0\n\t\t\twhile (_eat(type)) {\n\t\t\t\tcount += 1\n\t\t\t}\n\t\t\treturn count\n\t\t},\n\t\tmatch(cond, _offset = 0) {\n\t\t\tconst token = peek()\n\t\t\tif (!token) return false\n\t\t\tif (typeof cond === 'string') {\n\t\t\t\treturn token.type === cond\n\t\t\t}\n\t\t\treturn cond.test(token.type)\n\t\t},\n\n\t\tall(_max: number | undefined = undefined): Token[] {\n\t\t\tlet _all: Token[] = []\n\t\t\tlet tokens = tok()\n\t\t\twhile (tokens.length > 0) {\n\t\t\t\t_all = _all.concat(tokens)\n\t\t\t\ttokens = tok()\n\t\t\t}\n\t\t\treturn _all\n\t\t},\n\n\t\tsave: () => cursor,\n\n\t\trestore(point) {\n\t\t\tcursor = point\n\t\t},\n\n\t\tsubstring: (pos) => reader.substring(pos.start, pos.end),\n\t\tmodify,\n\t\tget now() {\n\t\t\tconst token = peek()\n\t\t\treturn reader.toIndex(token?.position.start ?? Infinity)\n\t\t},\n\t\ttoOffset: (point) => reader.toIndex(point),\n\t\ttoPoint: (offset) => reader.toPoint(offset),\n\t\tget todo() {\n\t\t\treturn todo\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline/footnote.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../../types.js'\nimport { tokenize } from './index.js'\n\nconst tokFootnoteRefernece = (reader: Reader) => {\n\tconst tokens: Token[] = []\n\n\tconst { eat, now, jump } = reader\n\tconst fnb = eat(/^\\[fn:/)\n\tif (!fnb) return\n\ttokens.push({\n\t\ttype: 'opening',\n\t\telement: 'footnote.reference',\n\t\tposition: fnb.position\n\t})\n\tconst closing = reader.findClosing(fnb.position.start)\n\tif (!closing) return\n\tconst label = eat(/^[\\w_-]+/)\n\tif (label) {\n\t\ttokens.push({\n\t\t\ttype: 'footnote.label',\n\t\t\tlabel: label.value,\n\t\t\tposition: label.position\n\t\t})\n\t}\n\tif (label && now().offset === closing.offset) {\n\t\ttokens.push({\n\t\t\ttype: 'closing',\n\t\t\telement: 'footnote.reference',\n\t\t\tposition: eat().position\n\t\t})\n\t\treturn tokens\n\t}\n\n\tif (!eat(/^:/)) return\n\tconst defRange = {\n\t\tstart: now(),\n\t\tend: closing\n\t}\n\n\tconst more = tokenize(reader.read(defRange))\n\ttokens.push(...more)\n\tjump(closing)\n\n\ttokens.push({\n\t\ttype: 'closing',\n\t\telement: 'footnote.reference',\n\t\tposition: eat().position\n\t})\n\n\treturn tokens\n}\n\nexport default tokFootnoteRefernece\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline/index.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../../types.js'\nimport type { Tokenizer } from '../index.js'\nimport tokenizeFootnoteRef from './footnote.js'\nimport tokenizeLink from './link.js'\nimport tokenizeMath from './math.js'\nimport tokenizeText from './text.js'\n\nconst ALL: Tokenizer[] = [\n\ttokenizeFootnoteRef,\n\ttokenizeLink,\n\ttokenizeMath,\n\ttokenizeText()\n]\n\nexport const tokenize = (\n\treader: Reader,\n\ttokenizers: Tokenizer[] = ALL,\n\t{ ignoring }: { ignoring: string[] } = { ignoring: [] }\n): Token[] => {\n\tconst { now, eat, jump, substring, getChar, toPoint } = reader\n\n\tconst _tokens: Token[] = []\n\n\tlet cursor = now().offset\n\n\tconst push = (...tokens: Token[]) => {\n\t\tif (tokens.length === 0) return\n\t\t// collect plain text\n\t\tconst textEnd = tokens[0].position.start\n\t\tif (cursor < textEnd.offset) {\n\t\t\t_tokens.push({\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: substring(cursor, textEnd),\n\t\t\t\tposition: { start: toPoint(cursor), end: { ...textEnd } }\n\t\t\t})\n\t\t}\n\n\t\tcursor = tokens[tokens.length - 1].position.end.offset\n\t\t_tokens.push(...tokens)\n\t}\n\n\tmain: while (getChar()) {\n\t\tconst newline = eat('newline')\n\t\tif (newline) {\n\t\t\tpush({\n\t\t\t\ttype: 'newline',\n\t\t\t\tposition: newline.position\n\t\t\t})\n\t\t\tbreak // newline breaks inline\n\t\t}\n\n\t\tfor (const t of tokenizers) {\n\t\t\tconst r = reader.read()\n\t\t\tconst tokens = t(r)\n\t\t\tif (tokens) {\n\t\t\t\tpush(...(Array.isArray(tokens) ? tokens : [tokens]))\n\t\t\t\tjump(r.now())\n\t\t\t\tcontinue main\n\t\t\t}\n\t\t}\n\n\t\teat()\n\t}\n\n\tif (cursor < now().offset) {\n\t\tconst value = substring(cursor, reader.now())\n\t\t_tokens.push({\n\t\t\ttype: 'text',\n\t\t\tvalue,\n\t\t\tposition: { start: toPoint(cursor), end: reader.now() }\n\t\t})\n\t}\n\n\treturn _tokens\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline/link.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../../types.js'\nimport uri from '../../uri.js'\nimport type { Tokenizer } from '../index.js'\nimport { tokenize } from './index.js'\nimport tokenizeText from './text.js'\n\nconst tokenizeLink: Tokenizer = (reader: Reader) => {\n\tconst tokens: Token[] = []\n\tconst { eat, findClosing, jump, getChar, now } = reader\n\tif (getChar() !== '[') {\n\t\treturn\n\t}\n\tconst linkOpening = eat('char')\n\t// if (!linkOpening) return\n\n\ttokens.push({\n\t\ttype: 'opening',\n\t\telement: 'link',\n\t\tposition: linkOpening.position\n\t})\n\n\tconst linkClosing = findClosing(linkOpening.position.start)\n\tif (!linkClosing) return\n\n\tif (getChar() !== '[') {\n\t\treturn\n\t}\n\tconst pathOpening = eat('char')\n\tconst pathClosing = findClosing(pathOpening.position.start)\n\tif (!pathClosing) return\n\n\tconst linkInfo = uri(reader.substring(pathOpening.position.end, pathClosing))\n\tif (!linkInfo) return\n\n\tjump(pathClosing)\n\teat('char') // eat the ]\n\n\ttokens.push({\n\t\ttype: 'link.path',\n\t\t...linkInfo,\n\t\tposition: {\n\t\t\tstart: pathOpening.position.start,\n\t\t\tend: now()\n\t\t}\n\t})\n\tif (getChar() === '[') {\n\t\tconst descClosing = findClosing()\n\t\tif (!descClosing) {\n\t\t\treturn\n\t\t}\n\t\teat() // descOpening\n\t\tconst desc = tokenize(reader.read({ end: descClosing }), [\n\t\t\ttokenizeText(now())\n\t\t])\n\t\ttokens.push(...desc)\n\t}\n\n\tjump(linkClosing)\n\ttokens.push({\n\t\ttype: 'closing',\n\t\telement: 'link',\n\t\tposition: eat().position\n\t})\n\n\treturn tokens\n}\n\nexport default tokenizeLink\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline/math.ts",
    "content": "import type { Token } from '../../types.js'\nimport type { Tokenizer } from '../index.js'\n\nconst tokenizeMath: Tokenizer = (reader) => {\n\tconst { now, eat, getChar, jump, substring, match } = reader\n\tconst tokens: Token[] = []\n\tconst tokenStart = now()\n\tlet closingMatch: RegExp | undefined\n\tif (getChar() === '\\\\') {\n\t\teat()\n\t\tconst opening = getChar()\n\t\tif (opening === '(') {\n\t\t\tclosingMatch = /\\\\\\)/\n\t\t} else if (opening === '[') {\n\t\t\tclosingMatch = /\\\\]/\n\t\t} else return\n\t\teat()\n\t} else if (getChar() === '$') {\n\t\teat()\n\t\tif (getChar() === '$') {\n\t\t\teat()\n\t\t\tclosingMatch = /\\$\\$/\n\t\t} else return\n\t}\n\n\tif (!closingMatch) return\n\n\tconst valueStart = now()\n\n\tconst m = match(closingMatch)\n\tif (!m) return\n\tconst valueEnd = m.position.start\n\n\tjump(m.position.end)\n\tconst tokenEnd = now()\n\n\ttokens.push({\n\t\ttype: 'text',\n\t\tstyle: 'math',\n\t\tvalue: substring(valueStart, valueEnd),\n\t\tposition: { start: tokenStart, end: tokenEnd }\n\t})\n\n\treturn tokens\n}\n\nexport default tokenizeMath\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline/text.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Point } from 'unist'\nimport type { Style, Token } from '../../types.js'\n\nconst MARKERS: { [key: string]: Style } = {\n\t'*': 'bold',\n\t'=': 'verbatim',\n\t'/': 'italic',\n\t'+': 'strikeThrough',\n\t_: 'underline',\n\t'~': 'code'\n}\n\nconst tokenizeText =\n\t(bol: Point | undefined = undefined) =>\n\t(reader: Reader) => {\n\t\tconst tokens: Token[] = []\n\t\tconst { now, eat, jump, getChar, findClosing, substring } = reader\n\t\tconst marker = getChar()\n\t\tconst style = MARKERS[marker]\n\t\tif (!style) return\n\t\t// check pre\n\t\tconst pre = getChar(-1)\n\t\tconst isBOL = (bol && bol.offset === now().offset) || now().column === 1\n\t\tif (!isBOL && !/[\\s({'\"]/.test(pre)) return\n\t\tconst tokenStart = now()\n\n\t\tconst closing = findClosing(now())\n\t\tif (!closing) return\n\n\t\teat()\n\t\tconst valueStart = now()\n\t\t// check border\n\t\tif (getChar().match(/\\s/)) return\n\n\t\tjump(closing)\n\t\t// check border\n\t\tif (getChar(-1).match(/\\s/)) return\n\t\t// check post\n\t\tconst post = getChar(1)\n\t\tif (post && ` \\t\\n-.,;:!?')}[\"`.indexOf(post) === -1) return\n\n\t\tconst valueEnd = now()\n\t\teat() // closing\n\t\ttokens.push({\n\t\t\ttype: 'text',\n\t\t\tstyle,\n\t\t\tvalue: substring(valueStart, valueEnd),\n\t\t\tposition: { start: tokenStart, end: now() }\n\t\t})\n\t\treturn tokens\n\t}\n\nexport default tokenizeText\n"
  },
  {
    "path": "packages/orga/src/tokenize/inline.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('Inline Tokenization', () => {\n\tit('recon single emphasis', () => {\n\t\tassert.deepEqual(tokenize('hello *world*, welcome to *org-mode*.'), [\n\t\t\t{\n\t\t\t\t_text: 'hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '*world*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'world'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ', welcome to ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ', welcome to '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '*org-mode*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'org-mode'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon emphasises at different locations', () => {\n\t\tassert.deepEqual(tokenize('one *two* three'), [\n\t\t\t{\n\t\t\t\t_text: 'one ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'one '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '*two*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'two'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' three',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' three'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('*one* two three'), [\n\t\t\t{\n\t\t\t\t_text: '*one*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'one'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' two three',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' two three'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('one two *three*'), [\n\t\t\t{\n\t\t\t\t_text: 'one two ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'one two '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '*three*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'three'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon link', () => {\n\t\tassert.deepEqual(tokenize(`hello [[./image/logo.png]]`), [\n\t\t\t{\n\t\t\t\t_text: 'hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[./image/logo.png]',\n\t\t\t\tprotocol: 'file',\n\t\t\t\tsearch: undefined,\n\t\t\t\ttype: 'link.path',\n\t\t\t\tvalue: './image/logo.png'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'closing'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize(`hello [[Internal Link][link]]`), [\n\t\t\t{\n\t\t\t\t_text: 'hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[Internal Link]',\n\t\t\t\tprotocol: 'internal',\n\t\t\t\tsearch: undefined,\n\t\t\t\ttype: 'link.path',\n\t\t\t\tvalue: 'Internal Link'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'link',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'link'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'closing'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize(`hello [[../image/logo.png][logo]]`), [\n\t\t\t{\n\t\t\t\t_text: 'hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[../image/logo.png]',\n\t\t\t\tprotocol: 'file',\n\t\t\t\tsearch: undefined,\n\t\t\t\ttype: 'link.path',\n\t\t\t\tvalue: '../image/logo.png'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'logo',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'logo'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'closing'\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize(`that is a [[../image/logo.png][/nice/ logo]]`), [\n\t\t\t{\n\t\t\t\t_text: 'that is a ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'that is a '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[../image/logo.png]',\n\t\t\t\tprotocol: 'file',\n\t\t\t\tsearch: undefined,\n\t\t\t\ttype: 'link.path',\n\t\t\t\tvalue: '../image/logo.png'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '/nice/',\n\t\t\t\tstyle: 'italic',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'nice'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' logo',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' logo'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'link',\n\t\t\t\ttype: 'closing'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon footnote reference', () => {\n\t\tassert.deepEqual(tokenize(`hello[fn:1] world.`), [\n\t\t\t{\n\t\t\t\t_text: 'hello',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '1',\n\t\t\t\tlabel: '1',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon anonymous footnote reference', () => {\n\t\tassert.deepEqual(tokenize('hello[fn::Anonymous] world.'), [\n\t\t\t{\n\t\t\t\t_text: 'hello',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'Anonymous',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'Anonymous'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon anonymous footnote reference with inner footnote reference', () => {\n\t\tassert.deepEqual(tokenize('hello[fn::[fn::Anonymous]] world.'), [\n\t\t\t{\n\t\t\t\t_text: 'hello',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'Anonymous',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'Anonymous'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon anonymous footnote reference with empty body', () => {\n\t\tassert.deepEqual(tokenize('hello[fn::] world.'), [\n\t\t\t{\n\t\t\t\t_text: 'hello',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon named inline footnote', () => {\n\t\tassert.deepEqual(tokenize('hello[fn:named:Inline named footnote] world.'), [\n\t\t\t{\n\t\t\t\t_text: 'hello',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'hello'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '[fn:',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'opening'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'named',\n\t\t\t\tlabel: 'named',\n\t\t\t\ttype: 'footnote.label'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'Inline named footnote',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'Inline named footnote'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ']',\n\t\t\t\telement: 'footnote.reference',\n\t\t\t\ttype: 'closing'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world.'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon invalid inline markups', () => {\n\t\tassert.deepEqual(tokenize(`* word*`), [\n\t\t\t{\n\t\t\t\t_text: '*',\n\t\t\t\tlevel: 1,\n\t\t\t\ttype: 'stars'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'word*',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'word*'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(`*word *`), [\n\t\t\t{\n\t\t\t\t_text: '*word *',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '*word *'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon emphasises with 2 chars', () => {\n\t\tassert.deepEqual(tokenize(`*12*`), [\n\t\t\t{\n\t\t\t\t_text: '*12*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '12'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(`*1*`), [\n\t\t\t{\n\t\t\t\t_text: '*1*',\n\t\t\t\tstyle: 'bold',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '1'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('recon mixed emphasis', () => {\n\t\tassert.deepEqual(\n\t\t\ttokenize(\n\t\t\t\t\"[[https://github.com/xiaoxinghu/orgajs][Here's]] to the *crazy* ones, the /misfits/, the _rebels_, the ~troublemakers~, the round pegs in the +round+ square holes...\"\n\t\t\t),\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t_text: '[',\n\t\t\t\t\telement: 'link',\n\t\t\t\t\ttype: 'opening'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '[https://github.com/xiaoxinghu/orgajs]',\n\t\t\t\t\tprotocol: 'https',\n\t\t\t\t\tsearch: undefined,\n\t\t\t\t\ttype: 'link.path',\n\t\t\t\t\tvalue: 'https://github.com/xiaoxinghu/orgajs'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: \"Here's\",\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: \"Here's\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ']',\n\t\t\t\t\telement: 'link',\n\t\t\t\t\ttype: 'closing'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ' to the ',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ' to the '\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '*crazy*',\n\t\t\t\t\tstyle: 'bold',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: 'crazy'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ' ones, the ',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ' ones, the '\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '/misfits/',\n\t\t\t\t\tstyle: 'italic',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: 'misfits'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ', the ',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ', the '\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '_rebels_',\n\t\t\t\t\tstyle: 'underline',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: 'rebels'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ', the ',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ', the '\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '~troublemakers~',\n\t\t\t\t\tstyle: 'code',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: 'troublemakers'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ', the round pegs in the ',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ', the round pegs in the '\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: '+round+',\n\t\t\t\t\tstyle: 'strikeThrough',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: 'round'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ' square holes...',\n\t\t\t\t\ttype: 'text',\n\t\t\t\t\tvalue: ' square holes...'\n\t\t\t\t}\n\t\t\t]\n\t\t)\n\t})\n\n\tit('can handle something more complicated', () => {\n\t\tconst content = `\nSpecial characters =~= and =!=. Also =~/.this/path= and ~that~ thing.\n`\n\n\t\tassert.deepEqual(tokenize(content), [\n\t\t\t{\n\t\t\t\t_text: '',\n\t\t\t\ttype: 'emptyLine'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '\\n',\n\t\t\t\ttype: 'newline'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'Special characters ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'Special characters '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '=~=',\n\t\t\t\tstyle: 'verbatim',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '~'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' and ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' and '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '=!=',\n\t\t\t\tstyle: 'verbatim',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '!'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '. Also ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '. Also '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '=~/.this/path=',\n\t\t\t\tstyle: 'verbatim',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '~/.this/path'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' and ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' and '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '~that~',\n\t\t\t\tstyle: 'code',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'that'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' thing.',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' thing.'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '\\n',\n\t\t\t\ttype: 'newline'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/keyword.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default (reader: Reader): Token[] | undefined => {\n\tconst keyword = reader.match(/^#\\+(\\w+):(?:[ \\t]+(.*))?$/my)\n\tif (keyword) {\n\t\treader.eat('line')\n\t\tconst tokens: Token[] = [\n\t\t\t{\n\t\t\t\ttype: 'keyword',\n\t\t\t\tkey: keyword.result[1],\n\t\t\t\tvalue: keyword.result[2] ?? '',\n\t\t\t\tposition: keyword.position\n\t\t\t}\n\t\t]\n\t\tconst nl = reader.eat('newline')\n\t\tif (nl) {\n\t\t\ttokens.push({\n\t\t\t\ttype: 'newline',\n\t\t\t\tposition: nl.position\n\t\t\t})\n\t\t}\n\n\t\treturn tokens\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/keywords.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize keywords', () => {\n\tit('knows keywords', () => {\n\t\tassert.deepEqual(tokenize('#+KEY: Value'), [\n\t\t\t{\n\t\t\t\t_text: '#+KEY: Value',\n\t\t\t\tkey: 'KEY',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: 'Value'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+KEY: Another Value'), [\n\t\t\t{\n\t\t\t\t_text: '#+KEY: Another Value',\n\t\t\t\tkey: 'KEY',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: 'Another Value'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+KEY: value : Value'), [\n\t\t\t{\n\t\t\t\t_text: '#+KEY: value : Value',\n\t\t\t\tkey: 'KEY',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: 'value : Value'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not keywords', () => {\n\t\tassert.deepEqual(tokenize('#+KEY : Value'), [\n\t\t\t{\n\t\t\t\t_text: '#+KEY : Value',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '#+KEY : Value'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('#+KE Y: Value'), [\n\t\t\t{\n\t\t\t\t_text: '#+KE Y: Value',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '#+KE Y: Value'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('ignores empty keywords', () => {\n\t\tassert.deepEqual(tokenize('#+todo:'), [\n\t\t\t{\n\t\t\t\t_text: '#+todo:',\n\t\t\t\tkey: 'todo',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: ''\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('#+todo:  '), [\n\t\t\t{\n\t\t\t\t_text: '#+todo:  ',\n\t\t\t\tkey: 'todo',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: ''\n\t\t\t}\n\t\t])\n\n\t\tassert.deepEqual(tokenize('#+todo:\\ncontent'), [\n\t\t\t{\n\t\t\t\t_text: '#+todo:',\n\t\t\t\tkey: 'todo',\n\t\t\t\ttype: 'keyword',\n\t\t\t\tvalue: ''\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '\\n',\n\t\t\t\ttype: 'newline'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'content',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'content'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/latex.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\n\nexport default (reader: Reader): Token[] | undefined => {\n\tconst { match, eat, endOfLine } = reader\n\n\tconst b = match(/\\\\begin\\{([a-zA-Z0-9*]+)\\}\\s*$/imy, { end: endOfLine() })\n\tif (b) {\n\t\teat('line')\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'latex.begin',\n\t\t\t\tname: b.result[1],\n\t\t\t\tposition: { ...b.position }\n\t\t\t}\n\t\t]\n\t}\n\n\tconst e = match(/\\\\end\\{([a-zA-Z0-9*]+)\\}\\s*$/imy, { end: endOfLine() })\n\tif (e) {\n\t\treader.eat('line')\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'latex.end',\n\t\t\t\tname: e.result[1],\n\t\t\t\tposition: { ...e.position }\n\t\t\t}\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/list.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize list item', () => {\n\tit('knows list items', () => {\n\t\t// unordered\n\t\tassert.deepEqual(tokenize('- buy milk'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: 'buy milk', type: 'text', value: 'buy milk' }\n\t\t])\n\t\tassert.deepEqual(tokenize('+ buy milk'), [\n\t\t\t{ _text: '+', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: 'buy milk', type: 'text', value: 'buy milk' }\n\t\t])\n\t\t// ordered\n\t\tassert.deepEqual(tokenize('1. buy milk'), [\n\t\t\t{ _text: '1.', indent: 0, ordered: true, type: 'list.item.bullet' },\n\t\t\t{ _text: 'buy milk', type: 'text', value: 'buy milk' }\n\t\t])\n\t\tassert.deepEqual(tokenize('12. buy milk'), [\n\t\t\t{\n\t\t\t\t_text: '12.',\n\t\t\t\tindent: 0,\n\t\t\t\tordered: true,\n\t\t\t\ttype: 'list.item.bullet'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'buy milk',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'buy milk'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('123) buy milk'), [\n\t\t\t{\n\t\t\t\t_text: '123)',\n\t\t\t\tindent: 0,\n\t\t\t\tordered: true,\n\t\t\t\ttype: 'list.item.bullet'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: 'buy milk',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'buy milk'\n\t\t\t}\n\t\t])\n\t\t// checkbox\n\t\tassert.deepEqual(tokenize('- [x] buy milk checked'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: '[x]', checked: true, type: 'list.item.checkbox' },\n\t\t\t{ _text: 'buy milk checked', type: 'text', value: 'buy milk checked' }\n\t\t])\n\t\tassert.deepEqual(tokenize('- [X] buy milk checked'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: '[X]', checked: true, type: 'list.item.checkbox' },\n\t\t\t{ _text: 'buy milk checked', type: 'text', value: 'buy milk checked' }\n\t\t])\n\t\tassert.deepEqual(tokenize('- [-] buy milk checked'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: '[-]', checked: true, type: 'list.item.checkbox' },\n\t\t\t{ _text: 'buy milk checked', type: 'text', value: 'buy milk checked' }\n\t\t])\n\t\tassert.deepEqual(tokenize('- [ ] buy milk unchecked'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: '[ ]', checked: false, type: 'list.item.checkbox' },\n\t\t\t{\n\t\t\t\t_text: 'buy milk unchecked',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'buy milk unchecked'\n\t\t\t}\n\t\t])\n\t\t// indent\n\t\tassert.deepEqual(tokenize('  - buy milk'), [\n\t\t\t{ _text: '-', indent: 2, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: 'buy milk', type: 'text', value: 'buy milk' }\n\t\t])\n\t\t// tag\n\t\tassert.deepEqual(tokenize('- item1 :: description here'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: 'item1', type: 'list.item.tag', value: 'item1' },\n\t\t\t{\n\t\t\t\t_text: 'description here',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'description here'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('- item2\\n :: description here'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: 'item2', type: 'text', value: 'item2' },\n\t\t\t{ _text: '\\n', type: 'newline' },\n\t\t\t{\n\t\t\t\t_text: ' :: description here',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' :: description here'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('- [x] item3 :: description here'), [\n\t\t\t{ _text: '-', indent: 0, ordered: false, type: 'list.item.bullet' },\n\t\t\t{ _text: '[x]', checked: true, type: 'list.item.checkbox' },\n\t\t\t{ _text: 'item3', type: 'list.item.tag', value: 'item3' },\n\t\t\t{\n\t\t\t\t_text: 'description here',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'description here'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not list items', () => {\n\t\tassert.deepEqual(tokenize('-not item'), [\n\t\t\t{ _text: '-not item', type: 'text', value: '-not item' }\n\t\t])\n\t\tassert.deepEqual(tokenize('1.not item'), [\n\t\t\t{ _text: '1.not item', type: 'text', value: '1.not item' }\n\t\t])\n\t\tassert.deepEqual(tokenize('8)not item'), [\n\t\t\t{ _text: '8)not item', type: 'text', value: '8)not item' }\n\t\t])\n\t\tassert.deepEqual(tokenize('8a) not item'), [\n\t\t\t{ _text: '8a) not item', type: 'text', value: '8a) not item' }\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/list.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\nimport { tokenize as tokenizeInline } from './inline/index.js'\n\nexport default (reader: Reader): Token[] => {\n\tconst { now, match, eat, jump, substring, endOfLine } = reader\n\tconst ws = eat('whitespaces')\n\n\tlet tokens: Token[] = []\n\n\tconst indent = now().column - 1\n\n\tconst bullet = match(/^([-+]|\\d+[.)])(?=\\s)/y)\n\tif (!bullet) {\n\t\tws && jump(ws.position.start)\n\t\treturn []\n\t}\n\ttokens.push({\n\t\ttype: 'list.item.bullet',\n\t\tindent,\n\t\tordered: /^\\d/.test(bullet.result[1]),\n\t\tposition: bullet.position\n\t})\n\n\tjump(bullet.position.end)\n\teat('whitespaces')\n\n\tconst checkbox = match(/^\\[(x|X|-| )\\](?=\\s)/y)\n\tif (checkbox) {\n\t\ttokens.push({\n\t\t\ttype: 'list.item.checkbox',\n\t\t\tchecked: checkbox.result[1] !== ' ',\n\t\t\tposition: checkbox.position\n\t\t})\n\t\tjump(checkbox.position.end)\n\t}\n\n\teat('whitespaces')\n\n\tconst tagMark = match(/\\s+::\\s+/, { end: endOfLine() })\n\tif (tagMark) {\n\t\tconst pos = { start: now(), end: tagMark.position.start }\n\t\ttokens.push({\n\t\t\ttype: 'list.item.tag',\n\t\t\tvalue: substring(pos.start, pos.end),\n\t\t\tposition: pos\n\t\t})\n\t\tjump(tagMark.position.end)\n\t}\n\n\ttokens = tokens.concat(tokenizeInline(reader))\n\n\treturn tokens\n}\n"
  },
  {
    "path": "packages/orga/src/tokenize/partial.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('partial tokenize', () => {\n\tit('can start from the middle', () => {\n\t\tassert.deepEqual(tokenize('a b c', { range: { start: 2 } }), [\n\t\t\t{ type: 'text', value: 'b c', _text: 'b c' }\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/planning.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\nconst options = {\n\ttimezone: 'Pacific/Auckland'\n}\n\ndescribe('tokenize planning', () => {\n\tit('knows plannings', () => {\n\t\tassert.deepEqual(tokenize('DEADLINE: <2018-01-01 Mon>', options), [\n\t\t\t{\n\t\t\t\t_text: 'DEADLINE:',\n\t\t\t\ttype: 'planning.keyword',\n\t\t\t\tvalue: 'DEADLINE'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' <2018-01-01 Mon>',\n\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\tvalue: {\n\t\t\t\t\tdate: new Date('2017-12-31T11:00:00.000Z'),\n\t\t\t\t\tend: undefined\n\t\t\t\t}\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('  DEADLINE: <2018-01-01 Mon>', options), [\n\t\t\t{\n\t\t\t\t_text: 'DEADLINE:',\n\t\t\t\ttype: 'planning.keyword',\n\t\t\t\tvalue: 'DEADLINE'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' <2018-01-01 Mon>',\n\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\tvalue: {\n\t\t\t\t\tdate: new Date('2017-12-31T11:00:00.000Z'),\n\t\t\t\t\tend: undefined\n\t\t\t\t}\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' \\tDEADLINE: <2018-01-01 Mon>', options), [\n\t\t\t{\n\t\t\t\t_text: 'DEADLINE:',\n\t\t\t\ttype: 'planning.keyword',\n\t\t\t\tvalue: 'DEADLINE'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' <2018-01-01 Mon>',\n\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\tvalue: {\n\t\t\t\t\tdate: new Date('2017-12-31T11:00:00.000Z'),\n\t\t\t\t\tend: undefined\n\t\t\t\t}\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(' \\t DEADLINE: <2018-01-01 Mon>', options), [\n\t\t\t{\n\t\t\t\t_text: 'DEADLINE:',\n\t\t\t\ttype: 'planning.keyword',\n\t\t\t\tvalue: 'DEADLINE'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' <2018-01-01 Mon>',\n\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\tvalue: {\n\t\t\t\t\tdate: new Date('2017-12-31T11:00:00.000Z'),\n\t\t\t\t\tend: undefined\n\t\t\t\t}\n\t\t\t}\n\t\t])\n\t})\n\n\tit('know multiple plannings', () => {\n\t\tassert.deepEqual(\n\t\t\ttokenize(\n\t\t\t\t'DEADLINE: <2020-07-03 Fri> SCHEDULED: <2020-07-03 Fri>',\n\t\t\t\toptions\n\t\t\t),\n\t\t\t[\n\t\t\t\t{\n\t\t\t\t\t_text: 'DEADLINE:',\n\t\t\t\t\ttype: 'planning.keyword',\n\t\t\t\t\tvalue: 'DEADLINE'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ' <2020-07-03 Fri> ',\n\t\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdate: new Date('2020-07-02T12:00:00.000Z'),\n\t\t\t\t\t\tend: undefined\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: 'SCHEDULED:',\n\t\t\t\t\ttype: 'planning.keyword',\n\t\t\t\t\tvalue: 'SCHEDULED'\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t_text: ' <2020-07-03 Fri>',\n\t\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\t\tvalue: {\n\t\t\t\t\t\tdate: new Date('2020-07-02T12:00:00.000Z'),\n\t\t\t\t\t\tend: undefined\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t)\n\t})\n\n\tit('knows these are not plannings', () => {\n\t\tassert.deepEqual(tokenize('dEADLINE: <2018-01-01 Mon>', options), [\n\t\t\t{\n\t\t\t\t_text: 'dEADLINE: <2018-01-01 Mon>',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: 'dEADLINE: <2018-01-01 Mon>'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/planning.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Point } from 'unist'\nimport { parse as parseTimestamp } from '../timestamp.js'\nimport type { Token } from '../types.js'\n\nexport default ({\n\tkeywords,\n\ttimezone\n}: {\n\tkeywords: string[]\n\ttimezone: string\n}) =>\n\t(reader: Reader): Token[] | undefined => {\n\t\tconst { now, match, eat, substring, getLine, jump } = reader\n\t\tconst ws = eat('whitespaces')\n\n\t\tconst pattern = `(${keywords.join('|')}):`\n\n\t\tif (!match(RegExp(pattern, 'y'))) {\n\t\t\tws && jump(ws.position.start)\n\t\t\treturn\n\t\t}\n\n\t\tconst currentLine = getLine()\n\n\t\tconst { line, column, offset } = now()\n\n\t\tconst getLocation = (_offset: number): Point => ({\n\t\t\tline,\n\t\t\tcolumn: column + _offset,\n\t\t\toffset: offset + _offset\n\t\t})\n\n\t\tconst all: Token[] = []\n\n\t\tconst parseLastTimestamp = (end: number) => {\n\t\t\tif (all.length === 0) return\n\t\t\tconst { type, position } = all[all.length - 1]\n\t\t\tif (!position) throw Error(`position is ${position}`)\n\t\t\tif (type !== 'planning.keyword') return\n\t\t\tconst endLocation = getLocation(end)\n\t\t\tconst timestampPosition = { start: position.end, end: endLocation }\n\t\t\tconst value = substring(timestampPosition.start, timestampPosition.end)\n\t\t\tall.push({\n\t\t\t\ttype: 'planning.timestamp',\n\t\t\t\tvalue: parseTimestamp(value, { timezone }),\n\t\t\t\tposition: timestampPosition\n\t\t\t})\n\t\t}\n\n\t\tconst p = RegExp(pattern, 'g')\n\t\tfor (;;) {\n\t\t\tconst m = p.exec(currentLine)\n\t\t\tif (m === null) break\n\t\t\tparseLastTimestamp(m.index)\n\n\t\t\tall.push({\n\t\t\t\ttype: 'planning.keyword',\n\t\t\t\tvalue: m[1],\n\t\t\t\tposition: {\n\t\t\t\t\tstart: getLocation(m.index),\n\t\t\t\t\tend: getLocation(p.lastIndex)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t\tparseLastTimestamp(currentLine.length)\n\t\teat('line')\n\n\t\treturn all\n\t}\n"
  },
  {
    "path": "packages/orga/src/tokenize/table.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport tokenize from './__tests__/tok'\n\ndescribe('tokenize table', () => {\n\tit('knows table hr', () => {\n\t\tassert.deepEqual(tokenize('|----+---+----|'), [\n\t\t\t{ _text: '|----+---+----|', type: 'table.hr' }\n\t\t])\n\t\tassert.deepEqual(tokenize('|--=-+---+----|'), [\n\t\t\t{ _text: '|--=-+---+----|', type: 'table.hr' }\n\t\t])\n\t\tassert.deepEqual(tokenize('  |----+---+----|'), [\n\t\t\t{ _text: '|----+---+----|', type: 'table.hr' }\n\t\t])\n\t\tassert.deepEqual(tokenize('|----+---+----'), [\n\t\t\t{ _text: '|----+---+----', type: 'table.hr' }\n\t\t])\n\t\tassert.deepEqual(tokenize('|---'), [{ _text: '|---', type: 'table.hr' }])\n\t\tassert.deepEqual(tokenize('|-'), [{ _text: '|-', type: 'table.hr' }])\n\t})\n\n\tit('knows these are not table separators', () => {\n\t\tassert.deepEqual(tokenize('----+---+----|'), [\n\t\t\t{ _text: '----+---+----|', type: 'text', value: '----+---+----|' }\n\t\t])\n\t})\n\n\tit('knows table rows', () => {\n\t\tassert.deepEqual(tokenize('| batman | superman | wonder woman |'), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' batman ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' batman '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' superman ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' superman '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' wonder woman ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' wonder woman '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(\"| hello | world | y'all |\"), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: \" y'all \",\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: \" y'all \"\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(\"   | hello | world | y'all |\"), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' world ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' world '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: \" y'all \",\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: \" y'all \"\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize(\"|    hello |  world   |y'all |\"), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '    hello ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '    hello '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '  world   ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '  world   '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: \"y'all \",\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: \"y'all \"\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t}\n\t\t])\n\t\t// with empty cell\n\t\tassert.deepEqual(tokenize('||  world   | |'), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '  world   ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '  world   '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: ' ',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: ' '\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t}\n\t\t])\n\t})\n\n\tit('knows these are not table rows', () => {\n\t\tassert.deepEqual(tokenize(\" hello | world | y'all |\"), [\n\t\t\t{\n\t\t\t\t_text: \" hello | world | y'all |\",\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: \" hello | world | y'all |\"\n\t\t\t}\n\t\t])\n\t\tassert.deepEqual(tokenize('|+'), [\n\t\t\t{\n\t\t\t\t_text: '|',\n\t\t\t\ttype: 'table.columnSeparator'\n\t\t\t},\n\t\t\t{\n\t\t\t\t_text: '+',\n\t\t\t\ttype: 'text',\n\t\t\t\tvalue: '+'\n\t\t\t}\n\t\t])\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/tokenize/table.ts",
    "content": "import type { Reader } from 'text-kit'\nimport type { Token } from '../types.js'\nimport { tokenize as tokenizeInline } from './inline/index.js'\n\nexport default (reader: Reader): Token[] => {\n\tconst { eat, getChar, jump, endOfLine, indexOf } = reader\n\tconst ws = eat('whitespaces')\n\tconst char = getChar()\n\n\tif (char !== '|') {\n\t\tws && jump(ws.position.start)\n\t\treturn []\n\t}\n\n\tif (getChar(1) === '-') {\n\t\tconst hr = eat('line')\n\t\tconst tokens: Token[] = [{ type: 'table.hr', position: hr.position }]\n\t\tconst nl = eat('newline')\n\t\tif (nl) tokens.push({ type: 'newline', position: nl.position })\n\t\treturn tokens\n\t}\n\n\tconst startColumnSeparator: Token = {\n\t\ttype: 'table.columnSeparator',\n\t\tposition: eat().position\n\t}\n\n\tconst tokens: Token[] = []\n\n\tconst tokCells = (): void => {\n\t\tconst pipe = indexOf('|')\n\t\tconst end = pipe || endOfLine()\n\t\tif (!end) throw new Error(`what is happening: ${end}`)\n\n\t\tconst inline = tokenizeInline(reader.read({ end }))\n\t\ttokens.push(...inline)\n\t\tjump(end)\n\n\t\tif (pipe) {\n\t\t\tconst c = eat('char')\n\t\t\ttokens.push({\n\t\t\t\ttype: 'table.columnSeparator',\n\t\t\t\tposition: c.position\n\t\t\t})\n\t\t\ttokCells()\n\t\t}\n\n\t\tconst nl = eat('newline')\n\t\tif (nl) {\n\t\t\ttokens.push({\n\t\t\t\ttype: 'newline',\n\t\t\t\tposition: nl.position\n\t\t\t})\n\t\t}\n\t}\n\n\ttokCells()\n\treturn [startColumnSeparator, ...tokens]\n}\n"
  },
  {
    "path": "packages/orga/src/types.ts",
    "content": "import type {\n\tNode,\n\tLiteral as UnistLiteral,\n\tParent as UnistParent\n} from 'unist'\n\nexport interface Literal extends UnistLiteral {\n\tvalue: string\n}\n\nexport interface Parent extends UnistParent {\n\tchildren: Content[]\n}\n\nexport type Primitive = string | number | boolean\n\nexport interface Attributes {\n\t[key: string]: Primitive | { [key: string]: Primitive }\n}\n\nexport interface Attributed {\n\tattributes: Attributes\n}\n\nexport interface Timestamp {\n\tdate: Date\n\tend?: Date\n}\n\nexport type Properties = Record<string, PropertyValue>\nexport type Settings = Record<string, PropertyValue>\n\ntype PropertyValue = string | string[] | Record<string, string>\n\nexport type Nodes = Document | Content | Token\n\n// ---- Syntax Tree Nodes ----\nexport interface Document extends Parent {\n\ttype: 'document'\n\tproperties: Properties\n\tchildren: TopLevelContent[]\n}\n\nexport interface Section extends Parent {\n\ttype: 'section'\n\tlevel: number\n\tproperties: Properties\n\tchildren: Content[]\n}\n\n// --- content types ----\nexport type BlockContent =\n\t| Section\n\t| Paragraph\n\t| Block\n\t| Drawer\n\t| Planning\n\t| List\n\t| Table\n\t| HorizontalRule\n\t| Headline\n\t| HTML\n\t| JSX\n\t| Latex\n\ntype TopLevelContent = BlockContent | Keyword | Footnote\n\nexport type Content =\n\t| TopLevelContent\n\t| TableContent\n\t| TableRow\n\t| TableCell\n\t| ListContent\n\t| PhrasingContent\n\nexport interface Footnote extends Parent {\n\ttype: 'footnote'\n\tlabel: string\n}\n\nexport interface Block extends Literal, Attributed {\n\ttype: 'block'\n\tname: string\n\tparams: string[]\n\tchildren: PhrasingContent[] | BlockContent[]\n}\n\nexport interface Latex extends Literal {\n\ttype: 'latex'\n\tname: string\n}\n\nexport interface Drawer extends Literal {\n\ttype: 'drawer'\n\tname: string\n}\n\nexport interface Planning extends Node {\n\ttype: 'planning'\n\tkeyword: string\n\ttimestamp: Timestamp\n}\n\ntype ListContent = ListItem | List\n\nexport interface List extends Parent, Attributed {\n\ttype: 'list'\n\tindent: number\n\tordered: boolean\n\tchildren: ListContent[]\n}\n\ntype TableContent = TableRow | TableRule\n\nexport interface Table extends Parent, Attributed {\n\ttype: 'table'\n\tchildren: TableContent[]\n}\n\nexport interface TableRow extends Parent {\n\ttype: 'table.row'\n\tchildren: TableCell[]\n}\n\nexport interface TableCell extends Parent {\n\ttype: 'table.cell'\n\tchildren: PhrasingContent[]\n}\n\nexport interface ListItem extends Parent {\n\ttype: 'list.item'\n\tindent: number\n\ttag?: string\n\tchildren: PhrasingContent[]\n}\n\nexport interface Headline extends Parent {\n\ttype: 'headline'\n\tlevel: number\n\tkeyword?: string\n\tactionable: boolean\n\tpriority?: string\n\ttags?: string[]\n\tchildren: PhrasingContent[]\n}\n\nexport interface Paragraph extends Parent, Attributed {\n\ttype: 'paragraph'\n\tchildren: PhrasingContent[]\n}\n\nexport interface HTML extends Literal {\n\ttype: 'html'\n}\n\nexport interface JSX extends Literal {\n\ttype: 'jsx'\n}\n\n// ---- Tokens ----\nexport type Token =\n\t| Keyword\n\t| Todo\n\t| Newline\n\t| EmptyLine\n\t| HorizontalRule\n\t| Stars\n\t| Priority\n\t| Tags\n\t| PlanningKeyword\n\t| PlanningTimestamp\n\t| ListItemTag\n\t| ListItemCheckbox\n\t| ListItemBullet\n\t| TableRule\n\t| TableColumnSeparator\n\t| PhrasingContent\n\t| FootnoteLabel\n\t| BlockBegin\n\t| BlockEnd\n\t| LatexBegin\n\t| LatexEnd\n\t| DrawerBegin\n\t| DrawerEnd\n\t| Comment\n\t| Opening\n\t| Closing\n\t| LinkPath\n\nexport type PhrasingContent =\n\t| Text\n\t| Link\n\t| FootnoteReference\n\t| Newline\n\t| EmptyLine\n\t| HTML\n\t| JSX\n\nexport interface HorizontalRule extends Node {\n\ttype: 'hr'\n}\n\nexport interface Newline extends Node {\n\ttype: 'newline'\n}\n\nexport interface EmptyLine extends Node {\n\ttype: 'emptyLine'\n}\n\nexport type Style =\n\t| 'bold'\n\t| 'verbatim'\n\t| 'italic'\n\t| 'strikeThrough'\n\t| 'underline'\n\t| 'code'\n\t| 'math'\n\nexport interface Text extends Literal {\n\ttype: 'text'\n\tstyle?: Style\n}\n\nexport interface Link extends Parent, Attributed {\n\ttype: 'link'\n\tpath: Omit<LinkPath, 'type'>\n\tchildren: PhrasingContent[]\n}\n\nexport interface LinkPath extends Literal {\n\ttype: 'link.path'\n\tprotocol: string\n\tsearch?: string | number\n}\n\nexport type Enclosed = Style | 'link' | 'footnote.reference'\n\nexport interface Opening extends Node {\n\ttype: 'opening'\n\telement: Enclosed\n}\n\nexport interface Closing extends Node {\n\ttype: 'closing'\n\telement: Enclosed\n}\n\n/**\n * A footnote reference, which is either:\n *\n * `[fn:LABEL]` - a plain footnote reference.\n *\n * `[fn:LABEL:DEFINITION]` - an inline footnote definition.\n *\n * `[fn::DEFINITION]` - an anonymous (inline) footnote definition.\n *\n * See https://orgmode.org/worg/dev/org-syntax.html#Footnote_References.\n *\n * If `label` is the empty string, then this is treated as an\n * anonymous footnote.\n *\n * If `children` is empty, then this is considered to not define a new\n * footnote (and in which case, `label` should not be the empty\n * string), if `children` is non-empty, then this is an inline\n * footnote definition.\n */\nexport interface FootnoteReference extends Parent {\n\ttype: 'footnote.reference'\n\tlabel: string\n\tchildren: PhrasingContent[]\n}\n\n// headline tokens\nexport interface Stars extends Node {\n\ttype: 'stars'\n\tlevel: number\n}\n\nexport interface Todo extends Node {\n\ttype: 'todo'\n\tkeyword: string\n\tactionable: boolean\n}\n\nexport interface Priority extends Literal {\n\ttype: 'priority'\n}\n\nexport interface Tags extends Node {\n\ttype: 'tags'\n\ttags: string[]\n}\n\n// block tokens\nexport interface BlockBegin extends Node {\n\ttype: 'block.begin'\n\tname: string\n\tparams: string[]\n}\n\nexport interface BlockEnd extends Node {\n\ttype: 'block.end'\n\tname: string\n}\n\n// drawer tokens\nexport interface DrawerBegin extends Node {\n\ttype: 'drawer.begin'\n\tname: string\n}\n\ninterface DrawerEnd extends Node {\n\ttype: 'drawer.end'\n}\n\nexport interface LatexBegin extends Node {\n\ttype: 'latex.begin'\n\tname: string\n}\n\nexport interface LatexEnd extends Node {\n\ttype: 'latex.end'\n\tname: string\n}\n\ninterface Comment extends Literal {\n\ttype: 'comment'\n}\n\nexport interface Keyword extends Node {\n\ttype: 'keyword'\n\tkey: string\n\tvalue: string\n}\n\nexport interface FootnoteLabel extends Node {\n\ttype: 'footnote.label'\n\tlabel: string\n}\n\nexport interface PlanningKeyword extends Literal {\n\ttype: 'planning.keyword'\n}\n\nexport interface PlanningTimestamp extends UnistLiteral {\n\ttype: 'planning.timestamp'\n\tvalue: Timestamp\n}\n\nexport interface ListItemTag extends Literal {\n\ttype: 'list.item.tag'\n}\n\nexport interface ListItemCheckbox extends Node {\n\ttype: 'list.item.checkbox'\n\tchecked: boolean\n}\n\nexport interface ListItemBullet extends Node {\n\ttype: 'list.item.bullet'\n\tordered: boolean\n\tindent: number\n}\n\nexport interface TableRule extends Node {\n\ttype: 'table.hr'\n}\n\nexport interface TableColumnSeparator extends Node {\n\ttype: 'table.columnSeparator'\n}\n\nexport function isSection(node: Node): node is Section {\n\treturn node.type === 'section'\n}\n\nexport function isParagraph(node: Node): node is Paragraph {\n\treturn node.type === 'paragraph'\n}\n\nexport function isLink(node: Node): node is Link {\n\treturn node.type === 'link'\n}\n\nexport function isFootnoteReference(node: Node): node is FootnoteReference {\n\treturn node.type === 'footnote.reference'\n}\n\nexport function isText(node: Node): node is Text {\n\treturn node.type === 'text'\n}\n\ndeclare module 'unist' {\n\tinterface Data {\n\t\t/** context hash */\n\t\thash?: number | undefined\n\t}\n}\n"
  },
  {
    "path": "packages/orga/src/uri.test.ts",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport parse from './uri'\n\ndescribe('Parsing Link', () => {\n\tit('recon local file', () => {\n\t\tassert.deepEqual(parse(`file:/hello.org`), {\n\t\t\tprotocol: 'file',\n\t\t\tsearch: undefined,\n\t\t\tvalue: '/hello.org'\n\t\t})\n\n\t\tassert.deepEqual(parse(`./hello.org`), {\n\t\t\tprotocol: 'file',\n\t\t\tsearch: undefined,\n\t\t\tvalue: './hello.org'\n\t\t})\n\n\t\tassert.deepEqual(parse(`./hello.org::23`), {\n\t\t\tprotocol: 'file',\n\t\t\tsearch: 23,\n\t\t\tvalue: './hello.org'\n\t\t})\n\t\tassert.deepEqual(parse(`./hello.org::*shopping list`), {\n\t\t\tprotocol: 'file',\n\t\t\tsearch: '*shopping list',\n\t\t\tvalue: './hello.org'\n\t\t})\n\t\tassert.deepEqual(parse(`./hello.org::apple pie`), {\n\t\t\tprotocol: 'file',\n\t\t\tsearch: 'apple pie',\n\t\t\tvalue: './hello.org'\n\t\t})\n\t})\n\n\tit('recon other protocol', () => {\n\t\tassert.deepEqual(parse(`http://google.com`), {\n\t\t\tprotocol: 'http',\n\t\t\tsearch: undefined,\n\t\t\tvalue: 'http://google.com'\n\t\t})\n\t\tassert.deepEqual(parse(`mailto:dawnstar.hu@gmail.com`), {\n\t\t\tprotocol: 'mailto',\n\t\t\tsearch: undefined,\n\t\t\tvalue: 'dawnstar.hu@gmail.com'\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "packages/orga/src/uri.ts",
    "content": "const URL_PATTERN = /(?:([a-z][a-z0-9+.-]*):)?(.*)/i\n\ninterface LinkInfo {\n\tprotocol: string\n\tvalue: string\n\tsearch?: string | number\n}\n\nconst isFilePath = (str: string): boolean => {\n\treturn str && /^\\.{0,2}\\//.test(str)\n}\n\nexport default (link: string): LinkInfo | undefined => {\n\tconst m = URL_PATTERN.exec(link)\n\tif (!m) return undefined\n\tconst protocol = (\n\t\tm[1] || (isFilePath(m[2]) ? `file` : `internal`)\n\t).toLowerCase()\n\tlet value = m[2]\n\tif (/https?/.test(protocol)) {\n\t\tvalue = `${protocol}:${value}`\n\t}\n\tlet search: string | number | undefined\n\tif (protocol === 'file') {\n\t\tconst m = /(.*?)::(.*)/.exec(value)\n\t\tif (m?.[1] && m[2]) {\n\t\t\tvalue = m[1]\n\t\t\tsearch = parseInt(m[2], 10)\n\t\t\tsearch = Number.isInteger(search) ? search : m[2]\n\t\t}\n\t}\n\treturn { protocol, value, search }\n}\n"
  },
  {
    "path": "packages/orga/src/utils.ts",
    "content": "import type { PhrasingContent, Token } from './types.js'\n\nconst matchOperatorsRe = /[|\\\\{}()[\\]^$+*?.]/g\n\nconst escapeRegExp = (str: string): string => {\n\treturn str.replace(matchOperatorsRe, '\\\\$&')\n}\n\nexport { escapeRegExp, escapeRegExp as escape }\n\nexport const clone = (obj: any) => {\n\treturn JSON.parse(JSON.stringify(obj))\n}\n\nexport const isPhrasingContent = (token: Token): token is PhrasingContent => {\n\treturn (\n\t\ttoken.type === 'text' ||\n\t\ttoken.type === 'footnote.reference' ||\n\t\ttoken.type === 'opening' ||\n\t\ttoken.type === 'link' ||\n\t\ttoken.type === 'newline'\n\t)\n}\n"
  },
  {
    "path": "packages/orga/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.esm.json\",\n\t\"compilerOptions\": {\n\t\t\"rootDir\": \"./src\",\n\t\t\"outDir\": \"./dist\"\n\t},\n\t\"include\": [\"./src\"]\n}\n"
  },
  {
    "path": "packages/orga-build/CHANGELOG.md",
    "content": "# orga-build\n\n## 0.9.0\n\n### Minor Changes\n\n- 8b13493: - add exclude config option to skip files from content scanning\n  - decouple Vite's root from the content root (now always cwd)\n\n## 0.8.0\n\n### Minor Changes\n\n- f4b8394: add data endpoint\n\n## 0.7.1\n\n### Patch Changes\n\n- 850bcf9: fix: use native anchor for external links to prevent wouter pushState SecurityError\n\n## 0.7.0\n\n### Minor Changes\n\n- be20652: expose rehypePlugins in orga-build\n\n## 0.6.3\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/rollup@1.3.4\n\n## 0.6.2\n\n### Patch Changes\n\n- 292e2f1: Use the shared virtual client entry in production builds so `styles` are imported, hashed by Vite, and injected from built CSS assets.\n\n## 0.6.1\n\n### Patch Changes\n\n- b2110a4: fix index.html resolution conflict\n\n## 0.6.0\n\n### Minor Changes\n\n- 18c8ed7: implement per-page head injection\n\n## 0.5.4\n\n### Patch Changes\n\n- 20f5a03: fix: render video links as `<video controls>` elements\n\n## 0.5.3\n\n### Patch Changes\n\n- 15434f6: Normalize org file: links to canonical slugs and fix index.org link targets\n\n## 0.5.2\n\n### Patch Changes\n\n- ada31b9: org-build output directly to outDir\n\n## 0.5.1\n\n### Patch Changes\n\n- 23b8f16: make orga-build dev mode to be vite-native\n\n## 0.5.0\n\n### Minor Changes\n\n- 06c6d43: Vit Environment API adoption\n\n## 0.4.0\n\n### Minor Changes\n\n- 3a425ad: update to vite 7 🤞\n\n## 0.3.2\n\n### Patch Changes\n\n- 1bff98b: fix HMR issue\n\n## 0.3.1\n\n### Patch Changes\n\n- abbee9a: add docs and rename orga-build/content to orga-build/client\n\n## 0.3.0\n\n### Minor Changes\n\n- ad0bd0d: Add `orga-build:content` virtual module with `getPages()`, `getPage()`, and `getEntries()` functions for querying content entries. Automatically extracts metadata from org-mode headers (e.g., `#+title:`, `#+date:`) and supports hierarchical path filtering.\n\n## 0.2.7\n\n### Patch Changes\n\n- @orgajs/rollup@1.3.3\n\n## 0.2.6\n\n### Patch Changes\n\n- 6d46012: remove log\n\n## 0.2.5\n\n### Patch Changes\n\n- 70ebb3b: handle image and relative links\n\n## 0.2.4\n\n### Patch Changes\n\n- c3fecf6: resolve react/react-dom/wouter properly\n\n## 0.2.3\n\n### Patch Changes\n\n- c71a873: fix dependency issue\n\n## 0.2.2\n\n### Patch Changes\n\n- 107b375: move react and react-dom to peer dependencies\n\n## 0.2.1\n\n### Patch Changes\n\n- cd8358d: replace react-router with wouter\n\n## 0.2.0\n\n### Minor Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n\n### Patch Changes\n\n- Updated dependencies [60ad38f]\n  - @orgajs/rollup@1.3.2\n  - @orgajs/esbuild@1.1.3\n  - @orgajs/node-loader@1.1.3\n\n## 0.1.4\n\n### Patch Changes\n\n- 27d31bf: remove log\n\n## 0.1.3\n\n### Patch Changes\n\n- e504f45: you can refer to image using relative path now\n\n## 0.1.2\n\n### Patch Changes\n\n- 10e8856: [orga-build] copy assets\n\n## 0.1.1\n\n### Patch Changes\n\n- 7c3c600: fix react resolve issue\n  - @orgajs/esbuild@1.1.2\n  - @orgajs/node-loader@1.1.2\n\n## 0.1.0\n\n### Minor Changes\n\n- 9392c3e: release orga-build\n"
  },
  {
    "path": "packages/orga-build/README.org",
    "content": "#+TITLE: orga-build\n\nA simple tool that builds org-mode files into a website.\n\n* Architecture\n\norga-build is built on top of Vite with a Vite-native architecture. The dev server uses Vite's native =createServer().listen()= pattern (no custom Express wrapper), which ensures maximum compatibility with the Vite ecosystem, including plugins like Cloudflare Workers.\n\n** Key Design Principles\n\n- *Vite-native*: Framework behavior is implemented as Vite plugins, not external server wrappers\n- *Zero-config*: Works with just =.org= files - no =index.html= required\n- *Plugin-driven*: All features are implemented as composable Vite plugins\n\n** Plugin Composition\n\nWhen using orga-build CLI with additional Vite plugins (like Cloudflare Workers), add them to =vitePlugins= in your =orga.config.js=:\n\n#+begin_src javascript\n// orga.config.js\nimport { cloudflare } from '@cloudflare/vite-plugin'\n\nexport default {\n  root: 'pages',\n  // Add external plugins here - orga-build plugins are included automatically\n  vitePlugins: [\n    cloudflare()\n  ]\n}\n#+end_src\n\nNote: Do NOT add =orgaBuildPlugin()= to =vitePlugins= - it's already included by the CLI. Only add external plugins.\n\nFor advanced users integrating directly with Vite (without the orga-build CLI), use =orgaBuildPlugin= in your =vite.config.js=:\n\n#+begin_src javascript\n// vite.config.js (advanced - direct Vite integration)\nimport { cloudflare } from '@cloudflare/vite-plugin'\nimport { orgaBuildPlugin, alias } from 'orga-build'\n\nexport default {\n  plugins: [\n    cloudflare(),\n    ...orgaBuildPlugin({ root: 'pages', containerClass: [] })\n  ],\n  resolve: { alias }\n}\n#+end_src\n\n** Default HTML Template\n\nIf your project doesn't have an =index.html= file, orga-build provides a default template that:\n- Sets up React rendering\n- Enables client-side routing\n- Works in both dev and production builds\n\nTo customize the HTML shell, create your own =index.html= in your project root.\n\n* Installation\n\n#+begin_src bash\nnpm install orga-build\n#+end_src\n\n* Configuration\n\norga-build uses =orga.config.js= (or =orga.config.mjs=) as the primary configuration file. This file should be placed in your project root.\n\n#+begin_src javascript\n// orga.config.js\nexport default {\n  // Directory containing your .org files (default: 'pages')\n  root: 'pages',\n\n  // Output directory for production build (default: 'out')\n  outDir: 'out',\n\n  // CSS class(es) to wrap rendered org content\n  containerClass: ['prose', 'prose-lg'],\n\n  // Global stylesheets — paths relative to orga.config.js (leading / optional).\n  // Injected in dev SSR <head> and imported by the client entry.\n  styles: ['pages/style.css'],\n\n  // Extra rehype plugins appended to orga-build defaults\n  // Useful for syntax highlighting (e.g. rehype-pretty-code).\n  rehypePlugins: [],\n\n  // Additional Vite plugins\n  vitePlugins: [],\n\n  // Glob patterns (relative to root) to exclude from content scanning.\n  // Useful for generated or declaration files that must live inside root\n  // but should not be treated as pages or endpoints.\n  exclude: ['**/*.d.ts']\n}\n#+end_src\n\n** Configuration Options\n\n| Option         | Type              | Default | Description                                                     |\n|----------------+-------------------+---------+-----------------------------------------------------------------|\n| =root=           | =string=            | ='pages'= | Directory containing content files                              |\n| =outDir=         | =string=            | ='out'=   | Output directory for production build                           |\n| =containerClass= | =string \\vert string[]= | =[]=      | CSS class(es) for content wrapper                               |\n| =styles=         | =string[]=          | =[]=      | Stylesheets to inject/import; paths relative to =orga.config.js=  |\n| =exclude=        | =string[]=          | =[]=      | Glob patterns (relative to =root=) excluded from content scanning |\n| =rehypePlugins=  | =PluggableList=     | =[]=      | Extra rehype plugins appended to orga-build defaults            |\n| =vitePlugins=    | =PluginOption[]=    | =[]=      | Additional Vite plugins                                         |\n\n** Syntax Highlighting Example\n\n#+begin_src javascript\nimport rehypePrettyCode from 'rehype-pretty-code'\n\nexport default {\n  rehypePlugins: [[rehypePrettyCode, { theme: 'github-dark' }]]\n}\n#+end_src\n\n* Routing\n\norga-build supports two route types: *page routes* and *endpoint routes*.\n\n** Page Routes\n\nPage routes are discovered from =.org=, =.tsx=, and =.jsx= files.\n\n- =index.org= -> =/=\n- =about.org= -> =/about=\n- =docs/getting-started.tsx= -> =/docs/getting-started=\n\nAt build time, page routes are emitted as HTML:\n\n- =/about= -> =out/about/index.html=\n\n** Endpoint Routes\n\nEndpoint routes are discovered from =.ts=, =.js=, =.mts=, and =.mjs= files where the basename already includes a target extension (for example =rss.xml.ts= or =data.json.ts=).\n\n- =rss.xml.ts= -> =/rss.xml=\n- =nested/feed.xml.ts= -> =/nested/feed.xml=\n- =api/data.json.ts= -> =/api/data.json=\n\nEndpoint modules must export:\n\n#+begin_src ts\nexport async function GET(ctx) {\n  return new Response('ok', {\n    headers: { 'content-type': 'text/plain; charset=utf-8' }\n  })\n}\n#+end_src\n\nAt build time, endpoint routes are emitted to exact filenames:\n\n- =/rss.xml= -> =out/rss.xml=\n- =/api/data.json= -> =out/api/data.json=\n\nRoute conflicts (same final route path) fail fast during dev/build startup.\n\n* TypeScript Setup\n\nIf you're using TypeScript and want type support for the =orga-build:content= virtual module, you need to add a reference to the type definitions.\n\n** Minimal Setup\n\n1. Create a =types.d.ts= file in your project root (or any location):\n\n#+begin_src typescript\n/// <reference types=\"orga-build/client\" />\n#+end_src\n\n2. Ensure your =tsconfig.json= includes this file:\n\n#+begin_src json\n{\n  \"compilerOptions\": {\n    \"module\": \"esnext\",\n    \"moduleResolution\": \"bundler\",\n    \"jsx\": \"react-jsx\"\n  },\n  \"include\": [\"types.d.ts\", \"**/*\"]\n}\n#+end_src\n\nThat's it! TypeScript will now recognize imports from =orga-build:content=.\n\n** Why This is Needed\n\nThe =orga-build:content= module is a \"virtual module\" - it doesn't exist as a physical file but is generated at build time by Vite. The =/// <reference types=\"orga-build/client\" />= directive tells TypeScript to load the type definitions for this virtual module.\n\n* Content Query API\n\norga-build provides an Astro-inspired content query API via the =orga-build:content= virtual module. This allows you to safely query content entries from any page or layout without circular imports.\n\n** Importing\n\n#+begin_src typescript\nimport { getPages, getPage } from 'orga-build:content'\n#+end_src\n\n** API Reference\n\n*** =getPages(path?, filter?)=\n\nGet all content entries matching a path pattern.\n\n*Parameters:*\n- =path= (optional): Path prefix to filter by (e.g., ='writing'=, ='content/writing/2025'=)\n- =filter= (optional): Filter function to further refine results\n\n*Returns:* Array of =ContentEntry= objects\n\n*Examples:*\n\n#+begin_src typescript\n// Get all entries\nconst all = getPages()\n\n// Get all entries in the 'writing' path\nconst writing = getPages('writing')\n\n// Get entries in a nested path\nconst posts2025 = getPages('content/writing/2025')\n\n// Filter out drafts\nconst published = getPages('writing', (entry) => {\n  return entry.data['draft'] !== 'true'\n})\n#+end_src\n\n*** =getPage(idOrSlug, path?)=\n\nGet a single content entry by id or slug.\n\n*Parameters:*\n- =idOrSlug=: The id or slug of the entry to find\n- =path= (optional): Path prefix to search within\n\n*Returns:* =ContentEntry | undefined=\n\n*Examples:*\n\n#+begin_src typescript\n// Get by slug\nconst post = getPage('/writing/the-birth-of-emacsclient')\n\n// Get by id within a path\nconst post = getPage('the-birth-of-emacsclient', 'writing')\n#+end_src\n\n*** =getEntries(refs)=\n\nGet multiple content entries by reference.\n\n*Parameters:*\n- =refs=: Array of references with =id= and optional =path=\n\n*Returns:* Array of =ContentEntry | undefined=\n\n*Examples:*\n\n#+begin_src typescript\nconst entries = getEntries([\n  { id: 'post-1', path: 'writing' },\n  { id: 'post-2', path: 'writing' }\n])\n#+end_src\n\n*** Aliases\n\nFor Astro familiarity:\n- =getCollection= - Alias for =getPages=\n- =getEntry= - Alias for =getPage=\n\n** ContentEntry Type\n\nEach entry has the following structure:\n\n#+begin_src typescript\ninterface ContentEntry {\n  id: string                    // e.g., 'post-name' or 'index'\n  slug: string                  // e.g., '/writing/post-name'\n  path: string                  // e.g., 'writing' or 'content/writing/2025'\n  filePath: string              // absolute source file path\n  ext: 'org' | 'tsx' | 'jsx'   // file extension\n  data: Record<string, unknown> // metadata from org headers\n}\n#+end_src\n\n** Metadata Extraction\n\nFor =.org= files, orga-build automatically extracts metadata from org-mode headers:\n\n#+begin_example\n#+title: My Post\n#+date: 2025-01-15\n#+draft: false\n#+end_example\n\nThis becomes:\n\n#+begin_src typescript\n{\n  data: {\n    title: 'My Post',\n    date: '2025-01-15',\n    draft: 'false'\n  }\n}\n#+end_src\n\nFor =.tsx= and =.jsx= files, the =data= field is currently empty in v1.\n\n** Path Matching Behavior\n\nPath matching works hierarchically:\n\n- =getPages()= - Returns all entries\n- =getPages('writing')= - Returns entries where:\n  - =path = 'writing'=, or\n  - =path= starts with ='writing/'=\n- =getPages('content/writing/2025')= - Returns entries under that specific subtree\n\n*Path Derivation Examples:*\n\n| File Path | Slug | Path | ID |\n|-----------+------+------+----|\n| =pages/writing/foo.org= | =/writing/foo= | =writing= | =foo= |\n| =pages/content/writing/2025/post.org= | =/content/writing/2025/post= | =content/writing/2025= | =post= |\n| =pages/index.org= | =/= | =''= (empty) | =index= |\n| =pages/about.org= | =/about= | =''= (empty) | =about= |\n\n** Example: Blog Index Page\n\n#+begin_src tsx\nimport { getPages } from 'orga-build:content'\n\nexport default function BlogIndex() {\n  const posts = getPages('writing', (entry) => {\n    return entry.data['draft'] !== 'true'\n  }).sort((a, b) => {\n    // Sort by date descending\n    return String(b.data['date']).localeCompare(String(a.data['date']))\n  })\n\n  return (\n    <div>\n      <h1>Blog Posts</h1>\n      <ul>\n        {posts.map((post) => (\n          <li key={post.id}>\n            <a href={post.slug}>{String(post.data['title'])}</a>\n            <span>{String(post.data['date'])}</span>\n          </li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n#+end_src\n\n** Example: Related Posts\n\n#+begin_src tsx\nimport { getPages } from 'orga-build:content'\n\nexport default function Post({ slug }: { slug: string }) {\n  // Get current post\n  const currentPost = getPages().find((p) => p.slug === slug)\n\n  // Get related posts from same path\n  const related = getPages(currentPost?.path).filter(\n    (p) => p.slug !== slug\n  ).slice(0, 3)\n\n  return (\n    <div>\n      <h2>Related Posts</h2>\n      <ul>\n        {related.map((post) => (\n          <li key={post.id}>\n            <a href={post.slug}>{String(post.data['title'])}</a>\n          </li>\n        ))}\n      </ul>\n    </div>\n  )\n}\n#+end_src\n\n* Development\n\n** TODO Items\n\n- resolve relative path in links and images\n- monitor file changes and cache properly\n\n* License\n\nMIT\n"
  },
  {
    "path": "packages/orga-build/cli.js",
    "content": "#!/usr/bin/env node\n\nimport { argv } from 'node:process'\nimport { parseArgs } from 'node:util'\nimport { build } from './lib/build.js'\nimport { loadConfig } from './lib/config.js'\nimport { serve } from './lib/serve.js'\n\nconst { positionals } = parseArgs({\n\targs: argv.slice(2),\n\toptions: {\n\t\twatch: { type: 'boolean', short: 'w' },\n\t\toutDir: { type: 'string', short: 'o', default: '.out' }\n\t},\n\ttokens: true,\n\tallowPositionals: true\n})\n\nconst { config, projectRoot } = await loadConfig(\n\t'orga.config.js',\n\t'orga.config.mjs'\n)\n\nawait (positionals.includes('dev')\n\t? serve(config, 3000, projectRoot)\n\t: build(config, projectRoot))\n"
  },
  {
    "path": "packages/orga-build/index.js",
    "content": "export { build } from './lib/build.js'\nexport { alias, createOrgaBuildConfig, orgaBuildPlugin } from './lib/plugin.js'\n"
  },
  {
    "path": "packages/orga-build/lib/__tests__/build.test.js",
    "content": "import assert from 'node:assert'\nimport fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { after, before, describe, test } from 'node:test'\nimport { fileURLToPath } from 'node:url'\nimport { build } from '../build.js'\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url))\nconst fixtureDir = path.join(__dirname, 'fixtures')\nconst outDir = path.join(__dirname, '.test-output')\n\nfunction markCodeBlocks() {\n\t/**\n\t * @param {any} tree\n\t */\n\treturn (tree) => {\n\t\ttree.children ||= []\n\t\ttree.children.unshift({\n\t\t\ttype: 'element',\n\t\t\ttagName: 'div',\n\t\t\tproperties: { id: 'rehype-plugin-ran' },\n\t\t\tchildren: []\n\t\t})\n\t}\n}\n\ndescribe('orga-build', () => {\n\tbefore(async () => {\n\t\tawait fs.mkdir(fixtureDir, { recursive: true })\n\t\tawait fs.mkdir(path.join(fixtureDir, 'docs'), { recursive: true })\n\t\t// Create minimal fixture\n\t\tawait fs.writeFile(\n\t\t\tpath.join(fixtureDir, 'index.org'),\n\t\t\t`#+title: Test Page\n\n* Hello World\n\nThis is a test page.\n\nHere's [[file:./docs/index.org][index page]].\n\nHere's [[file:more.org][another page]].\n\nHere's [[mailto:hi@unclex.net][send me an email]].\n`\n\t\t)\n\t\tawait fs.writeFile(\n\t\t\tpath.join(fixtureDir, 'docs', 'index.org'),\n\t\t\t'Docs index page.'\n\t\t)\n\t\tawait fs.writeFile(path.join(fixtureDir, 'more.org'), 'Another page.')\n\t\tawait fs.writeFile(\n\t\t\tpath.join(fixtureDir, 'rss.xml.ts'),\n\t\t\t`import { getPages } from 'orga-build:content'\n\nexport function GET() {\n  const pages = getPages()\n  return new Response(\n    '<?xml version=\"1.0\" encoding=\"UTF-8\"?><rss><count>' + pages.length + '</count></rss>',\n    { headers: { 'content-type': 'application/xml; charset=utf-8' } }\n  )\n}\n`\n\t\t)\n\t\tawait fs.writeFile(\n\t\t\tpath.join(fixtureDir, 'style.css'),\n\t\t\t'.global-style-marker { color: rgb(1, 2, 3); }'\n\t\t)\n\t})\n\n\tafter(async () => {\n\t\tawait fs.rm(outDir, { recursive: true, force: true })\n\t\tawait fs.rm(fixtureDir, { recursive: true, force: true })\n\t})\n\n\ttest('builds org files to HTML', async () => {\n\t\tawait build({\n\t\t\troot: fixtureDir,\n\t\t\toutDir: outDir,\n\t\t\tcontainerClass: [],\n\t\t\tvitePlugins: [],\n\t\t\tpreBuild: [],\n\t\t\tpostBuild: []\n\t\t})\n\n\t\t// Check output exists\n\t\tconst indexPath = path.join(outDir, 'index.html')\n\t\tconst indexExists = await fs\n\t\t\t.access(indexPath)\n\t\t\t.then(() => true)\n\t\t\t.catch(() => false)\n\t\tassert.ok(indexExists, 'index.html should exist')\n\n\t\t// Check content\n\t\tconst html = await fs.readFile(indexPath, 'utf-8')\n\t\tassert.ok(html.includes('<title>Test Page</title>'), 'should have title')\n\t\tassert.ok(html.includes('Hello World'), 'should have heading content')\n\t\tassert.ok(\n\t\t\thtml.includes('href=\"/docs\"'),\n\t\t\t'should rewrite docs/index.org to /docs'\n\t\t)\n\t\tassert.ok(html.includes('href=\"/more\"'), 'should rewrite more.org to /more')\n\t\tassert.ok(\n\t\t\thtml.includes('href=\"mailto:hi@unclex.net\"'),\n\t\t\t'should keep mailto protocol in href'\n\t\t)\n\t})\n\n\ttest('generates assets directory', async () => {\n\t\tconst assetsDir = path.join(outDir, 'assets')\n\t\tconst assetsExists = await fs\n\t\t\t.access(assetsDir)\n\t\t\t.then(() => true)\n\t\t\t.catch(() => false)\n\t\tassert.ok(assetsExists, 'assets directory should exist')\n\t})\n\n\ttest('processes configured global styles through vite and injects built css', async () => {\n\t\tconst styleUrl =\n\t\t\t'/' + path.relative(process.cwd(), path.join(fixtureDir, 'style.css'))\n\t\tawait build({\n\t\t\troot: fixtureDir,\n\t\t\toutDir: outDir,\n\t\t\tcontainerClass: [],\n\t\t\tstyles: [styleUrl],\n\t\t\tvitePlugins: [],\n\t\t\tpreBuild: [],\n\t\t\tpostBuild: []\n\t\t})\n\n\t\tconst html = await fs.readFile(path.join(outDir, 'index.html'), 'utf-8')\n\t\tassert.ok(\n\t\t\t!html.includes('href=\"/style.css\"'),\n\t\t\t'should not link raw source css path'\n\t\t)\n\n\t\tconst cssHrefMatch = html.match(/href=\"\\/(assets\\/[^\"]+\\.css)\"/)\n\t\tassert.ok(\n\t\t\tcssHrefMatch,\n\t\t\t'should link built css asset from assets with hashed name'\n\t\t)\n\n\t\tconst builtCssPath = cssHrefMatch[1]\n\t\tconst builtCss = await fs.readFile(path.join(outDir, builtCssPath), 'utf-8')\n\t\tassert.ok(\n\t\t\tbuiltCss.includes('.global-style-marker'),\n\t\t\t'built css should include configured global style content'\n\t\t)\n\t})\n\n\ttest('applies custom rehype plugins from config', async () => {\n\t\tconst fixtureDirRehype = path.join(__dirname, 'fixtures-rehype')\n\t\tconst outDirRehype = path.join(__dirname, '.test-output-rehype')\n\n\t\ttry {\n\t\t\tawait fs.mkdir(fixtureDirRehype, { recursive: true })\n\t\t\tawait fs.writeFile(\n\t\t\t\tpath.join(fixtureDirRehype, 'index.org'),\n\t\t\t\t`#+title: Rehype Test\n\nThis page verifies custom rehype plugins.`\n\t\t\t)\n\n\t\t\tawait build({\n\t\t\t\troot: fixtureDirRehype,\n\t\t\t\toutDir: outDirRehype,\n\t\t\t\tcontainerClass: [],\n\t\t\t\trehypePlugins: [markCodeBlocks],\n\t\t\t\tvitePlugins: [],\n\t\t\t\tpreBuild: [],\n\t\t\t\tpostBuild: []\n\t\t\t})\n\n\t\t\tconst html = await fs.readFile(\n\t\t\t\tpath.join(outDirRehype, 'index.html'),\n\t\t\t\t'utf-8'\n\t\t\t)\n\t\t\tassert.ok(\n\t\t\t\thtml.includes('rehype-plugin-ran'),\n\t\t\t\t'should apply user-provided rehype plugins to rendered HTML'\n\t\t\t)\n\t\t} finally {\n\t\t\tawait fs.rm(outDirRehype, { recursive: true, force: true })\n\t\t\tawait fs.rm(fixtureDirRehype, { recursive: true, force: true })\n\t\t}\n\t})\n\n\ttest('emits endpoint routes with exact output filenames', async () => {\n\t\tawait build({\n\t\t\troot: fixtureDir,\n\t\t\toutDir: outDir,\n\t\t\tcontainerClass: [],\n\t\t\tvitePlugins: [],\n\t\t\tpreBuild: [],\n\t\t\tpostBuild: []\n\t\t})\n\n\t\tconst rss = await fs.readFile(path.join(outDir, 'rss.xml'), 'utf-8')\n\t\tassert.ok(\n\t\t\trss.includes('<rss>') && rss.includes('<count>'),\n\t\t\t'should emit rss.xml from GET endpoint'\n\t\t)\n\t})\n\n\ttest('fails on duplicate route conflicts', async () => {\n\t\tconst fixtureDirConflict = path.join(__dirname, 'fixtures-conflict')\n\t\tconst outDirConflict = path.join(__dirname, '.test-output-conflict')\n\t\ttry {\n\t\t\tawait fs.mkdir(fixtureDirConflict, { recursive: true })\n\t\t\tawait fs.writeFile(path.join(fixtureDirConflict, 'index.org'), 'Home')\n\t\t\tawait fs.writeFile(\n\t\t\t\tpath.join(fixtureDirConflict, 'index.tsx'),\n\t\t\t\t'export default function Page() { return <div>Index</div> }'\n\t\t\t)\n\n\t\t\tawait assert.rejects(\n\t\t\t\t() =>\n\t\t\t\t\tbuild({\n\t\t\t\t\t\troot: fixtureDirConflict,\n\t\t\t\t\t\toutDir: outDirConflict,\n\t\t\t\t\t\tcontainerClass: [],\n\t\t\t\t\t\tvitePlugins: [],\n\t\t\t\t\t\tpreBuild: [],\n\t\t\t\t\t\tpostBuild: []\n\t\t\t\t\t}),\n\t\t\t\t/Route conflict detected/\n\t\t\t)\n\t\t} finally {\n\t\t\tawait fs.rm(outDirConflict, { recursive: true, force: true })\n\t\t\tawait fs.rm(fixtureDirConflict, { recursive: true, force: true })\n\t\t}\n\t})\n})\n"
  },
  {
    "path": "packages/orga-build/lib/app.jsx",
    "content": "import { Link, Route, Switch } from 'wouter'\nimport * as components from '/@orga-build/components'\nimport layouts from '/@orga-build/layouts'\nimport pages from '/@orga-build/pages'\n\nfunction SmartLink({ href, ...props }) {\n\tif (!href || /^([a-z][a-z\\d+\\-.]*:|\\/\\/)/i.test(href)) {\n\t\treturn <a href={href} {...props} />\n\t}\n\treturn <Link href={href} {...props} />\n}\n\nexport function App() {\n\tconst _pages = Object.entries(pages).map(([path, page]) => {\n\t\treturn {\n\t\t\tslug: path,\n\t\t\t...page\n\t\t}\n\t})\n\n\tconst pageRoutes = Object.entries(pages).map(([path, page]) => {\n\t\tconst layoutIds = Object.keys(layouts)\n\t\t\t.filter((key) => path.startsWith(key))\n\t\t\t.sort((a, b) => -a.localeCompare(b))\n\t\tlet element = (\n\t\t\t<page.default\n\t\t\t\tkey={path}\n\t\t\t\tcomponents={{ ...components, Link, a: SmartLink }}\n\t\t\t/>\n\t\t)\n\t\tfor (const layoutId of layoutIds) {\n\t\t\tconst Layout = layouts[layoutId]\n\t\t\telement = (\n\t\t\t\t<Layout title={page.title} slug={path} pages={_pages} {...page}>\n\t\t\t\t\t{element}\n\t\t\t\t</Layout>\n\t\t\t)\n\t\t}\n\t\treturn {\n\t\t\tpath,\n\t\t\telement\n\t\t}\n\t})\n\n\treturn (\n\t\t<Switch>\n\t\t\t{pageRoutes.map((route) => {\n\t\t\t\treturn (\n\t\t\t\t\t<Route key={`r-${route.path}`} path={route.path}>\n\t\t\t\t\t\t{route.element}\n\t\t\t\t\t</Route>\n\t\t\t\t)\n\t\t\t})}\n\t\t</Switch>\n\t)\n}\n"
  },
  {
    "path": "packages/orga-build/lib/build.js",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\nimport { fileURLToPath, pathToFileURL } from 'node:url'\nimport { createBuilder } from 'vite'\nimport { resolveEndpointResponse } from './endpoint.js'\nimport { emptyDir, ensureDir, exists } from './fs.js'\nimport { alias, createOrgaBuildConfig } from './plugin.js'\nimport { escapeHtml } from './util.js'\nimport { appEntryId } from './vite.js'\n\n// Re-export alias for backwards compatibility\nexport { alias }\n\nconst ssrEntry = fileURLToPath(new URL('./ssr.jsx', import.meta.url))\nconst defaultIndexHtml = fileURLToPath(new URL('./index.html', import.meta.url))\n\n/**\n * @param {import('./config.js').Config} config\n * @param {string} [projectRoot]\n */\nexport async function build(\n\t{\n\t\toutDir,\n\t\troot,\n\t\tcontainerClass,\n\t\tstyles = [],\n\t\trehypePlugins = [],\n\t\tvitePlugins = [],\n\t\texclude = []\n\t},\n\tprojectRoot = process.cwd()\n) {\n\tawait emptyDir(outDir)\n\tconst ssrOutDir = path.join(outDir, '.ssr')\n\tconst clientOutDir = outDir\n\n\tconst { plugins, resolve } = createOrgaBuildConfig({\n\t\troot,\n\t\toutDir,\n\t\tcontainerClass,\n\t\tstyles,\n\t\trehypePlugins,\n\t\tvitePlugins,\n\t\texclude\n\t})\n\n\t// Shared config with environment-specific build settings\n\tconst builder = await createBuilder({\n\t\tplugins,\n\t\tresolve,\n\t\tssr: { noExternal: true },\n\t\tenvironments: {\n\t\t\tssr: {\n\t\t\t\tbuild: {\n\t\t\t\t\tssr: true,\n\t\t\t\t\toutDir: ssrOutDir,\n\t\t\t\t\tcssCodeSplit: false,\n\t\t\t\t\temptyOutDir: true,\n\t\t\t\t\tminify: false,\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: ssrEntry,\n\t\t\t\t\t\toutput: {\n\t\t\t\t\t\t\tentryFileNames: '[name].mjs',\n\t\t\t\t\t\t\tchunkFileNames: '[name]-[hash].mjs'\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tclient: {\n\t\t\t\tbuild: {\n\t\t\t\t\toutDir: clientOutDir,\n\t\t\t\t\tcssCodeSplit: false,\n\t\t\t\t\temptyOutDir: false,\n\t\t\t\t\tassetsDir: 'assets',\n\t\t\t\t\trollupOptions: {\n\t\t\t\t\t\tinput: appEntryId,\n\t\t\t\t\t\tpreserveEntrySignatures: 'allow-extension'\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t})\n\n\t// Build SSR first to get render function and pages\n\tconsole.log('preparing ssr bundle...')\n\tawait builder.build(builder.environments.ssr)\n\n\tconst {\n\t\trender,\n\t\tpages,\n\t\tendpoints = {}\n\t} = await import(pathToFileURL(path.join(ssrOutDir, 'ssr.mjs')).toString())\n\n\t// Build client bundle\n\tconst _clientResult = await builder.build(builder.environments.client)\n\n\t// Normalize build result to single RollupOutput\n\tconst clientOutput = Array.isArray(_clientResult)\n\t\t? _clientResult[0].output\n\t\t: 'output' in _clientResult\n\t\t\t? _clientResult.output\n\t\t\t: null\n\tif (!clientOutput) throw new Error('Unexpected client build result')\n\n\t/* --- get from client bundle result: entry chunk, css chunks --- */\n\tconst entryChunk = clientOutput.find(\n\t\t(/** @type {any} */ c) => c.type === 'chunk' && c.isEntry\n\t)\n\n\tconst cssChunks = clientOutput.filter(\n\t\t(/** @type {any} */ c) => c.type === 'asset' && c.fileName.endsWith('.css')\n\t)\n\n\t/* --- get html template, inject entry js and css --- */\n\t// Check for user's index.html in project root, otherwise use default\n\tconst userIndexPath = path.join(projectRoot, 'index.html')\n\tconst indexHtmlPath = (await exists(userIndexPath))\n\t\t? userIndexPath\n\t\t: defaultIndexHtml\n\tconst template = await fs.readFile(indexHtmlPath, { encoding: 'utf-8' })\n\t/* --- for each page path, render html using render function from ssr bundle, and inject the right css  --- */\n\tconst pagePaths = Object.keys(pages)\n\tawait Promise.all(\n\t\tpagePaths.map(async (pagePath) => {\n\t\t\tconst html = renderHTML(pagePath)\n\t\t\tconst writePath = path.join(\n\t\t\t\tclientOutDir,\n\t\t\t\tpagePath.replace(/^\\//, ''),\n\t\t\t\t'index.html'\n\t\t\t)\n\t\t\tawait ensureDir(path.dirname(writePath))\n\t\t\tawait fs.writeFile(writePath, html)\n\t\t})\n\t)\n\n\tconst endpointPaths = Object.keys(endpoints)\n\tawait Promise.all(\n\t\tendpointPaths.map(async (route) => {\n\t\t\tconst endpointModule = endpoints[route]\n\t\t\tconst ctx = {\n\t\t\t\turl: new URL(`http://localhost${route}`),\n\t\t\t\tparams: {},\n\t\t\t\tmode: /** @type {'build'} */ ('build'),\n\t\t\t\troute: { route }\n\t\t\t}\n\n\t\t\tconst response = await resolveEndpointResponse(endpointModule, ctx, 'GET')\n\t\t\tif (response.status < 200 || response.status >= 300) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Endpoint route \"${route}\" returned non-2xx status during build: ${response.status}`\n\t\t\t\t)\n\t\t\t}\n\n\t\t\tconst bytes = Buffer.from(await response.arrayBuffer())\n\t\t\tconst writePath = path.join(clientOutDir, route.replace(/^\\//, ''))\n\t\t\tawait ensureDir(path.dirname(writePath))\n\t\t\tawait fs.writeFile(writePath, bytes)\n\t\t})\n\t)\n\n\tawait fs.rm(ssrOutDir, { recursive: true })\n\n\treturn\n\n\t// ---------- the end ----------\n\n\t/**\n\t * @param {string} pagePath\n\t */\n\tfunction renderHTML(pagePath) {\n\t\tconst content = render(pagePath)\n\t\tconst ssr = {\n\t\t\troutePath: pagePath\n\t\t}\n\t\tlet html = template.replace(\n\t\t\t'<div id=\"root\"></div>',\n\t\t\t`\n\t\t<script>window._ssr=${JSON.stringify(ssr)};</script>\n\t\t<div id=\"root\">${content}</div>\n\t\t`\n\t\t)\n\t\tconst css = cssChunks\n\t\t\t.map(\n\t\t\t\t(/** @type {any} */ c) =>\n\t\t\t\t\t`<link rel=\"stylesheet\" href=\"/${c.fileName}\">`\n\t\t\t)\n\t\t\t.join('\\n')\n\t\thtml = html.replace(\n\t\t\t'<script type=\"module\" src=\"/@orga-build/main.js\"></script>',\n\t\t\t`<script type=\"module\" src=\"/${entryChunk?.fileName}\"></script>`\n\t\t)\n\n\t\thtml = html.replace('</head>', `${css}</head>`)\n\n\t\tconst page = pages[pagePath]\n\t\tif (page) {\n\t\t\thtml = html.replace(/%orga\\.(\\w+)%/g, (_, key) => {\n\t\t\t\tconst value = page[key] ?? ''\n\t\t\t\treturn escapeHtml(String(value))\n\t\t\t})\n\t\t}\n\n\t\treturn html\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/lib/components.js",
    "content": "export { Link } from 'wouter'\n"
  },
  {
    "path": "packages/orga-build/lib/config.js",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * @typedef {Object} Config\n * @property {string} outDir\n * @property {string} root\n * @property {string[]} preBuild\n * @property {string[]} postBuild\n * @property {import('vite').PluginOption[]} vitePlugins - Array of Vite plugins\n * @property {string[]|string} containerClass\n * @property {string[]} [styles] - Global stylesheet URLs injected in dev SSR and imported by client entry\n * @property {import('unified').PluggableList} [rehypePlugins] - Extra rehype plugins appended to orga-build defaults\n * @property {string[]} [exclude] - Glob patterns for files to exclude from content scanning\n */\n\n/** @type {Config} */\nconst defaultConfig = {\n\toutDir: '.out',\n\troot: '.',\n\tpreBuild: [],\n\tpostBuild: [],\n\tvitePlugins: [],\n\tcontainerClass: [],\n\tstyles: [],\n\trehypePlugins: [],\n\texclude: []\n}\n\n/**\n * @param {string[]} files\n * @returns {Promise<{ config: Config, projectRoot: string }>}\n */\nexport async function loadConfig(...files) {\n\tconst cwd = process.cwd()\n\n\t/**\n\t * @param {string} value\n\t */\n\tconst resolveConfigPath = (value) =>\n\t\tpath.isAbsolute(value) ? value : path.resolve(cwd, value)\n\n\tlet result = { ...defaultConfig }\n\tlet configPath = null\n\n\tfor (const file of files) {\n\t\tconst filePath = path.join(cwd, file)\n\n\t\ttry {\n\t\t\tawait fs.access(filePath, fs.constants.F_OK)\n\t\t} catch {\n\t\t\t// File doesn't exist, try next\n\t\t\tcontinue\n\t\t}\n\n\t\ttry {\n\t\t\tconst module = await import(filePath)\n\t\t\t// Support both default export (recommended) and named exports\n\t\t\tconst config = module.default || module\n\t\t\tresult = { ...defaultConfig, ...config }\n\t\t\tconfigPath = filePath\n\t\t\tbreak\n\t\t} catch (err) {\n\t\t\t// Config file exists but has errors\n\t\t\tconsole.error(`Error loading config from ${file}:`, err)\n\t\t}\n\t}\n\n\tresult.root = resolveConfigPath(result.root)\n\tresult.outDir = resolveConfigPath(result.outDir)\n\tconst styles = result.styles\n\tresult.styles = Array.isArray(styles)\n\t\t? styles\n\t\t\t\t.filter((v) => typeof v === 'string')\n\t\t\t\t.map((v) => '/' + v.replace(/^\\/+/, ''))\n\t\t: []\n\treturn {\n\t\tconfig: result,\n\t\tprojectRoot: configPath ? path.dirname(configPath) : cwd\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/lib/content.d.ts",
    "content": "declare module 'orga-build:content' {\n\texport interface ContentEntry {\n\t\tid: string\n\t\tslug: string\n\t\tpath: string\n\t\tfilePath: string\n\t\text: 'org' | 'tsx' | 'jsx'\n\t\tdata: Record<string, unknown>\n\t}\n\n\t/**\n\t * Get all content entries matching a path pattern\n\t * @param path - Optional path prefix to filter by (e.g., 'writing', 'content/writing/2025')\n\t * @param filter - Optional filter function to further refine results\n\t * @returns Array of matching content entries\n\t */\n\texport function getPages(\n\t\tpath?: string,\n\t\tfilter?: (entry: ContentEntry) => boolean\n\t): ContentEntry[]\n\n\t/**\n\t * Get a single content entry by id or slug\n\t * @param idOrSlug - The id or slug of the entry to find\n\t * @param path - Optional path prefix to search within\n\t * @returns The matching content entry or undefined\n\t */\n\texport function getPage(\n\t\tidOrSlug: string,\n\t\tpath?: string\n\t): ContentEntry | undefined\n\n\t/**\n\t * Get multiple content entries by reference\n\t * @param refs - Array of references with id and optional path\n\t * @returns Array of matching content entries (may include undefined)\n\t */\n\texport function getEntries(\n\t\trefs: Array<{ path?: string; id: string }>\n\t): Array<ContentEntry | undefined>\n\n\t/**\n\t * Alias for getPages\n\t */\n\texport const getCollection: typeof getPages\n\n\t/**\n\t * Alias for getPage\n\t */\n\texport const getEntry: typeof getPage\n}\n"
  },
  {
    "path": "packages/orga-build/lib/csr.jsx",
    "content": "import { createRoot } from 'react-dom/client'\nimport { Router } from 'wouter'\nimport { App } from './app.jsx'\n\nconst container = document.getElementById('root')\nconst root = createRoot(container)\nroot.render(\n\t<Router>\n\t\t<App />\n\t</Router>\n)\n"
  },
  {
    "path": "packages/orga-build/lib/endpoint.js",
    "content": "/**\n * @typedef {Object} EndpointContext\n * @property {URL} url\n * @property {Record<string, string>} params\n * @property {'dev' | 'build'} mode\n * @property {{ route: string }} route\n */\n\n/**\n * @param {Record<string, any>} endpointModule\n * @param {EndpointContext} ctx\n * @param {string} method\n * @returns {Promise<Response>}\n */\nexport async function resolveEndpointResponse(\n\tendpointModule,\n\tctx,\n\tmethod = 'GET'\n) {\n\tconst route = ctx.route.route\n\n\tif (method === 'HEAD' && typeof endpointModule.HEAD === 'function') {\n\t\tconst res = await endpointModule.HEAD(ctx)\n\t\tif (!(res instanceof Response))\n\t\t\tthrow new Error(`Endpoint route \"${route}\" HEAD must return Response`)\n\t\treturn res\n\t}\n\n\tif (typeof endpointModule.GET !== 'function') {\n\t\tthrow new Error(\n\t\t\t`Endpoint route \"${route}\" must export GET(ctx) returning Response`\n\t\t)\n\t}\n\n\tconst res = await endpointModule.GET(ctx)\n\tif (!(res instanceof Response)) {\n\t\tthrow new Error(`Endpoint route \"${route}\" GET must return Response`)\n\t}\n\n\tif (method === 'HEAD') {\n\t\treturn new Response(null, {\n\t\t\tstatus: res.status,\n\t\t\tstatusText: res.statusText,\n\t\t\theaders: new Headers(res.headers)\n\t\t})\n\t}\n\n\treturn res\n}\n"
  },
  {
    "path": "packages/orga-build/lib/files.js",
    "content": "import { readFile } from 'node:fs/promises'\nimport path from 'node:path'\nimport { globby } from 'globby'\nimport { getSettings } from 'orga'\n\n/**\n * @typedef {Object} Page\n * @property {string} dataPath\n * @property {string} [title]\n *   Path to the page data file\n */\n\n/**\n * @typedef {Object} EndpointRoute\n * @property {string} route\n * @property {string} dataPath\n */\n\n/**\n * @typedef {Object} ContentEntry\n * @property {string} id\n * @property {string} slug\n * @property {string} path\n * @property {string} filePath\n * @property {'org' | 'tsx' | 'jsx'} ext\n * @property {Record<string, unknown>} data\n */\n\n/**\n * Extract file extension from file path\n * @param {string} filePath\n * @returns {'org' | 'tsx' | 'jsx'}\n */\nfunction getFileExtension(filePath) {\n\tconst match = filePath.match(/\\.(org|tsx|jsx)$/)\n\treturn /** @type {'org' | 'tsx' | 'jsx'} */ (match ? match[1] : 'org')\n}\n\n/**\n * Derive content path from slug\n * @param {string} slug - e.g. '/writing/foo', '/content/writing/2025/post', '/'\n * @returns {string} - e.g. 'writing', 'content/writing/2025', ''\n */\nfunction getContentPath(slug) {\n\t// Remove leading slash\n\tlet normalized = slug.replace(/^\\/+/, '')\n\t// Remove trailing slash\n\tnormalized = normalized.replace(/\\/+$/, '')\n\n\t// If root page, return empty string\n\tif (!normalized) {\n\t\treturn ''\n\t}\n\n\t// Get all segments except the last one (the file name)\n\tconst segments = normalized.split('/')\n\tif (segments.length === 1) {\n\t\t// Single segment like '/about' -> path is empty (root level)\n\t\treturn ''\n\t}\n\n\t// Multiple segments like '/writing/foo' -> path is 'writing'\n\treturn segments.slice(0, -1).join('/')\n}\n\n/**\n * Derive content id from slug\n * @param {string} slug - e.g. '/writing/foo', '/writing', '/'\n * @returns {string} - e.g. 'foo', 'writing', 'index'\n */\nfunction getContentId(slug) {\n\t// Remove leading and trailing slashes\n\tconst normalized = slug.replace(/^\\/+/, '').replace(/\\/+$/, '')\n\n\t// If root page, return 'index'\n\tif (!normalized) {\n\t\treturn 'index'\n\t}\n\n\t// Get last segment\n\tconst segments = normalized.split('/')\n\treturn segments[segments.length - 1] || 'index'\n}\n\n/**\n * @param {string} dir\n * @param {object} [options]\n * @param {string} [options.outDir] - Output directory to exclude from file discovery\n * @param {string[]} [options.exclude] - Additional glob patterns to exclude from file discovery\n */\nexport function setup(dir, { outDir, exclude = [] } = {}) {\n\tconst outDirRelative = outDir ? path.relative(dir, outDir) : null\n\t// Only exclude outDir if it's inside the root (not an external path like ../out)\n\tconst outDirExclude =\n\t\toutDirRelative && !outDirRelative.startsWith('..')\n\t\t\t? `!${outDirRelative}/**`\n\t\t\t: null\n\n\tconst discoveredRoutes = cache(async function () {\n\t\tconst files = await globby(\n\t\t\t[\n\t\t\t\t'**/*.{org,tsx,jsx,ts,js,mts,mjs}',\n\t\t\t\t'!**/_*/**',\n\t\t\t\t'!**/_*',\n\t\t\t\t'!**/.*/**',\n\t\t\t\t'!**/.*',\n\t\t\t\t'!node_modules/**',\n\t\t\t\t...(outDirExclude ? [outDirExclude] : []),\n\t\t\t\t...exclude.map((p) => `!${p}`)\n\t\t\t],\n\t\t\t{ cwd: dir }\n\t\t)\n\n\t\t/** @type {Record<string, Page>} */\n\t\tconst pages = {}\n\t\t/** @type {Record<string, EndpointRoute>} */\n\t\tconst endpoints = {}\n\t\t/** @type {Map<string, { sourceType: 'page' | 'endpoint', filePath: string }>} */\n\t\tconst routeOwners = new Map()\n\n\t\tfor (const file of files) {\n\t\t\tconst absolutePath = path.join(dir, file)\n\t\t\tconst pageSlug = getPageSlugFromFilePath(file)\n\t\t\tconst endpointRoute = getEndpointRouteFromFilePath(file)\n\n\t\t\tif (pageSlug) {\n\t\t\t\tassertUniqueRoute(routeOwners, pageSlug, 'page', absolutePath)\n\t\t\t\tpages[pageSlug] = { dataPath: absolutePath }\n\t\t\t}\n\n\t\t\tif (endpointRoute) {\n\t\t\t\tassertUniqueRoute(routeOwners, endpointRoute, 'endpoint', absolutePath)\n\t\t\t\tendpoints[endpointRoute] = {\n\t\t\t\t\troute: endpointRoute,\n\t\t\t\t\tdataPath: absolutePath\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { pages, endpoints }\n\t})\n\n\tconst pages = cache(async function () {\n\t\tconst routes = await discoveredRoutes()\n\t\treturn routes.pages\n\t})\n\n\tconst endpoints = cache(async function () {\n\t\tconst routes = await discoveredRoutes()\n\t\treturn routes.endpoints\n\t})\n\n\tconst layouts = cache(async function () {\n\t\tconst layoutFiles = await globby(\n\t\t\t[\n\t\t\t\t'**/_layout.{tsx,jsx}',\n\t\t\t\t'!**/.*/**',\n\t\t\t\t'!**/.*',\n\t\t\t\t'!node_modules/**',\n\t\t\t\t...(outDirExclude ? [outDirExclude] : []),\n\t\t\t\t...exclude.map((p) => `!${p}`)\n\t\t\t],\n\t\t\t{\n\t\t\t\tcwd: dir\n\t\t\t}\n\t\t)\n\n\t\treturn layoutFiles.reduce(\n\t\t\t(/** @type {Record<string, string>} */ result, file) => {\n\t\t\t\tconst layoutSlug = path.dirname(getSlugFromContentFilePath(file))\n\t\t\t\tresult[layoutSlug] = path.join(dir, file)\n\t\t\t\treturn result\n\t\t\t},\n\t\t\t/** @type {Record<string, string>} */ {}\n\t\t)\n\t})\n\n\tconst components = cache(async function () {\n\t\tconst files = await globby(\n\t\t\t[\n\t\t\t\t'_components.{tsx,jsx}',\n\t\t\t\t'!**/.*/**',\n\t\t\t\t'!**/.*',\n\t\t\t\t'!node_modules/**',\n\t\t\t\t...(outDirExclude ? [outDirExclude] : []),\n\t\t\t\t...exclude.map((p) => `!${p}`)\n\t\t\t],\n\t\t\t{\n\t\t\t\tcwd: dir\n\t\t\t}\n\t\t)\n\t\treturn files[0] ? path.join(dir, files[0]) : null\n\t})\n\n\tconst contentEntries = cache(async function () {\n\t\tconst allPages = await pages()\n\t\t/** @type {ContentEntry[]} */\n\t\tconst entries = []\n\n\t\tfor (const [slug, pageData] of Object.entries(allPages)) {\n\t\t\tconst filePath = pageData.dataPath\n\t\t\tconst ext = getFileExtension(filePath)\n\n\t\t\t// Derive path from directory structure\n\t\t\tconst derivedPath = getContentPath(slug)\n\n\t\t\t// Derive id from the slug (last segment or 'index')\n\t\t\tconst id = getContentId(slug)\n\n\t\t\t/** @type {Record<string, unknown>} */\n\t\t\tlet data = {}\n\n\t\t\t// Extract metadata from .org files\n\t\t\tif (ext === 'org') {\n\t\t\t\ttry {\n\t\t\t\t\tconst content = await readFile(filePath, 'utf-8')\n\t\t\t\t\tdata = getSettings(content)\n\t\t\t\t} catch (/** @type {any} */ error) {\n\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t`Failed to read metadata from ${filePath}:`,\n\t\t\t\t\t\terror?.message || error\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tentries.push({\n\t\t\t\tid,\n\t\t\t\tslug,\n\t\t\t\tpath: derivedPath,\n\t\t\t\tfilePath,\n\t\t\t\text,\n\t\t\t\tdata\n\t\t\t})\n\t\t}\n\n\t\treturn entries\n\t})\n\n\tconst files = {\n\t\tpages,\n\t\tpage,\n\t\tendpoints,\n\t\tendpoint,\n\t\tcomponents,\n\t\tlayouts,\n\t\tcontentEntries,\n\t\tinvalidate() {\n\t\t\tdiscoveredRoutes.invalidate()\n\t\t\tpages.invalidate()\n\t\t\tendpoints.invalidate()\n\t\t\tlayouts.invalidate()\n\t\t\tcomponents.invalidate()\n\t\t\tcontentEntries.invalidate()\n\t\t}\n\t}\n\n\treturn files\n\n\t/** @param {string} slug */\n\tasync function page(slug) {\n\t\tconst all = await pages()\n\t\treturn all[slug]\n\t}\n\n\t/** @param {string} route */\n\tasync function endpoint(route) {\n\t\tconst all = await endpoints()\n\t\treturn all[route]\n\t}\n}\n\n/**\n * Creates a cached version of an async function that will only execute once\n * and return the cached result on subsequent calls. The returned function\n * also has an `invalidate()` method to clear the cache.\n *\n * @template T\n * @param {() => Promise<T>} fn - The async function to cache\n * @returns {(() => Promise<T>) & { invalidate: () => void }}\n */\nfunction cache(fn) {\n\tlet settled = false\n\t/** @type {T | undefined} */\n\tlet value\n\t/** @returns {Promise<T>} */\n\tasync function cached() {\n\t\tif (!settled) {\n\t\t\tvalue = await fn()\n\t\t\tsettled = true\n\t\t}\n\t\treturn /** @type {T} */ (value)\n\t}\n\tcached.invalidate = function () {\n\t\tsettled = false\n\t\tvalue = undefined\n\t}\n\treturn cached\n}\n\n/**\n * Convert a content file path (relative to content root) to the canonical page slug.\n * @param {string} contentFilePath\n */\nexport function getSlugFromContentFilePath(contentFilePath) {\n\tconst normalizedFilePath = contentFilePath.replace(/\\\\/g, '/')\n\tlet slug = normalizedFilePath.replace(/\\.(org|md|mdx|js|jsx|ts|tsx)$/, '')\n\tslug = slug.replace(/index$/, '')\n\t// remove trailing slash\n\tslug = slug.replace(/\\/$/, '')\n\t// ensure starting slash\n\tslug = slug.replace(/^\\//, '')\n\tslug = `/${slug}`\n\n\t// turn [id] into :id\n\t// so that react-router can recognize it as url params\n\t// pagePublicPath = pagePublicPath.replace(\n\t// \t/\\[(.*?)\\]/g,\n\t// \t(_, paramName) => `:${paramName}`\n\t// )\n\n\treturn slug\n}\n\n/**\n * @param {string} filePath\n * @returns {string|null}\n */\nfunction getPageSlugFromFilePath(filePath) {\n\tif (!/\\.(org|tsx|jsx)$/.test(filePath)) {\n\t\treturn null\n\t}\n\treturn getSlugFromContentFilePath(filePath)\n}\n\n/**\n * @param {string} filePath\n * @returns {string|null}\n */\nfunction getEndpointRouteFromFilePath(filePath) {\n\tif (!/\\.(ts|js|mts|mjs)$/.test(filePath)) {\n\t\treturn null\n\t}\n\n\tconst normalizedFilePath = filePath.replace(/\\\\/g, '/')\n\tconst targetPath = normalizedFilePath.replace(/\\.(ts|js|mts|mjs)$/, '')\n\tconst basename = path.posix.basename(targetPath)\n\n\t// Endpoint files must carry a target extension: rss.xml.ts, data.json.ts, etc.\n\tif (!basename.includes('.')) {\n\t\treturn null\n\t}\n\n\treturn `/${targetPath.replace(/^\\/+/, '')}`\n}\n\n/**\n * @param {Map<string, { sourceType: 'page' | 'endpoint', filePath: string }>} routeOwners\n * @param {string} route\n * @param {'page' | 'endpoint'} sourceType\n * @param {string} filePath\n */\nfunction assertUniqueRoute(routeOwners, route, sourceType, filePath) {\n\tconst existing = routeOwners.get(route)\n\tif (existing) {\n\t\tthrow new Error(\n\t\t\t`Route conflict detected for \"${route}\"\\n- ${existing.sourceType}: ${existing.filePath}\\n- ${sourceType}: ${filePath}`\n\t\t)\n\t}\n\trouteOwners.set(route, { sourceType, filePath })\n}\n"
  },
  {
    "path": "packages/orga-build/lib/fs.js",
    "content": "import fs from 'node:fs/promises'\nimport path from 'node:path'\n\n/**\n * Resolves a path to an absolute path, even if it's already absolute\n * @param {string} rootPath - The path to resolve\n * @returns {string} - The absolute path\n */\nexport function resolvePath(rootPath) {\n\tif (!rootPath) {\n\t\treturn process.cwd()\n\t}\n\n\t// If it's already absolute, return it as is\n\tif (path.isAbsolute(rootPath)) {\n\t\treturn rootPath\n\t}\n\n\t// Otherwise, resolve it relative to the current working directory\n\treturn path.resolve(process.cwd(), rootPath)\n}\n\n/**\n * @param {string} path\n * @returns {Promise<boolean>}\n */\nexport async function exists(path) {\n\ttry {\n\t\tawait fs.access(path)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * @param {string} dir\n * @returns {Promise<void>}\n */\nexport async function emptyDir(dir) {\n\t/** @type {string[]} */\n\tlet items = []\n\ttry {\n\t\titems = await fs.readdir(dir)\n\t} catch {\n\t\tawait fs.mkdir(dir, { recursive: true })\n\t}\n\n\tawait Promise.all(\n\t\titems.map((item) => fs.rm(`${dir}/${item}`, { recursive: true }))\n\t)\n}\n\n/**\n * @param {string} path\n */\nexport async function ensureDir(path) {\n\ttry {\n\t\tawait fs.mkdir(path, { recursive: true })\n\t} catch (/** @type{any} */ e) {\n\t\tif (e && typeof e === 'object' && 'code' in e && e.code !== 'EEXIST') {\n\t\t\tthrow e\n\t\t}\n\t}\n}\n\n/**\n * @param {string} src\n * @param {string} dest\n */\nexport async function copy(src, dest) {\n\tawait fs.mkdir(dest, { recursive: true })\n\tawait fs.cp(src, dest, { recursive: true })\n}\n"
  },
  {
    "path": "packages/orga-build/lib/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n\t<meta charset=\"UTF-8\"/>\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"/>\n\t<title>%orga.title%</title>\n</head>\n<body>\n<div id=\"root\"></div>\n<script type=\"module\" src=\"/@orga-build/main.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "packages/orga-build/lib/orga.js",
    "content": "/**\n * @import {Root as HastTree} from 'hast'\n */\nimport path from 'node:path'\nimport _orga from '@orgajs/rollup'\nimport { visitParents } from 'unist-util-visit-parents'\nimport { getSlugFromContentFilePath } from './files.js'\n\n/**\n * @param {Object} options\n * @param {string|string[]} options.containerClass - CSS class name(s) to wrap the rendered content\n * @param {string} options.root - Root directory for content files\n * @param {import('unified').PluggableList} [options.rehypePlugins] - Extra rehype plugins appended to defaults\n */\nexport function setupOrga({ containerClass, root, rehypePlugins = [] }) {\n\treturn _orga({\n\t\trehypePlugins: [\n\t\t\t[rehypeWrap, { className: containerClass }],\n\t\t\t[rewriteOrgFileLinks, { root }],\n\t\t\tmediaAssets,\n\t\t\t...rehypePlugins\n\t\t]\n\t})\n}\n\n// --- plugins ---\n\nfunction mediaAssets() {\n\t/**\n\t * @param {any} tree\n\t */\n\treturn function (tree) {\n\t\t/** @type {Record<string, string>} */\n\t\tconst imports = {}\n\t\tvisitParents(tree, [{ tagName: 'img' }, { tagName: 'video' }], (node) => {\n\t\t\tnode.type = 'jsx'\n\t\t\tconst { src, ...rest } = node.properties\n\t\t\tif (typeof src !== 'string') return\n\t\t\tif (src.startsWith('http')) return\n\t\t\tconst tagName = node.tagName\n\t\t\tif (!imports[src]) imports[src] = `asset_${genId()}`\n\t\t\tconst name = imports[src]\n\t\t\tconst attrs = Object.entries(rest)\n\t\t\t\t.filter(([, v]) => v !== undefined && v !== false)\n\t\t\t\t.map(([k, v]) => (v === true ? k : `${k}='${v}'`))\n\t\t\t\t.join(' ')\n\t\t\tnode.value = `<${tagName} src={${name}}${attrs ? ` ${attrs}` : ''}/>`\n\t\t})\n\n\t\tfor (const [src, name] of Object.entries(imports)) {\n\t\t\ttree.children.unshift({\n\t\t\t\ttype: 'jsx',\n\t\t\t\tvalue: `import ${name} from '${src}'`,\n\t\t\t\tchildren: []\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * @param {Object} options\n * @param {string[]} options.className\n */\nfunction rehypeWrap({ className = [] }) {\n\t/**\n\t * Transform.\n\t *\n\t * @param {HastTree} tree\n\t *   Tree.\n\t * @returns {HastTree}\n\t *   Nothing.\n\t */\n\treturn (tree) => {\n\t\treturn {\n\t\t\t...tree,\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'element',\n\t\t\t\t\ttagName: 'div',\n\t\t\t\t\tproperties: {\n\t\t\t\t\t\tclassName\n\t\t\t\t\t},\n\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\tchildren: tree.children\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t}\n}\n\n/**\n * @param {Object} options\n * @param {string} options.root\n */\nfunction rewriteOrgFileLinks({ root }) {\n\t/**\n\t * @param {any} tree\n\t * @param {import('vfile').VFile} [file]\n\t */\n\treturn function (tree, file) {\n\t\tconst filePath = file?.path\n\t\tif (!filePath) return\n\n\t\tvisitParents(tree, { tagName: 'a' }, (node) => {\n\t\t\tconst href = node?.properties?.href\n\t\t\tif (typeof href !== 'string') return\n\t\t\tif (!href.endsWith('.org')) return\n\n\t\t\tconst targetSlug = resolveOrgHrefToContentSlug({\n\t\t\t\troot,\n\t\t\t\tfilePath,\n\t\t\t\thref\n\t\t\t})\n\t\t\tif (!targetSlug) return\n\t\t\tnode.properties.href = targetSlug\n\t\t})\n\t}\n}\n\n/**\n * @param {Object} options\n * @param {string} options.root\n * @param {string} options.filePath\n * @param {string} options.href\n * @returns {string|null}\n */\nfunction resolveOrgHrefToContentSlug({ root, filePath, href }) {\n\tconst decodedHrefPath = decodeURI(href)\n\tconst absoluteTargetPath = decodedHrefPath.startsWith('/')\n\t\t? path.resolve(root, `.${decodedHrefPath}`)\n\t\t: path.resolve(path.dirname(filePath), decodedHrefPath)\n\n\tconst relativeTargetPath = path.relative(root, absoluteTargetPath)\n\tif (\n\t\trelativeTargetPath.startsWith('..') ||\n\t\tpath.isAbsolute(relativeTargetPath)\n\t) {\n\t\treturn null\n\t}\n\n\treturn getSlugFromContentFilePath(relativeTargetPath)\n}\n\nfunction genId(length = 8) {\n\tconst array = new Uint8Array(length)\n\tcrypto.getRandomValues(array)\n\treturn Array.from(array, (byte) => (byte % 36).toString(36)).join('')\n}\n"
  },
  {
    "path": "packages/orga-build/lib/plugin.js",
    "content": "import fs from 'node:fs/promises'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport react from '@vitejs/plugin-react'\nimport { createServerModuleRunner } from 'vite'\nimport { resolveEndpointResponse } from './endpoint.js'\nimport { setupOrga } from './orga.js'\nimport { escapeHtml } from './util.js'\nimport { pluginFactory } from './vite.js'\n\nconst ssrEntry = fileURLToPath(new URL('./ssr.jsx', import.meta.url))\n\nconst require = createRequire(import.meta.url)\nconst defaultIndexHtml = fileURLToPath(new URL('./index.html', import.meta.url))\n/**\n * Alias map for React and wouter to ensure consistent resolution\n */\nexport const alias = {\n\treact: path.dirname(require.resolve('react/package.json')),\n\t'react-dom': path.dirname(require.resolve('react-dom/package.json')),\n\twouter: path.dirname(require.resolve('wouter'))\n}\n\n/**\n * @typedef {Object} OrgaBuildPluginOptions\n * @property {string} root - Root directory for content files\n * @property {string | undefined} [outDir] - Output directory (excluded from file discovery)\n * @property {string|string[]} [containerClass] - CSS class(es) to wrap rendered content\n * @property {string[]} [styles] - Global stylesheet URLs to import/inject\n * @property {import('unified').PluggableList} [rehypePlugins] - Extra rehype plugins appended to orga-build defaults\n * @property {string[]} [exclude] - Glob patterns for files to exclude from content scanning\n */\n\n/**\n * Creates the canonical orga-build plugin preset.\n * This is the single composition path used by both dev and build.\n *\n * @param {OrgaBuildPluginOptions} options\n * @returns {import('vite').PluginOption[]}\n */\nexport function orgaBuildPlugin({\n\troot,\n\toutDir,\n\tcontainerClass = [],\n\tstyles = [],\n\trehypePlugins = [],\n\texclude = []\n}) {\n\treturn [\n\t\tsetupOrga({ containerClass, root, rehypePlugins }),\n\t\treact(),\n\t\tpluginFactory({ dir: root, outDir, styles, exclude })\n\t]\n}\n\n/**\n * Creates the full Vite config options for orga-build.\n * Includes plugins, resolve aliases, and other shared config.\n *\n * @param {OrgaBuildPluginOptions & { outDir?: string, vitePlugins?: import('vite').PluginOption[], includeFallbackHtml?: boolean, projectRoot?: string }} options\n * @returns {{ plugins: import('vite').PluginOption[], resolve: { alias: typeof alias } }}\n */\nexport function createOrgaBuildConfig({\n\troot,\n\toutDir,\n\tcontainerClass = [],\n\tstyles = [],\n\trehypePlugins = [],\n\tvitePlugins = [],\n\tincludeFallbackHtml = false,\n\tprojectRoot = process.cwd(),\n\texclude = []\n}) {\n\tconst plugins = [\n\t\t...vitePlugins,\n\t\t...orgaBuildPlugin({\n\t\t\troot,\n\t\t\toutDir,\n\t\t\tcontainerClass,\n\t\t\tstyles,\n\t\t\trehypePlugins,\n\t\t\texclude\n\t\t})\n\t]\n\tif (includeFallbackHtml) {\n\t\t// HTML fallback must be first so it can handle HTML navigation requests\n\t\t// before runtime plugins (e.g. Cloudflare) potentially return 404.\n\t\tplugins.unshift(htmlFallbackPlugin(projectRoot, styles))\n\t}\n\treturn {\n\t\tplugins,\n\t\tresolve: { alias }\n\t}\n}\n\n/**\n * Checks if a user-provided index.html exists in the project root.\n *\n * @param {string} root - Project root directory\n * @returns {Promise<boolean>}\n */\nasync function hasUserIndexHtml(root) {\n\ttry {\n\t\tawait fs.access(path.join(root, 'index.html'), fs.constants.F_OK)\n\t\treturn true\n\t} catch {\n\t\treturn false\n\t}\n}\n\n/**\n * Creates an HTML serving plugin that handles index.html for dev mode.\n *\n * This plugin performs per-request SSR in dev mode (matching Astro/SvelteKit behaviour):\n * - SSR-renders each page on every request using Vite's server module runner\n * - Injects rendered content and page metadata (%orga.*% placeholders) into the template\n * - Falls back to the shell HTML for unknown routes (client-side router handles 404)\n * - Only handles GET/HEAD requests that accept HTML\n * - Does not intercept asset requests\n *\n * @param {string} projectRoot - Project root directory (where orga.config.js lives)\n * @param {string[]} [styles]\n * @returns {import('vite').Plugin}\n */\nexport function htmlFallbackPlugin(projectRoot, styles = []) {\n\treturn {\n\t\tname: 'orga-build:html-fallback',\n\n\t\tasync configureServer(server) {\n\t\t\t// Determine which index.html to use at startup\n\t\t\t// Look for user's index.html in project root (where orga.config.js lives)\n\t\t\tconst userIndexPath = path.join(projectRoot, 'index.html')\n\t\t\tconst userHasIndex = await hasUserIndexHtml(projectRoot)\n\t\t\tconst indexHtmlPath = userHasIndex ? userIndexPath : defaultIndexHtml\n\n\t\t\t// CJS compatibility here depends on Vite externalizing bare-specifier deps\n\t\t\t// (e.g. react/*) to native Node import(). If aliases rewrite specifiers\n\t\t\t// to absolute paths, modules can be inlined and evaluated without CJS globals.\n\t\t\tconst runner = createServerModuleRunner(server.environments.ssr)\n\n\t\t\tserver.middlewares.use(async (req, res, next) => {\n\t\t\t\t// Only handle GET/HEAD requests\n\t\t\t\tif (req.method !== 'GET' && req.method !== 'HEAD') {\n\t\t\t\t\treturn next()\n\t\t\t\t}\n\n\t\t\t\tconst url = req.url || '/'\n\t\t\t\tconst pathname = url.split('?')[0]\n\n\t\t\t\t// Endpoint routes are handled first and bypass HTML fallback.\n\t\t\t\ttry {\n\t\t\t\t\tconst { endpoints } = await runner.import(ssrEntry)\n\t\t\t\t\tconst endpointModule = endpoints?.[pathname]\n\t\t\t\t\tif (endpointModule) {\n\t\t\t\t\t\tconst ctx = {\n\t\t\t\t\t\t\turl: new URL(url, `http://${req.headers.host || 'localhost'}`),\n\t\t\t\t\t\t\tparams: {},\n\t\t\t\t\t\t\tmode: /** @type {'dev'} */ ('dev'),\n\t\t\t\t\t\t\troute: { route: pathname }\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst response = await resolveEndpointResponse(\n\t\t\t\t\t\t\tendpointModule,\n\t\t\t\t\t\t\tctx,\n\t\t\t\t\t\t\treq.method\n\t\t\t\t\t\t)\n\t\t\t\t\t\tres.statusCode = response.status\n\t\t\t\t\t\tresponse.headers.forEach((headerValue, headerName) => {\n\t\t\t\t\t\t\tres.setHeader(headerName, headerValue)\n\t\t\t\t\t\t})\n\t\t\t\t\t\tif (req.method === 'HEAD') {\n\t\t\t\t\t\t\tres.end()\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconst bytes = Buffer.from(await response.arrayBuffer())\n\t\t\t\t\t\tres.end(bytes)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tnext(e)\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\t// Only handle browser-like navigation requests.\n\t\t\t\t// Don't match generic */* accepts to avoid hijacking API requests.\n\t\t\t\tconst accept = req.headers.accept || ''\n\t\t\t\tif (!accept.includes('text/html')) {\n\t\t\t\t\treturn next()\n\t\t\t\t}\n\n\t\t\t\t// Don't intercept asset requests (files with extensions)\n\t\t\t\tif (pathname !== '/' && /\\.\\w+$/.test(pathname)) {\n\t\t\t\t\treturn next()\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\t// Import via the runner on each request — the module graph handles\n\t\t\t\t\t// HMR invalidation so stale modules are never served.\n\t\t\t\t\tconst { render, pages } = await runner.import(ssrEntry)\n\t\t\t\t\tconst content = render(pathname)\n\n\t\t\t\t\tlet html = await fs.readFile(indexHtmlPath, 'utf-8')\n\t\t\t\t\thtml = await server.transformIndexHtml(url, html)\n\n\t\t\t\t\tconst uniqueCssUrls = [...new Set(styles)]\n\t\t\t\t\tif (uniqueCssUrls.length > 0) {\n\t\t\t\t\t\tconst cssLinks = uniqueCssUrls\n\t\t\t\t\t\t\t.map((u) => `<link rel=\"stylesheet\" href=\"${escapeHtml(u)}\">`)\n\t\t\t\t\t\t\t.join('')\n\t\t\t\t\t\thtml = html.replace('</head>', `${cssLinks}</head>`)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (content) {\n\t\t\t\t\t\tconst ssr = { routePath: pathname }\n\t\t\t\t\t\thtml = html.replace(\n\t\t\t\t\t\t\t'<div id=\"root\"></div>',\n\t\t\t\t\t\t\t`<script>window._ssr=${JSON.stringify(ssr)};</script><div id=\"root\">${content}</div>`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Replace %orga.*% placeholders with page metadata\n\t\t\t\t\tconst page = pages[pathname]\n\t\t\t\t\tif (page) {\n\t\t\t\t\t\thtml = html.replace(/%orga\\.(\\w+)%/g, (_, key) => {\n\t\t\t\t\t\t\tconst value = page[key] ?? ''\n\t\t\t\t\t\t\treturn escapeHtml(String(value))\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t\t// Strip any remaining unresolved placeholders (unknown route)\n\t\t\t\t\thtml = html.replace(/%orga\\.\\w+%/g, '')\n\n\t\t\t\t\tres.statusCode = 200\n\t\t\t\t\tres.setHeader('Content-Type', 'text/html')\n\t\t\t\t\tres.end(html)\n\t\t\t\t} catch (e) {\n\t\t\t\t\tnext(e)\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/lib/serve.js",
    "content": "import path from 'node:path'\nimport { createServer } from 'vite'\nimport { alias, createOrgaBuildConfig } from './plugin.js'\n\n/**\n * Start the development server using native Vite.\n *\n * @param {import('./config.js').Config} config\n * @param {number} [port]\n * @param {string} [projectRoot]\n */\nexport async function serve(config, port = 3000, projectRoot = process.cwd()) {\n\tconst { plugins } = createOrgaBuildConfig({\n\t\troot: config.root,\n\t\toutDir: config.outDir,\n\t\tcontainerClass: config.containerClass,\n\t\tstyles: config.styles ?? [],\n\t\trehypePlugins: config.rehypePlugins ?? [],\n\t\tvitePlugins: config.vitePlugins,\n\t\tincludeFallbackHtml: true,\n\t\tprojectRoot,\n\t\texclude: config.exclude ?? []\n\t})\n\n\tconst server = await createServer({\n\t\tplugins,\n\t\tappType: 'custom',\n\t\t// Aliases are scoped to the client environment only.\n\t\t// The SSR environment must NOT have these aliases: they convert bare specifiers\n\t\t// (e.g. 'react') into absolute paths, which bypasses Vite's fetchModule\n\t\t// externalization branch and causes CJS packages to be evaluated inline by\n\t\t// ESModulesEvaluator (which has no 'module'/'require' globals).\n\t\tenvironments: {\n\t\t\tclient: {\n\t\t\t\tresolve: /** @type {any} */ ({ alias })\n\t\t\t}\n\t\t},\n\t\tserver: {\n\t\t\tport,\n\t\t\tstrictPort: false,\n\t\t\twatch: {\n\t\t\t\tignored: [`${path.resolve(config.outDir)}/**`]\n\t\t\t}\n\t\t}\n\t})\n\n\tawait server.listen()\n\tserver.printUrls()\n}\n"
  },
  {
    "path": "packages/orga-build/lib/ssr.jsx",
    "content": "import { renderToString } from 'react-dom/server'\nimport { Router } from 'wouter'\nimport endpoints from '/@orga-build/endpoints'\nimport pages from '/@orga-build/pages'\nimport { App } from './app.jsx'\n\nexport { pages }\nexport { endpoints }\n\n/**\n * @param {string} url\n */\nexport function render(url) {\n\tconst page = pages[url]\n\tif (!page) {\n\t\tconsole.log(`no page found for ${url}`)\n\t\treturn\n\t}\n\tconst ssrContext = {}\n\tconsole.log(`rendering ${url}`)\n\treturn renderToString(\n\t\t<Router ssrPath={url} ssrContext={ssrContext}>\n\t\t\t<App />\n\t\t</Router>\n\t)\n}\n"
  },
  {
    "path": "packages/orga-build/lib/util.js",
    "content": "import { exec } from 'node:child_process'\nimport { createElement } from 'react'\n\nexport function buildNav() {}\n\n/**\n * @param {string} file\n * @param {...RegExp|string} patterns\n * @returns {boolean}\n */\nexport function match(file, ...patterns) {\n\treturn patterns.some((p) => {\n\t\tif (p instanceof RegExp) {\n\t\t\treturn p.test(file)\n\t\t}\n\t\treturn file === p\n\t})\n}\n\n/**\n * Default layout\n * @param {Object} props\n * @param {string|undefined} props.title\n * @param {import('react').ReactNode} props.children\n * @returns {React.JSX.Element}\n */\nexport function DefaultLayout({ title, children }) {\n\treturn createElement(\n\t\t'html',\n\t\t{ lang: 'en' },\n\t\tcreateElement(\n\t\t\t'head',\n\t\t\t{},\n\t\t\tcreateElement('meta', { charSet: 'utf-8' }),\n\t\t\tcreateElement('meta', {\n\t\t\t\tname: 'viewport',\n\t\t\t\tcontent: 'width=device-width, initial-scale=1'\n\t\t\t}),\n\t\t\ttitle && createElement('title', {}, title)\n\t\t),\n\t\tcreateElement('body', {}, children)\n\t)\n}\n\n/**\n * @param {string} str\n * @returns {string}\n */\nexport function escapeHtml(str) {\n\treturn String(str)\n\t\t.replace(/&/g, '&amp;')\n\t\t.replace(/\"/g, '&quot;')\n\t\t.replace(/</g, '&lt;')\n\t\t.replace(/>/g, '&gt;')\n}\n\n/**\n * @param {string} cmd\n */\nexport async function $(cmd) {\n\treturn new Promise((resolve, reject) => {\n\t\texec(cmd, (err, stdout, stderr) => {\n\t\t\tif (err) {\n\t\t\t\treject(err)\n\t\t\t}\n\t\t\tif (stderr) {\n\t\t\t\tconsole.error(stderr)\n\t\t\t}\n\t\t\tconsole.log(stdout)\n\t\t\tresolve(stdout)\n\t\t})\n\t})\n}\n"
  },
  {
    "path": "packages/orga-build/lib/vite.js",
    "content": "import path from 'node:path'\nimport { setup } from './files.js'\n\nconst magicModulePrefix = '/@orga-build/'\nconst pagesModuleId = `${magicModulePrefix}pages`\nconst endpointsModuleId = `${magicModulePrefix}endpoints`\nexport const appEntryId = `${magicModulePrefix}main.js`\nconst contentModuleId = 'orga-build:content'\nconst contentModuleIdResolved = `\\0${contentModuleId}`\nconst endpointModulePrefix = `${endpointsModuleId}/__route__/`\n\n/**\n * @param {Object} options\n * @param {string} options.dir\n * @param {string} [options.outDir]\n * @param {string[]} [options.styles]\n * @param {string[]} [options.exclude]\n * @returns {import('vite').Plugin}\n */\nexport function pluginFactory({ dir, outDir, styles = [], exclude = [] }) {\n\tconst files = setup(dir, { outDir, exclude })\n\n\treturn {\n\t\tname: 'vite-plugin-orga-pages',\n\t\tenforce: 'pre',\n\t\tconfig: (_config, _env) => ({\n\t\t\tfuture: {\n\t\t\t\tremovePluginHookSsrArgument: 'warn',\n\t\t\t\tremovePluginHookHandleHotUpdate: 'warn',\n\t\t\t\tremoveSsrLoadModule: 'warn'\n\t\t\t}\n\t\t}),\n\n\t\tasync configureServer(_server) {\n\t\t\t// Eagerly run file discovery so route conflicts surface at startup\n\t\t\tawait files.pages()\n\t\t\tawait files.endpoints()\n\t\t},\n\n\t\thotUpdate() {\n\t\t\t// Invalidate in-memory file caches so added/removed routes are picked up\n\t\t\tfiles.invalidate()\n\t\t\t// Invalidate content module when content files change\n\t\t\tconst module = this.environment.moduleGraph.getModuleById(\n\t\t\t\tcontentModuleIdResolved\n\t\t\t)\n\t\t\tif (module) {\n\t\t\t\tthis.environment.moduleGraph.invalidateModule(module)\n\t\t\t\t// Full reload for now; can optimize to HMR later\n\t\t\t\tthis.environment.hot.send({ type: 'full-reload', path: '*' })\n\t\t\t}\n\t\t},\n\n\t\tasync resolveId(id, _importer) {\n\t\t\tif (id === appEntryId) {\n\t\t\t\treturn appEntryId\n\t\t\t}\n\t\t\tif (id === contentModuleId) {\n\t\t\t\treturn contentModuleIdResolved\n\t\t\t}\n\t\t\tif (id.startsWith(magicModulePrefix)) {\n\t\t\t\treturn id\n\t\t\t}\n\t\t},\n\t\tasync load(id) {\n\t\t\tif (id === appEntryId) {\n\t\t\t\tconst styleImports = styles\n\t\t\t\t\t.map((styleUrl) => `import ${JSON.stringify(styleUrl)};`)\n\t\t\t\t\t.join('\\n')\n\t\t\t\treturn `${styleImports}\\nimport \"orga-build/csr\";`\n\t\t\t}\n\t\t\tif (id === contentModuleIdResolved) {\n\t\t\t\treturn await renderContentModule()\n\t\t\t}\n\t\t\tif (id === pagesModuleId) {\n\t\t\t\treturn await renderPageList()\n\t\t\t}\n\t\t\tif (id === endpointsModuleId) {\n\t\t\t\treturn await renderEndpointList()\n\t\t\t}\n\t\t\tif (id.startsWith(pagesModuleId)) {\n\t\t\t\tconst pageId = id.replace(pagesModuleId, '')\n\t\t\t\tconst page = await files.page(pageId)\n\t\t\t\tif (page) {\n\t\t\t\t\treturn `\nexport * from '${page.dataPath}';\nexport {default} from '${page.dataPath}';\n`\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (id.startsWith(endpointModulePrefix)) {\n\t\t\t\tconst routeHex = id.slice(endpointModulePrefix.length)\n\t\t\t\tconst endpointId = Buffer.from(routeHex, 'hex').toString('utf-8')\n\t\t\t\tconst endpoint = await files.endpoint(endpointId)\n\t\t\t\tif (endpoint) {\n\t\t\t\t\treturn `export * from '${endpoint.dataPath}';`\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (id === `${magicModulePrefix}layouts`) {\n\t\t\t\tconst layouts = await files.layouts()\n\t\t\t\t/** @type {string[]} */\n\t\t\t\tconst imports = []\n\t\t\t\tconst lines = Object.entries(layouts).map(([key, value], i) => {\n\t\t\t\t\timports.push(`import Layout${i} from '${value}'`)\n\t\t\t\t\treturn `layouts['${key}'] = Layout${i}`\n\t\t\t\t})\n\t\t\t\treturn `\n${imports.join('\\n')}\nconst layouts = {};\n${lines.join('\\n')}\nexport default layouts;\n\t\t\t\t`\n\t\t\t}\n\n\t\t\tif (id === `${magicModulePrefix}components`) {\n\t\t\t\treturn await renderComponents()\n\t\t\t}\n\t\t}\n\t}\n\n\tasync function renderPageList() {\n\t\tconst pages = await files.pages()\n\t\treturn renderModuleMap('pages', pages, (id) =>\n\t\t\tpath.join(magicModulePrefix, 'pages', id)\n\t\t)\n\t}\n\n\tasync function renderEndpointList() {\n\t\tconst endpoints = await files.endpoints()\n\t\treturn renderModuleMap(\n\t\t\t'endpoints',\n\t\t\tendpoints,\n\t\t\t(route) => endpointModulePrefix + Buffer.from(route).toString('hex')\n\t\t)\n\t}\n\n\t/**\n\t * @param {string} name\n\t * @param {Record<string, unknown>} entries\n\t * @param {(key: string) => string} toModulePath\n\t */\n\tfunction renderModuleMap(name, entries, toModulePath) {\n\t\t/** @type {string[]} */\n\t\tconst imports = []\n\t\t/** @type {string[]} */\n\t\tconst assignments = []\n\t\tObject.keys(entries).forEach((key, i) => {\n\t\t\timports.push(`import * as m${i} from '${toModulePath(key)}'`)\n\t\t\tassignments.push(`${name}['${key}'] = m${i}`)\n\t\t})\n\t\treturn [\n\t\t\timports.join('\\n'),\n\t\t\t`const ${name} = {};`,\n\t\t\tassignments.join('\\n'),\n\t\t\t`export default ${name};`\n\t\t].join('\\n')\n\t}\n\n\tasync function renderComponents() {\n\t\tconst components = await files.components()\n\t\tif (components) {\n\t\t\treturn `export * from '${components}'`\n\t\t}\n\t\treturn ''\n\t}\n\n\tasync function renderContentModule() {\n\t\tconst entries = await files.contentEntries()\n\t\tconst manifest = JSON.stringify(entries, null, 2)\n\n\t\treturn `\nconst __entries = ${manifest}\n\nfunction normalizePath(path = '') {\n  return String(path).replace(/^\\\\/+|\\\\/+$/g, '')\n}\n\nfunction pathMatches(entryPath, queryPath) {\n  const e = normalizePath(entryPath)\n  const q = normalizePath(queryPath)\n  if (!q) return true\n  return e === q || e.startsWith(q + '/')\n}\n\nexport function getPages(path = '', filter) {\n  const list = __entries.filter((e) => pathMatches(e.path, path))\n  return typeof filter === 'function' ? list.filter(filter) : list\n}\n\nexport function getPage(idOrSlug, path = '') {\n  return __entries.find((e) => {\n    if (!pathMatches(e.path, path)) return false\n    return e.id === idOrSlug || e.slug === idOrSlug\n  })\n}\n\nexport function getEntries(refs) {\n  return refs.map((r) => getPage(r.id, r.path || ''))\n}\n\nexport const getCollection = getPages\nexport const getEntry = getPage\n`\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/lib/watch.js",
    "content": "import fs from 'node:fs/promises'\n\n/**\n * @param {import(\"fs\").PathLike} dir\n * @param {RegExp} ignore\n * @param {{(event: fs.FileChangeInfo<string>): Promise<void> | void}} onChange\n */\nexport async function watch(dir, ignore, onChange) {\n\tlet busy = false\n\tlet dirty = false\n\t/** @type {ReturnType<typeof setTimeout> | null} */\n\tlet timeout = null\n\tconst delay = 1000\n\tconst defaultIgnorePattern = /node_modules|\\.git|\\.DS_Store|\\.orga-build/\n\n\tconst watcher = fs.watch(dir, { recursive: true })\n\tfor await (const event of watcher) {\n\t\tif (\n\t\t\tevent.eventType !== 'change' ||\n\t\t\tevent.filename === null ||\n\t\t\tshouldIgnore(event.filename)\n\t\t) {\n\t\t\tcontinue\n\t\t}\n\t\tconsole.log(`file changed: ${event.filename}`)\n\t\tdirty = true\n\t\tif (busy) {\n\t\t\tcontinue\n\t\t}\n\t\tif (timeout !== null) clearTimeout(timeout)\n\t\ttimeout = setTimeout(processEvent, delay, event)\n\t}\n\n\t/**\n\t * @param {any} event\n\t */\n\tasync function processEvent(event) {\n\t\tbusy = true\n\t\tdirty = false\n\t\tawait onChange(event)\n\t\tbusy = false\n\t\tif (dirty) {\n\t\t\tprocessEvent(event)\n\t\t}\n\t}\n\n\t/**\n\t * @param {string} filename\n\t */\n\tfunction shouldIgnore(filename) {\n\t\treturn defaultIgnorePattern.test(filename) || ignore.test(filename)\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/package.json",
    "content": "{\n\t\"name\": \"orga-build\",\n\t\"version\": \"0.9.0\",\n\t\"description\": \"A simple tool that builds org-mode files into a website\",\n\t\"type\": \"module\",\n\t\"engines\": {\n\t\t\"node\": \">=20.19.0\"\n\t},\n\t\"bin\": {\n\t\t\"orga-build\": \"./cli.js\"\n\t},\n\t\"scripts\": {\n\t\t\"clean\": \"fd . -e d.ts -e d.ts.map -I -x rm {}\",\n\t\t\"test\": \"node --test --no-warnings \\\"lib/__tests__/*.test.js\\\"\"\n\t},\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"cli.js\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\",\n\t\t\"lib/content.d.ts\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./index.d.ts\",\n\t\t\t\"import\": \"./index.js\"\n\t\t},\n\t\t\"./csr\": \"./lib/csr.jsx\",\n\t\t\"./components\": \"./lib/components.js\",\n\t\t\"./client\": {\n\t\t\t\"types\": \"./lib/content.d.ts\"\n\t\t}\n\t},\n\t\"keywords\": [\n\t\t\"orgajs\",\n\t\t\"org-mode\",\n\t\t\"build\",\n\t\t\"website\",\n\t\t\"react\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/orga-build\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/rollup\": \"workspace:*\",\n\t\t\"@vitejs/plugin-react\": \"^5.1.4\",\n\t\t\"globby\": \"^14.1.0\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"rehype-katex\": \"^7.0.1\",\n\t\t\"unified\": \"^11.0.5\",\n\t\t\"unist-util-visit-parents\": \"^6.0.1\",\n\t\t\"vite\": \"^7.3.1\",\n\t\t\"wouter\": \"^3.7.0\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/hast\": \"^3.0.4\",\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"@types/react\": \"^19.0.8\",\n\t\t\"@types/react-dom\": \"^19.0.3\",\n\t\t\"orga\": \"workspace:*\"\n\t}\n}\n"
  },
  {
    "path": "packages/orga-build/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/orgx/CHANGELOG.md",
    "content": "# @orgajs/orgx\n\n## 2.6.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/reorg-parse@4.4.1\n  - @orgajs/reorg-rehype@4.3.9\n\n## 2.6.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/reorg-parse@4.4.0\n  - @orgajs/reorg-rehype@4.3.3\n\n## 2.5.2\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.3.1\n- @orgajs/reorg-rehype@4.3.2\n\n## 2.5.1\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.3.1\n\n## 2.5.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/reorg-rehype@4.3.0\n  - @orgajs/reorg-parse@4.3.0\n\n## 2.4.1\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n\n## 2.4.0\n\n### Minor Changes\n\n- 351f690: introduce @orgajs/node-loader, @orgajs/esbuild, @orgajs/build\n\n  - @orgajs/node-loader : the nodejs loader for org-mode files\n  - @orgajs/esbuild : esbuild plugin\n  - @orgajs/build : static site generator, a.k.a orga-build\n\n## 2.3.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/reorg-rehype@4.2.0\n  - @orgajs/reorg-parse@4.2.0\n\n## 2.2.2\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@4.1.3\n\n## 2.2.1\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.1.2\n- @orgajs/reorg-rehype@4.1.2\n\n## 2.2.0\n\n### Minor Changes\n\n- ac322714: implement editor\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.1.1\n- @orgajs/reorg-rehype@4.1.1\n\n## 2.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/reorg-rehype@4.1.0\n  - @orgajs/reorg-parse@4.1.0\n\n## 2.0.1\n\n### Patch Changes\n\n- 1dbf674d: fix layout issue\n\n  `OrgaLayout` was renamed to `OrgLayout`.\n\n## 2.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - @orgajs/reorg-rehype@4.0.0\n  - @orgajs/reorg-parse@4.0.0\n\n## 1.0.8\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n- Updated dependencies [eeccc870]\n  - @orgajs/reorg-rehype@3.0.10\n  - @orgajs/reorg-parse@3.1.7\n\n## 1.0.7\n\n### Patch Changes\n\n- 6c1ddb9f: add latex support\n  - @orgajs/reorg-rehype@3.0.9\n  - @orgajs/reorg-parse@3.1.6\n\n## 1.0.6\n\n### Patch Changes\n\n- 4bde5155: tidy up dependencies\n  - @orgajs/reorg-parse@3.1.5\n  - @orgajs/reorg-rehype@3.0.8\n\n## 1.0.5\n\n### Patch Changes\n\n- @orgajs/reorg-rehype@3.0.7\n- @orgajs/reorg-parse@3.1.4\n\n## 1.0.4\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.3\n- @orgajs/reorg-rehype@3.0.6\n\n## 1.0.3\n\n### Patch Changes\n\n- cd7cac3d: export evaluateSync\n\n## 1.0.2\n\n### Patch Changes\n\n- c8edd571: add evaluateSync function to orgx\n\n## 1.0.1\n\n### Patch Changes\n\n- 594bf16b: ## @orgajs/orgx\n\n  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).\n\n  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:\n\n  - `@orgajs/loader`\n  - `@orgajs/next`\n  - `gatsby-plugin-orga`\n  - `gatsby-theme-orga-docs`\n  - `@orgajs/playground'`\n\n  `gatsby-transformer-orga` is still using the original compiler, since it has it's own ecosystem which requires some work to do a proper migration. That means the derivative packages around it are using the original compiler.\n\n  - `gatsby-theme-orga-posts`\n  - `gatsby-theme-orga-posts-core`\n\n  ## theme-ui support\n\n  `theme-ui` has `mdx` support builtin, and it's hard to do a clean extraction. So the package `@orgajs/theme-ui` is wrapping theme-ui, and provide orga specific tweaks. For gatsby, `gatsby-plugin-orga-theme-ui` is the equivalent of `gatsby-plugin-theme-ui`, but with orga support.\n\n  - @orgajs/reorg-parse@3.1.2\n  - @orgajs/reorg-rehype@3.0.5\n"
  },
  {
    "path": "packages/orgx/README.org",
    "content": "#+title: @orgajs/orgx\n\nA (almost) direct port of [[https://github.com/wooorm/xdm][xdm]].\n"
  },
  {
    "path": "packages/orgx/index.js",
    "content": "/**\n * @typedef {import('./lib/core.js').ProcessorOptions} ProcessorOptions\n * @typedef {import('./lib/compile.js').CompileOptions} CompileOptions\n * @typedef {import('./lib/evaluate.js').EvaluateOptions} EvaluateOptions\n * @typedef {import('./lib/types.js').OrgComponents} OrgComponents\n * @typedef {import('./lib/types.js').OrgContent} OrgContent\n * @typedef {import('./lib/types.js').OrgModule} OrgModule\n * @typedef {import('./lib/types.js').OrgProps} OrgProps\n */\n\nexport { compile, compileSync } from './lib/compile.js'\nexport { createProcessor } from './lib/core.js'\nexport { evaluate, evaluateSync } from './lib/evaluate.js'\nexport { run, runSync } from './lib/run.js'\nexport { isOrgContent } from './lib/util/is-org-content.js'\n"
  },
  {
    "path": "packages/orgx/lib/compile.js",
    "content": "/**\n * @typedef {import('vfile').VFile} VFile\n * @typedef {import('vfile').VFileCompatible} VFileCompatible\n * @typedef {import('./core.js').PluginOptions} PluginOptions\n * @typedef {import('./core.js').BaseProcessorOptions} BaseProcessorOptions\n */\n\n/**\n * @typedef {Omit<BaseProcessorOptions, 'format'>} CoreProcessorOptions\n *   Core configuration.\n *\n * @typedef ExtraOptions\n *   Extra configuration.\n * @property {'detect' | 'mdx' | 'md' | null | undefined} [format='detect']\n *   Format of `file`.\n *\n * @typedef {CoreProcessorOptions & PluginOptions & ExtraOptions} CompileOptions\n *   Configuration.\n */\n\nimport { createProcessor } from './core.js'\nimport { resolveFileAndOptions } from './util/resolve-file-and-options.js'\n\n/**\n * Compile MDX to JS.\n *\n * @param {VFileCompatible} vfileCompatible\n *   MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be\n *   given to `vfile`).\n * @param {CompileOptions | null | undefined} [compileOptions]\n *   Compile configuration.\n * @return {Promise<VFile>}\n *   File.\n */\nexport function compile(vfileCompatible, compileOptions) {\n\tconst { file, options } = resolveFileAndOptions(\n\t\tvfileCompatible,\n\t\tcompileOptions\n\t)\n\treturn createProcessor(options).process(file)\n}\n\n/**\n * Synchronously compile MDX to JS.\n *\n * @param {VFileCompatible} vfileCompatible\n *   MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be\n *   given to `vfile`).\n * @param {CompileOptions | null | undefined} [compileOptions]\n *   Compile configuration.\n * @return {VFile}\n *   File.\n */\nexport function compileSync(vfileCompatible, compileOptions) {\n\tconst { file, options } = resolveFileAndOptions(\n\t\tvfileCompatible,\n\t\tcompileOptions\n\t)\n\treturn createProcessor(options).processSync(file)\n}\n"
  },
  {
    "path": "packages/orgx/lib/core.js",
    "content": "/**\n * @import {Program} from 'estree-jsx'\n * @import {PluggableList, Processor} from 'unified'\n * @typedef {import('./plugin/rehype-recma.js').Options} RehypeRecmaOptions\n * @typedef {import('./plugin/recma-document.js').RecmaDocumentOptions} RecmaDocumentOptions\n * @typedef {import('recma-stringify').Options} RecmaStringifyOptions\n * @typedef {import('./plugin/recma-jsx-rewrite.js').RecmaJsxRewriteOptions} RecmaJsxRewriteOptions\n */\n\n/**\n * @typedef BaseProcessorOptions\n *   Base configuration.\n * @property {boolean | null | undefined} [jsx=false]\n *   Whether to keep JSX.\n *   Format of the files to be processed.\n * @property {'function-body' | 'program'} [outputFormat='program']\n *   Whether to compile to a whole program or a function body..\n * @property {PluggableList | null | undefined} [recmaPlugins]\n *   List of recma (esast, JavaScript) plugins.\n * @property {PluggableList | null | undefined} [reorgPlugins]\n *   List of remark (mdast, markdown) plugins.\n * @property {PluggableList | null | undefined} [rehypePlugins]\n *   List of rehype (hast, HTML) plugins.\n * @property {import('@orgajs/reorg-rehype').Options | null | undefined} [reorgRehypeOptions]\n *   Options to pass through to `reorg-rehype`.\n *\n * @typedef {Omit<RehypeRecmaOptions & RecmaDocumentOptions & RecmaStringifyOptions & RecmaJsxRewriteOptions, 'outputFormat'>} PluginOptions\n *   Configuration for internal plugins.\n *\n * @typedef {BaseProcessorOptions & PluginOptions} ProcessorOptions\n *   Configuration for processor.\n */\n\nimport reorgParse from '@orgajs/reorg-parse'\nimport reorgRehype from '@orgajs/reorg-rehype'\nimport recmaBuildJsx from 'recma-build-jsx'\nimport recmaJsx from 'recma-jsx'\nimport recmaStringify from 'recma-stringify'\nimport { unified } from 'unified'\nimport { recmaBuildJsxTransform } from './plugin/recma-build-jsx-transform.js'\nimport { recmaDocument } from './plugin/recma-document.js'\nimport { recmaJsxRewrite } from './plugin/recma-jsx-rewrite.js'\nimport rehypeRecma from './plugin/rehype-recma.js'\n\n/**\n * Pipeline to:\n *\n * 1. Parse org-mode\n * 2. Transform through reorg (oast), rehype (hast), and recma (esast)\n * 3. Serialize as JavaScript\n *\n * @param {Readonly<ProcessorOptions> | null | undefined} [options]\n *   Configuration.\n * @return {Processor<Document, Program, Program, Program, string>}\n *   Processor.\n\n */\nexport function createProcessor(options) {\n\tconst {\n\t\tdevelopment,\n\t\tjsx,\n\t\toutputFormat,\n\t\tproviderImportSource,\n\t\trecmaPlugins,\n\t\trehypePlugins,\n\t\treorgPlugins,\n\t\treorgRehypeOptions,\n\t\telementAttributeNameCase,\n\t\tstylePropertyNameCase,\n\t\tSourceMapGenerator,\n\t\t...rest\n\t} = options || {}\n\tconst dev = development ?? false\n\n\tconst pipeline = unified()\n\t\t.use(reorgParse)\n\t\t.use(reorgPlugins || [])\n\t\t.use(reorgRehype, {\n\t\t\t...reorgRehypeOptions,\n\t\t\tallowDangerousHtml: true\n\t\t})\n\t\t.use(rehypePlugins || [])\n\t\t.use(rehypeRecma, { elementAttributeNameCase, stylePropertyNameCase })\n\t\t.use(recmaDocument, { ...rest, outputFormat })\n\t\t.use(recmaJsxRewrite, {\n\t\t\tdevelopment: dev,\n\t\t\tproviderImportSource,\n\t\t\toutputFormat\n\t\t})\n\n\tif (!jsx) {\n\t\tpipeline\n\t\t\t.use(recmaBuildJsx, { development: dev, outputFormat })\n\t\t\t.use(recmaBuildJsxTransform, { outputFormat })\n\t}\n\n\tpipeline\n\t\t.use(recmaJsx)\n\t\t.use(recmaStringify, { SourceMapGenerator })\n\t\t.use(recmaPlugins || [])\n\n\t// @ts-expect-error: TS doesn’t get the plugins we added with if-statements.\n\treturn pipeline\n}\n"
  },
  {
    "path": "packages/orgx/lib/evaluate.js",
    "content": "/**\n * @typedef {import('./types.js').OrgModule} ExportMap\n * @typedef {import('vfile').VFileCompatible} VFileCompatible\n * @typedef {import('./util/resolve-evaluate-options.js').EvaluateOptions} EvaluateOptions\n */\n\nimport { compile, compileSync } from './compile.js'\nimport { run, runSync } from './run.js'\nimport { resolveEvaluateOptions } from './util/resolve-evaluate-options.js'\n\n/**\n * Evaluate Org Content.\n *\n * @param {VFileCompatible} vfileCompatible\n *   MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be\n *   given to `vfile`).\n * @param {EvaluateOptions} evaluateOptions\n *   Configuration for evaluation.\n * @return {Promise<ExportMap>}\n *   Export map.\n */\nexport async function evaluate(vfileCompatible, evaluateOptions) {\n\tconst { compiletime, runtime } = resolveEvaluateOptions(evaluateOptions)\n\treturn run(await compile(vfileCompatible, compiletime), runtime)\n}\n\n/**\n * Synchronously evaluate MDX.\n *\n * @param {VFileCompatible} vfileCompatible\n *   MDX document to parse (`string`, `Buffer`, `vfile`, anything that can be\n *   given to `vfile`).\n * @param {EvaluateOptions} evaluateOptions\n *   Configuration for evaluation.\n * @return {ExportMap}\n *   Export map.\n */\nexport function evaluateSync(vfileCompatible, evaluateOptions) {\n\tconst { compiletime, runtime } = resolveEvaluateOptions(evaluateOptions)\n\treturn runSync(compileSync(vfileCompatible, compiletime), runtime)\n}\n"
  },
  {
    "path": "packages/orgx/lib/plugin/recma-build-jsx-transform.js",
    "content": "/**\n * @import {Program} from 'estree-jsx'\n */\n\n/**\n * @typedef Options\n *   Configuration for internal plugin `recma-build-jsx-transform`.\n * @property {'function-body' | 'program' | null | undefined} [outputFormat='program']\n *   Whether to keep the import of the automatic runtime or get it from\n *   `arguments[0]` instead (default: `'program'`).\n */\n\nimport { specifiersToDeclarations } from '../util/estree-util-specifiers-to-declarations.js'\nimport { toIdOrMemberExpression } from '../util/estree-util-to-id-or-member-expression.js'\n\n/**\n * Plugin to change the tree after compiling JSX away.\n *\n * @param {Readonly<Options> | null | undefined} [options]\n *   Configuration (optional).\n * @returns\n *   Transform.\n */\nexport function recmaBuildJsxTransform(options) {\n\t/* c8 ignore next -- always given in `@mdx-js/mdx` */\n\tconst { outputFormat } = options || {}\n\n\t/**\n\t * @param {Program} tree\n\t *   Tree.\n\t * @returns {undefined}\n\t *   Nothing.\n\t */\n\treturn function (tree) {\n\t\t// Remove the pragma comment that we injected ourselves as it is no longer\n\t\t// needed.\n\t\t// if (tree.comments) {\n\t\t//   tree.comments = tree.comments.filter(function (d) {\n\t\t//     return !d.data?._mdxIsPragmaComment\n\t\t//   })\n\t\t// }\n\n\t\t// When compiling to a function body, replace the import that was just\n\t\t// generated, and get `jsx`, `jsxs`, and `Fragment` from `arguments[0]`\n\t\t// instead.\n\t\tif (outputFormat === 'function-body') {\n\t\t\tlet index = 0\n\n\t\t\t// Skip directives: JS currently only has `use strict`, but Acorn allows\n\t\t\t// arbitrary ones.\n\t\t\t// Practically things like `use client` could be used?\n\t\t\twhile (index < tree.body.length) {\n\t\t\t\tconst child = tree.body[index]\n\t\t\t\tif ('directive' in child && child.directive) {\n\t\t\t\t\tindex++\n\t\t\t\t} else {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst declaration = tree.body[index]\n\n\t\t\tif (\n\t\t\t\tdeclaration &&\n\t\t\t\tdeclaration.type === 'ImportDeclaration' &&\n\t\t\t\ttypeof declaration.source.value === 'string' &&\n\t\t\t\t/\\/jsx-(dev-)?runtime$/.test(declaration.source.value)\n\t\t\t) {\n\t\t\t\ttree.body[index] = {\n\t\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\t\tkind: 'const',\n\t\t\t\t\tdeclarations: specifiersToDeclarations(\n\t\t\t\t\t\tdeclaration.specifiers,\n\t\t\t\t\t\ttoIdOrMemberExpression(['arguments', 0])\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/plugin/recma-document.js",
    "content": "/**\n * @typedef {import('estree-jsx').Directive} Directive\n * @typedef {import('estree-jsx').ExportAllDeclaration} ExportAllDeclaration\n * @typedef {import('estree-jsx').ExportDefaultDeclaration} ExportDefaultDeclaration\n * @typedef {import('estree-jsx').ExportNamedDeclaration} ExportNamedDeclaration\n * @typedef {import('estree-jsx').ExportSpecifier} ExportSpecifier\n * @typedef {import('estree-jsx').Expression} Expression\n * @typedef {import('estree-jsx').FunctionDeclaration} FunctionDeclaration\n * @typedef {import('estree-jsx').ImportDeclaration} ImportDeclaration\n * @typedef {import('estree-jsx').ImportDefaultSpecifier} ImportDefaultSpecifier\n * @typedef {import('estree-jsx').ImportExpression} ImportExpression\n * @typedef {import('estree-jsx').ImportSpecifier} ImportSpecifier\n * @typedef {import('estree-jsx').Literal} Literal\n * @typedef {import('estree-jsx').JSXElement} JSXElement\n * @typedef {import('estree-jsx').ModuleDeclaration} ModuleDeclaration\n * @typedef {import('estree-jsx').Node} Node\n * @typedef {import('estree-jsx').Program} Program\n * @typedef {import('estree-jsx').Property} Property\n * @typedef {import('estree-jsx').SimpleLiteral} SimpleLiteral\n * @typedef {import('estree-jsx').SpreadElement} SpreadElement\n * @typedef {import('estree-jsx').Statement} Statement\n * @typedef {import('estree-jsx').VariableDeclarator} VariableDeclarator\n */\n\n/**\n * @typedef RecmaDocumentOptions\n *   Configuration for internal plugin `recma-document`.\n * @property {'function-body' | 'program' | null | undefined} [outputFormat='program']\n *   Whether to use either `import` and `export` statements to get the runtime\n *   (and optionally provider) and export the content, or get values from\n *   `arguments` and return things.\n * @property {boolean | null | undefined} [useDynamicImport=false]\n *   Whether to keep `import` (and `export … from`) statements or compile them\n *   to dynamic `import()` instead.\n * @property {string | null | undefined} [baseUrl]\n *   Resolve `import`s (and `export … from`, and `import.meta.url`) relative to\n *   this URL.\n * @property {string | null | undefined} [pragma='React.createElement']\n *   Pragma for JSX (used in classic runtime).\n * @property {string | null | undefined} [pragmaFrag='React.Fragment']\n *   Pragma for JSX fragments (used in classic runtime).\n * @property {string | null | undefined} [pragmaImportSource='react']\n *   Where to import the identifier of `pragma` from (used in classic runtime).\n * @property {string | null | undefined} [jsxImportSource='react']\n *   Place to import automatic JSX runtimes from (used in automatic runtime).\n * @property {'automatic' | 'classic' | null | undefined} [jsxRuntime='automatic']\n *   JSX runtime to use.\n */\n\nimport { walk } from 'estree-walker'\nimport { analyze } from 'periscopic'\nimport { positionFromEstree } from 'unist-util-position-from-estree'\nimport { stringifyPosition } from 'unist-util-stringify-position'\nimport { create } from '../util/estree-util-create.js'\nimport { declarationToExpression } from '../util/estree-util-declaration-to-expression.js'\nimport { isDeclaration } from '../util/estree-util-is-declaration.js'\nimport { specifiersToDeclarations } from '../util/estree-util-specifiers-to-declarations.js'\n\n/**\n * A plugin to wrap the estree in `OrgContent`.\n *\n * @type {import('unified').Plugin<[RecmaDocumentOptions | null | undefined] | [], Program>}\n */\nexport function recmaDocument(options) {\n\t// Always given inside `@mdx-js/mdx`\n\t/* c8 ignore next */\n\tconst options_ = options || {}\n\tconst baseUrl = options_.baseUrl || undefined\n\tconst useDynamicImport = options_.useDynamicImport || undefined\n\tconst outputFormat = options_.outputFormat || 'program'\n\tconst pragma =\n\t\toptions_.pragma === undefined ? 'React.createElement' : options_.pragma\n\tconst pragmaFrag =\n\t\toptions_.pragmaFrag === undefined ? 'React.Fragment' : options_.pragmaFrag\n\tconst pragmaImportSource = options_.pragmaImportSource || 'react'\n\tconst jsxImportSource = options_.jsxImportSource || 'react'\n\tconst jsxRuntime = options_.jsxRuntime || 'automatic'\n\n\treturn (tree, file) => {\n\t\t/** @type {Array<[string, string] | string>} */\n\t\tconst exportedIdentifiers = []\n\t\t/** @type {Array<Directive | ModuleDeclaration | Statement>} */\n\t\tconst replacement = []\n\t\t/** @type {Array<string>} */\n\t\tconst pragmas = []\n\t\tlet exportAllCount = 0\n\t\t/** @type {ExportDefaultDeclaration | ExportSpecifier | undefined} */\n\t\tlet layout\n\t\t/** @type {boolean | undefined} */\n\t\tlet content\n\t\t/** @type {Node} */\n\t\tlet child\n\n\t\t// Patch missing comments, which types say could occur.\n\t\t/* c8 ignore next */\n\t\tif (!tree.comments) tree.comments = []\n\n\t\tif (jsxRuntime) {\n\t\t\tpragmas.push(`@jsxRuntime ${jsxRuntime}`)\n\t\t}\n\n\t\tif (jsxRuntime === 'automatic' && jsxImportSource) {\n\t\t\tpragmas.push(`@jsxImportSource ${jsxImportSource}`)\n\t\t}\n\n\t\tif (jsxRuntime === 'classic' && pragma) {\n\t\t\tpragmas.push(`@jsx ${pragma}`)\n\t\t}\n\n\t\tif (jsxRuntime === 'classic' && pragmaFrag) {\n\t\t\tpragmas.push(`@jsxFrag ${pragmaFrag}`)\n\t\t}\n\n\t\tif (pragmas.length > 0) {\n\t\t\ttree.comments.unshift({ type: 'Block', value: pragmas.join(' ') })\n\t\t}\n\n\t\tif (jsxRuntime === 'classic' && pragmaImportSource) {\n\t\t\tif (!pragma) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t'Missing `pragma` in classic runtime with `pragmaImportSource`'\n\t\t\t\t)\n\t\t\t}\n\n\t\t\thandleEsm({\n\t\t\t\ttype: 'ImportDeclaration',\n\t\t\t\tspecifiers: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'ImportDefaultSpecifier',\n\t\t\t\t\t\tlocal: { type: 'Identifier', name: pragma.split('.')[0] }\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tsource: { type: 'Literal', value: pragmaImportSource }\n\t\t\t})\n\t\t}\n\n\t\t// Find the `export default`, the JSX expression, and leave the rest\n\t\t// (import/exports) as they are.\n\t\tfor (child of tree.body) {\n\t\t\t// ```js\n\t\t\t// export default props => <>{props.children}</>\n\t\t\t// ```\n\t\t\t//\n\t\t\t// Treat it as an inline layout declaration.\n\t\t\tif (child.type === 'ExportDefaultDeclaration') {\n\t\t\t\tif (layout) {\n\t\t\t\t\tfile.fail(\n\t\t\t\t\t\t'Cannot specify multiple layouts (previous: ' +\n\t\t\t\t\t\t\tstringifyPosition(positionFromEstree(layout)) +\n\t\t\t\t\t\t\t')',\n\t\t\t\t\t\tpositionFromEstree(child),\n\t\t\t\t\t\t'recma-document:duplicate-layout'\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tlayout = child\n\t\t\t\treplacement.push({\n\t\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\t\tkind: 'const',\n\t\t\t\t\tdeclarations: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\tid: { type: 'Identifier', name: 'OrgLayout' },\n\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\tinit: isDeclaration(child.declaration)\n\t\t\t\t\t\t\t\t? declarationToExpression(child.declaration)\n\t\t\t\t\t\t\t\t: child.declaration\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t})\n\t\t\t}\n\t\t\t// ```js\n\t\t\t// export {a, b as c} from 'd'\n\t\t\t// ```\n\t\t\telse if (child.type === 'ExportNamedDeclaration' && child.source) {\n\t\t\t\tconst source = /** @type {SimpleLiteral} */ (child.source)\n\n\t\t\t\t// Remove `default` or `as default`, but not `default as`, specifier.\n\t\t\t\tchild.specifiers = child.specifiers.filter((specifier) => {\n\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\tif (specifier.exported.name === 'default') {\n\t\t\t\t\t\tif (layout) {\n\t\t\t\t\t\t\tfile.fail(\n\t\t\t\t\t\t\t\t'Cannot specify multiple layouts (previous: ' +\n\t\t\t\t\t\t\t\t\tstringifyPosition(positionFromEstree(layout)) +\n\t\t\t\t\t\t\t\t\t')',\n\t\t\t\t\t\t\t\tpositionFromEstree(child),\n\t\t\t\t\t\t\t\t'recma-document:duplicate-layout'\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tlayout = specifier\n\n\t\t\t\t\t\t// Make it just an import: `import OrgLayout from '…'`.\n\t\t\t\t\t\t/** @type {Array<ImportDefaultSpecifier | ImportSpecifier>} */\n\t\t\t\t\t\tconst specifiers = []\n\n\t\t\t\t\t\t// Default as default / something else as default.\n\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\tif (specifier.local.name === 'default') {\n\t\t\t\t\t\t\tspecifiers.push({\n\t\t\t\t\t\t\t\ttype: 'ImportDefaultSpecifier',\n\t\t\t\t\t\t\t\tlocal: { type: 'Identifier', name: 'OrgLayout' }\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t/** @type {ImportSpecifier} */\n\t\t\t\t\t\t\tconst importSpecifier = {\n\t\t\t\t\t\t\t\ttype: 'ImportSpecifier',\n\t\t\t\t\t\t\t\timported: specifier.local,\n\t\t\t\t\t\t\t\tlocal: { type: 'Identifier', name: 'OrgLayout' }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tcreate(specifier.local, importSpecifier)\n\t\t\t\t\t\t\tspecifiers.push(importSpecifier)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/** @type {Literal} */\n\t\t\t\t\t\tconst from = { type: 'Literal', value: source.value }\n\t\t\t\t\t\tcreate(source, from)\n\n\t\t\t\t\t\t/** @type {ImportDeclaration} */\n\t\t\t\t\t\tconst declaration = {\n\t\t\t\t\t\t\ttype: 'ImportDeclaration',\n\t\t\t\t\t\t\tspecifiers,\n\t\t\t\t\t\t\tsource: from\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcreate(specifier, declaration)\n\t\t\t\t\t\thandleEsm(declaration)\n\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\n\t\t\t\t\treturn true\n\t\t\t\t})\n\n\t\t\t\t// If there are other things imported, keep it.\n\t\t\t\tif (child.specifiers.length > 0) {\n\t\t\t\t\thandleExport(child)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// ```js\n\t\t\t// export {a, b as c}\n\t\t\t// export * from 'a'\n\t\t\t// ```\n\t\t\telse if (\n\t\t\t\tchild.type === 'ExportNamedDeclaration' ||\n\t\t\t\tchild.type === 'ExportAllDeclaration'\n\t\t\t) {\n\t\t\t\thandleExport(child)\n\t\t\t} else if (child.type === 'ImportDeclaration') {\n\t\t\t\thandleEsm(child)\n\t\t\t} else if (\n\t\t\t\tchild.type === 'ExpressionStatement' &&\n\t\t\t\t(child.expression.type === 'JSXFragment' ||\n\t\t\t\t\tchild.expression.type === 'JSXElement')\n\t\t\t) {\n\t\t\t\tcontent = true\n\t\t\t\treplacement.push(...createMdxContent(child.expression, Boolean(layout)))\n\t\t\t\t// The following catch-all branch is because plugins might’ve added\n\t\t\t\t// other things.\n\t\t\t\t// Normally, we only have import/export/jsx, but just add whatever’s\n\t\t\t\t// there.\n\t\t\t\t/* c8 ignore next 3 */\n\t\t\t} else {\n\t\t\t\treplacement.push(child)\n\t\t\t}\n\t\t}\n\n\t\t// If there was no JSX content at all, add an empty function.\n\t\tif (!content) {\n\t\t\treplacement.push(...createMdxContent(undefined, Boolean(layout)))\n\t\t}\n\n\t\texportedIdentifiers.push(['OrgContent', 'default'])\n\n\t\tif (outputFormat === 'function-body') {\n\t\t\treplacement.push({\n\t\t\t\ttype: 'ReturnStatement',\n\t\t\t\targument: {\n\t\t\t\t\ttype: 'ObjectExpression',\n\t\t\t\t\tproperties: [\n\t\t\t\t\t\t...Array.from({ length: exportAllCount }).map(\n\t\t\t\t\t\t\t/**\n\t\t\t\t\t\t\t * @param {undefined} _\n\t\t\t\t\t\t\t * @param {number} index\n\t\t\t\t\t\t\t * @returns {SpreadElement}\n\t\t\t\t\t\t\t */\n\t\t\t\t\t\t\t(_, index) => ({\n\t\t\t\t\t\t\t\ttype: 'SpreadElement',\n\t\t\t\t\t\t\t\targument: {\n\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\tname: `_exportAll${index + 1}`\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t),\n\t\t\t\t\t\t...exportedIdentifiers.map((d) => {\n\t\t\t\t\t\t\t/** @type {Property} */\n\t\t\t\t\t\t\tconst prop = {\n\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\tkind: 'init',\n\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\tcomputed: false,\n\t\t\t\t\t\t\t\tshorthand: typeof d === 'string',\n\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\tname: typeof d === 'string' ? d : d[1]\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\tname: typeof d === 'string' ? d : d[0]\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn prop\n\t\t\t\t\t\t})\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t})\n\t\t} else {\n\t\t\treplacement.push({\n\t\t\t\ttype: 'ExportDefaultDeclaration',\n\t\t\t\tdeclaration: { type: 'Identifier', name: 'OrgContent' }\n\t\t\t})\n\t\t}\n\n\t\ttree.body = replacement\n\n\t\tif (baseUrl) {\n\t\t\twalk(tree, {\n\t\t\t\tenter(node) {\n\t\t\t\t\tif (\n\t\t\t\t\t\tnode.type === 'MemberExpression' &&\n\t\t\t\t\t\t'object' in node &&\n\t\t\t\t\t\tnode.object.type === 'MetaProperty' &&\n\t\t\t\t\t\tnode.property.type === 'Identifier' &&\n\t\t\t\t\t\tnode.object.meta.name === 'import' &&\n\t\t\t\t\t\tnode.object.property.name === 'meta' &&\n\t\t\t\t\t\tnode.property.name === 'url'\n\t\t\t\t\t) {\n\t\t\t\t\t\t/** @type {SimpleLiteral} */\n\t\t\t\t\t\tconst replacement = { type: 'Literal', value: baseUrl }\n\t\t\t\t\t\tthis.replace(replacement)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\n\t\t/**\n\t\t * @param {ExportAllDeclaration | ExportNamedDeclaration} node\n\t\t * @returns {void}\n\t\t */\n\t\tfunction handleExport(node) {\n\t\t\tif (node.type === 'ExportNamedDeclaration') {\n\t\t\t\t// ```js\n\t\t\t\t// export function a() {}\n\t\t\t\t// export class A {}\n\t\t\t\t// export var a = 1\n\t\t\t\t// ```\n\t\t\t\tif (node.declaration) {\n\t\t\t\t\texportedIdentifiers.push(\n\t\t\t\t\t\t...analyze(node.declaration).scope.declarations.keys()\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\t// ```js\n\t\t\t\t// export {a, b as c}\n\t\t\t\t// export {a, b as c} from 'd'\n\t\t\t\t// ```\n\t\t\t\tfor (child of node.specifiers) {\n\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\texportedIdentifiers.push(child.exported.name)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\thandleEsm(node)\n\t\t}\n\n\t\t/**\n\t\t * @param {ExportAllDeclaration | ExportNamedDeclaration | ImportDeclaration} node\n\t\t * @returns {void}\n\t\t */\n\t\tfunction handleEsm(node) {\n\t\t\t// Rewrite the source of the `import` / `export … from`.\n\t\t\t// See: <https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier>\n\t\t\tif (baseUrl && node.source) {\n\t\t\t\tlet value = String(node.source.value)\n\n\t\t\t\ttry {\n\t\t\t\t\t// A full valid URL.\n\t\t\t\t\tvalue = String(new URL(value))\n\t\t\t\t} catch {\n\t\t\t\t\t// Relative: `/example.js`, `./example.js`, and `../example.js`.\n\t\t\t\t\tif (/^\\.{0,2}\\//.test(value)) {\n\t\t\t\t\t\tvalue = String(new URL(value, baseUrl))\n\t\t\t\t\t}\n\t\t\t\t\t// Otherwise, it’s a bare specifiers.\n\t\t\t\t\t// For example `some-package`, `@some-package`, and\n\t\t\t\t\t// `some-package/path`.\n\t\t\t\t\t// These are supported in Node and browsers plan to support them\n\t\t\t\t\t// with import maps (<https://github.com/WICG/import-maps>).\n\t\t\t\t}\n\n\t\t\t\t/** @type {Literal} */\n\t\t\t\tconst literal = { type: 'Literal', value }\n\t\t\t\tcreate(node.source, literal)\n\t\t\t\tnode.source = literal\n\t\t\t}\n\n\t\t\t/** @type {ModuleDeclaration | Statement | undefined} */\n\t\t\tlet replace\n\t\t\t/** @type {Expression} */\n\t\t\tlet init\n\n\t\t\tif (outputFormat === 'function-body') {\n\t\t\t\tif (\n\t\t\t\t\t// Always have a source:\n\t\t\t\t\tnode.type === 'ImportDeclaration' ||\n\t\t\t\t\tnode.type === 'ExportAllDeclaration' ||\n\t\t\t\t\t// Source optional:\n\t\t\t\t\t(node.type === 'ExportNamedDeclaration' && node.source)\n\t\t\t\t) {\n\t\t\t\t\tif (!useDynamicImport) {\n\t\t\t\t\t\tfile.fail(\n\t\t\t\t\t\t\t'Cannot use `import` or `export … from` in `evaluate` (outputting a function body) by default: please set `useDynamicImport: true` (and probably specify a `baseUrl`)',\n\t\t\t\t\t\t\tpositionFromEstree(node),\n\t\t\t\t\t\t\t'recma-document:invalid-esm-statement'\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\n\t\t\t\t\t// Just for types.\n\t\t\t\t\t/* c8 ignore next 3 */\n\t\t\t\t\tif (!node.source) {\n\t\t\t\t\t\tthrow new Error('Expected `node.source` to be defined')\n\t\t\t\t\t}\n\n\t\t\t\t\t// ```\n\t\t\t\t\t// import 'a'\n\t\t\t\t\t// //=> await import('a')\n\t\t\t\t\t// import a from 'b'\n\t\t\t\t\t// //=> const {default: a} = await import('b')\n\t\t\t\t\t// export {a, b as c} from 'd'\n\t\t\t\t\t// //=> const {a, c: b} = await import('d')\n\t\t\t\t\t// export * from 'a'\n\t\t\t\t\t// //=> const _exportAll0 = await import('a')\n\t\t\t\t\t// ```\n\t\t\t\t\t/** @type {ImportExpression} */\n\t\t\t\t\tconst argument = { type: 'ImportExpression', source: node.source }\n\t\t\t\t\tcreate(node, argument)\n\t\t\t\t\tinit = { type: 'AwaitExpression', argument }\n\n\t\t\t\t\tif (\n\t\t\t\t\t\t(node.type === 'ImportDeclaration' ||\n\t\t\t\t\t\t\tnode.type === 'ExportNamedDeclaration') &&\n\t\t\t\t\t\tnode.specifiers.length === 0\n\t\t\t\t\t) {\n\t\t\t\t\t\treplace = { type: 'ExpressionStatement', expression: init }\n\t\t\t\t\t} else {\n\t\t\t\t\t\treplace = {\n\t\t\t\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\t\t\t\tkind: 'const',\n\t\t\t\t\t\t\tdeclarations:\n\t\t\t\t\t\t\t\tnode.type === 'ExportAllDeclaration'\n\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\t\t\t\t\t\tid: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: `_exportAll${++exportAllCount}`\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tinit\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t: specifiersToDeclarations(node.specifiers, init)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else if (node.declaration) {\n\t\t\t\t\treplace = node.declaration\n\t\t\t\t} else {\n\t\t\t\t\t/** @type {Array<VariableDeclarator>} */\n\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\tconst declarators = node.specifiers\n\t\t\t\t\t\t.filter(\n\t\t\t\t\t\t\t// @ts-expect-error\n\t\t\t\t\t\t\t(specifier) => specifier.local.name !== specifier.exported.name\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.map((specifier) => ({\n\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\tid: specifier.exported,\n\t\t\t\t\t\t\tinit: specifier.local\n\t\t\t\t\t\t}))\n\n\t\t\t\t\tif (declarators.length > 0) {\n\t\t\t\t\t\treplace = {\n\t\t\t\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\t\t\t\tkind: 'const',\n\t\t\t\t\t\t\tdeclarations: declarators\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treplace = node\n\t\t\t}\n\n\t\t\tif (replace) {\n\t\t\t\treplacement.push(replace)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @param {Expression | undefined} [content]\n\t * @param {boolean | undefined} [hasInternalLayout]\n\t * @returns {Array<FunctionDeclaration>}\n\t */\n\tfunction createMdxContent(content, hasInternalLayout) {\n\t\t/** @type {JSXElement} */\n\t\tconst element = {\n\t\t\ttype: 'JSXElement',\n\t\t\topeningElement: {\n\t\t\t\ttype: 'JSXOpeningElement',\n\t\t\t\tname: { type: 'JSXIdentifier', name: 'OrgLayout' },\n\t\t\t\tattributes: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'JSXSpreadAttribute',\n\t\t\t\t\t\targument: { type: 'Identifier', name: 'props' }\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tselfClosing: false\n\t\t\t},\n\t\t\tclosingElement: {\n\t\t\t\ttype: 'JSXClosingElement',\n\t\t\t\tname: { type: 'JSXIdentifier', name: 'OrgLayout' }\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'JSXElement',\n\t\t\t\t\topeningElement: {\n\t\t\t\t\t\ttype: 'JSXOpeningElement',\n\t\t\t\t\t\tname: { type: 'JSXIdentifier', name: '_createOrgContent' },\n\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'JSXSpreadAttribute',\n\t\t\t\t\t\t\t\targument: { type: 'Identifier', name: 'props' }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tselfClosing: true\n\t\t\t\t\t},\n\t\t\t\t\tclosingElement: null,\n\t\t\t\t\tchildren: []\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\n\t\tlet result = /** @type {Expression} */ (element)\n\n\t\tif (!hasInternalLayout) {\n\t\t\tresult = {\n\t\t\t\ttype: 'ConditionalExpression',\n\t\t\t\ttest: { type: 'Identifier', name: 'OrgLayout' },\n\t\t\t\tconsequent: result,\n\t\t\t\talternate: {\n\t\t\t\t\ttype: 'CallExpression',\n\t\t\t\t\tcallee: { type: 'Identifier', name: '_createOrgContent' },\n\t\t\t\t\targuments: [{ type: 'Identifier', name: 'props' }],\n\t\t\t\t\toptional: false\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tlet argument = content || { type: 'Literal', value: null }\n\n\t\t// Unwrap a fragment of a single element.\n\t\tif (\n\t\t\targument &&\n\t\t\targument.type === 'JSXFragment' &&\n\t\t\targument.children.length === 1 &&\n\t\t\targument.children[0].type === 'JSXElement'\n\t\t) {\n\t\t\targument = argument.children[0]\n\t\t}\n\n\t\treturn [\n\t\t\t{\n\t\t\t\ttype: 'FunctionDeclaration',\n\t\t\t\tid: { type: 'Identifier', name: '_createOrgContent' },\n\t\t\t\tparams: [{ type: 'Identifier', name: 'props' }],\n\t\t\t\tbody: {\n\t\t\t\t\ttype: 'BlockStatement',\n\t\t\t\t\tbody: [{ type: 'ReturnStatement', argument }]\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\ttype: 'FunctionDeclaration',\n\t\t\t\tid: { type: 'Identifier', name: 'OrgContent' },\n\t\t\t\tparams: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: 'AssignmentPattern',\n\t\t\t\t\t\tleft: { type: 'Identifier', name: 'props' },\n\t\t\t\t\t\tright: { type: 'ObjectExpression', properties: [] }\n\t\t\t\t\t}\n\t\t\t\t],\n\t\t\t\tbody: {\n\t\t\t\t\ttype: 'BlockStatement',\n\t\t\t\t\tbody: [{ type: 'ReturnStatement', argument: result }]\n\t\t\t\t}\n\t\t\t}\n\t\t]\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/plugin/recma-jsx-rewrite.js",
    "content": "/**\n * @typedef {import('estree-jsx').Expression} Expression\n * @typedef {import('estree-jsx').Function} EstreeFunction\n * @typedef {import('estree-jsx').Identifier} Identifier\n * @typedef {import('estree-jsx').ImportSpecifier} ImportSpecifier\n * @typedef {import('estree-jsx').JSXElement} JSXElement\n * @typedef {import('estree-jsx').ModuleDeclaration} ModuleDeclaration\n * @typedef {import('estree-jsx').Node} Node\n * @typedef {import('estree-jsx').ObjectPattern} ObjectPattern\n * @typedef {import('estree-jsx').Program} Program\n * @typedef {import('estree-jsx').Property} Property\n * @typedef {import('estree-jsx').Statement} Statement\n * @typedef {import('estree-jsx').VariableDeclarator} VariableDeclarator\n *\n * @typedef {import('periscopic').Scope & {node: Node}} Scope\n */\n\n/**\n * @typedef RecmaJsxRewriteOptions\n *   Configuration for internal plugin `recma-jsx-rewrite`.\n * @property {'function-body' | 'program' | null | undefined} [outputFormat='program']\n *   Whether to use an import statement or `arguments[0]` to get the provider.\n * @property {string | null | undefined} [providerImportSource]\n *   Place to import a provider from.\n * @property {boolean | null | undefined} [development=false]\n *   Whether to add extra info to error messages in generated code.\n *\n *   This also results in the development automatic JSX runtime\n *   (`/jsx-dev-runtime`, `jsxDEV`) being used, which passes positional info to\n *   nodes.\n *   The default can be set to `true` in Node.js through environment variables:\n *   set `NODE_ENV=development`.\n *\n * @typedef StackEntry\n * @property {Array<string>} objects\n * @property {Array<string>} components\n * @property {Array<string>} tags\n * @property {Record<string, {node: JSXElement, component: boolean}>} references\n * @property {Map<string|number, string>} idToInvalidComponentName\n * @property {EstreeFunction} node\n */\n\nimport { name as isIdentifierName } from 'estree-util-is-identifier-name'\nimport { walk } from 'estree-walker'\nimport { analyze } from 'periscopic'\nimport { positionFromEstree } from 'unist-util-position-from-estree'\nimport { stringifyPosition } from 'unist-util-stringify-position'\nimport { specifiersToDeclarations } from '../util/estree-util-specifiers-to-declarations.js'\nimport { toBinaryAddition } from '../util/estree-util-to-binary-addition.js'\nimport {\n\ttoIdOrMemberExpression,\n\ttoJsxIdOrMemberExpression\n} from '../util/estree-util-to-id-or-member-expression.js'\n\nconst own = {}.hasOwnProperty\n\n/**\n * A plugin that rewrites JSX in functions to accept components as\n * `props.components` (when the function is called `_createOrgContent`), or from\n * a provider (if there is one).\n * It also makes sure that any undefined components are defined: either from\n * received components or as a function that throws an error.\n *\n * @type {import('unified').Plugin<[RecmaJsxRewriteOptions | null | undefined] | [], Program>}\n */\nexport function recmaJsxRewrite(options) {\n\t// Always given inside `@mdx-js/mdx`\n\t/* c8 ignore next */\n\tconst { development, providerImportSource, outputFormat } = options || {}\n\n\treturn (tree, file) => {\n\t\t// Find everything that’s defined in the top-level scope.\n\t\tconst scopeInfo = analyze(tree)\n\t\t/** @type {Array<StackEntry>} */\n\t\tconst fnStack = []\n\t\tlet importProvider = false\n\t\tlet createErrorHelper = false\n\t\t/** @type {Scope | undefined} */\n\t\tlet currentScope\n\n\t\twalk(tree, {\n\t\t\tenter(node) {\n\t\t\t\tconst newScope = /** @type {Scope | undefined} */ (\n\t\t\t\t\tscopeInfo.map.get(node)\n\t\t\t\t)\n\n\t\t\t\tif (\n\t\t\t\t\tnode.type === 'FunctionDeclaration' ||\n\t\t\t\t\tnode.type === 'FunctionExpression' ||\n\t\t\t\t\tnode.type === 'ArrowFunctionExpression'\n\t\t\t\t) {\n\t\t\t\t\tfnStack.push({\n\t\t\t\t\t\tobjects: [],\n\t\t\t\t\t\tcomponents: [],\n\t\t\t\t\t\ttags: [],\n\t\t\t\t\t\treferences: {},\n\t\t\t\t\t\tidToInvalidComponentName: new Map(),\n\t\t\t\t\t\tnode\n\t\t\t\t\t})\n\n\t\t\t\t\t// OrgContent only ever contains OrgLayout\n\t\t\t\t\tif (\n\t\t\t\t\t\tisNamedFunction(node, 'OrgContent') &&\n\t\t\t\t\t\tnewScope &&\n\t\t\t\t\t\t!inScope(newScope, 'OrgLayout')\n\t\t\t\t\t) {\n\t\t\t\t\t\tfnStack[0].components.push('OrgLayout')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst fnScope = fnStack[0]\n\t\t\t\tif (\n\t\t\t\t\t!fnScope ||\n\t\t\t\t\t(!isNamedFunction(fnScope.node, '_createOrgContent') &&\n\t\t\t\t\t\t!providerImportSource)\n\t\t\t\t) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (newScope) {\n\t\t\t\t\tnewScope.node = node\n\t\t\t\t\tcurrentScope = newScope\n\t\t\t\t}\n\n\t\t\t\tif (currentScope && node.type === 'JSXElement') {\n\t\t\t\t\tlet name = node.openingElement.name\n\n\t\t\t\t\t// `<x.y>`, `<Foo.Bar>`, `<x.y.z>`.\n\t\t\t\t\tif (name.type === 'JSXMemberExpression') {\n\t\t\t\t\t\t/** @type {Array<string>} */\n\t\t\t\t\t\tconst ids = []\n\n\t\t\t\t\t\t// Find the left-most identifier.\n\t\t\t\t\t\twhile (name.type === 'JSXMemberExpression') {\n\t\t\t\t\t\t\tids.unshift(name.property.name)\n\t\t\t\t\t\t\tname = name.object\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tids.unshift(name.name)\n\t\t\t\t\t\tconst fullId = ids.join('.')\n\t\t\t\t\t\tconst id = name.name\n\n\t\t\t\t\t\tconst isInScope = inScope(currentScope, id)\n\n\t\t\t\t\t\tif (!own.call(fnScope.references, fullId)) {\n\t\t\t\t\t\t\tconst parentScope = /** @type {Scope | undefined} */ (\n\t\t\t\t\t\t\t\tcurrentScope.parent\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\t!isInScope ||\n\t\t\t\t\t\t\t\t// If the parent scope is `_createOrgContent`, then this\n\t\t\t\t\t\t\t\t// references a component we can add a check statement for.\n\t\t\t\t\t\t\t\t(parentScope &&\n\t\t\t\t\t\t\t\t\tparentScope.node.type === 'FunctionDeclaration' &&\n\t\t\t\t\t\t\t\t\tisNamedFunction(parentScope.node, '_createOrgContent'))\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tfnScope.references[fullId] = { node, component: true }\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!fnScope.objects.includes(id) && !isInScope) {\n\t\t\t\t\t\t\tfnScope.objects.push(id)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// `<xml:thing>`.\n\t\t\t\t\telse if (name.type === 'JSXNamespacedName') {\n\t\t\t\t\t\t// Ignore namespaces.\n\t\t\t\t\t}\n\t\t\t\t\t// If the name is a valid ES identifier, and it doesn’t start with a\n\t\t\t\t\t// lowercase letter, it’s a component.\n\t\t\t\t\t// For example, `$foo`, `_bar`, `Baz` are all component names.\n\t\t\t\t\t// But `foo` and `b-ar` are tag names.\n\t\t\t\t\telse if (isIdentifierName(name.name) && !/^[a-z]/.test(name.name)) {\n\t\t\t\t\t\tconst id = name.name\n\n\t\t\t\t\t\tif (!inScope(currentScope, id)) {\n\t\t\t\t\t\t\t// No need to add an error for an undefined layout — we use an\n\t\t\t\t\t\t\t// `if` later.\n\t\t\t\t\t\t\tif (id !== 'OrgLayout' && !own.call(fnScope.references, id)) {\n\t\t\t\t\t\t\t\tfnScope.references[id] = { node, component: true }\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (!fnScope.components.includes(id)) {\n\t\t\t\t\t\t\t\tfnScope.components.push(id)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t// @ts-expect-error Allow fields passed through from mdast through hast to\n\t\t\t\t\t// esast.\n\t\t\t\t\telse if (node.data?._mdxExplicitJsx) {\n\t\t\t\t\t\t// Do not turn explicit JSX into components from `_components`.\n\t\t\t\t\t\t// As in, a given `h1` component is used for `# heading` (next case),\n\t\t\t\t\t\t// but not for `<h1>heading</h1>`.\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst id = name.name\n\n\t\t\t\t\t\tif (!fnScope.tags.includes(id)) {\n\t\t\t\t\t\t\tfnScope.tags.push(id)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t/** @type {Array<string | number>} */\n\t\t\t\t\t\tlet jsxIdExpression = ['_components', id]\n\t\t\t\t\t\tif (isIdentifierName(id) === false) {\n\t\t\t\t\t\t\tlet invalidComponentName =\n\t\t\t\t\t\t\t\tfnScope.idToInvalidComponentName.get(id)\n\t\t\t\t\t\t\tif (invalidComponentName === undefined) {\n\t\t\t\t\t\t\t\tinvalidComponentName = `_component${fnScope.idToInvalidComponentName.size}`\n\t\t\t\t\t\t\t\tfnScope.idToInvalidComponentName.set(id, invalidComponentName)\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tjsxIdExpression = [invalidComponentName]\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tnode.openingElement.name =\n\t\t\t\t\t\t\ttoJsxIdOrMemberExpression(jsxIdExpression)\n\n\t\t\t\t\t\tif (node.closingElement) {\n\t\t\t\t\t\t\tnode.closingElement.name =\n\t\t\t\t\t\t\t\ttoJsxIdOrMemberExpression(jsxIdExpression)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tleave(node) {\n\t\t\t\t/** @type {Array<Property>} */\n\t\t\t\tconst defaults = []\n\t\t\t\t/** @type {Array<string>} */\n\t\t\t\tconst actual = []\n\t\t\t\t/** @type {Array<Expression>} */\n\t\t\t\tconst parameters = []\n\t\t\t\t/** @type {Array<VariableDeclarator>} */\n\t\t\t\tconst declarations = []\n\n\t\t\t\tif (currentScope && currentScope.node === node) {\n\t\t\t\t\t// @ts-expect-error: `node`s were patched when entering.\n\t\t\t\t\tcurrentScope = currentScope.parent\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tnode.type === 'FunctionDeclaration' ||\n\t\t\t\t\tnode.type === 'FunctionExpression' ||\n\t\t\t\t\tnode.type === 'ArrowFunctionExpression'\n\t\t\t\t) {\n\t\t\t\t\tconst fn = node\n\t\t\t\t\tconst scope = fnStack[fnStack.length - 1]\n\t\t\t\t\t/** @type {string} */\n\t\t\t\t\tlet name\n\n\t\t\t\t\tfor (name of scope.tags) {\n\t\t\t\t\t\tdefaults.push({\n\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\tkind: 'init',\n\t\t\t\t\t\t\tkey: isIdentifierName(name)\n\t\t\t\t\t\t\t\t? { type: 'Identifier', name }\n\t\t\t\t\t\t\t\t: { type: 'Literal', value: name },\n\t\t\t\t\t\t\tvalue: { type: 'Literal', value: name },\n\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\tshorthand: false,\n\t\t\t\t\t\t\tcomputed: false\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\tactual.push(...scope.components)\n\n\t\t\t\t\tfor (name of scope.objects) {\n\t\t\t\t\t\t// In some cases, a component is used directly (`<X>`) but it’s also\n\t\t\t\t\t\t// used as an object (`<X.Y>`).\n\t\t\t\t\t\tif (!actual.includes(name)) {\n\t\t\t\t\t\t\tactual.push(name)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/** @type {Array<Statement>} */\n\t\t\t\t\tconst statements = []\n\n\t\t\t\t\tif (\n\t\t\t\t\t\tdefaults.length > 0 ||\n\t\t\t\t\t\tactual.length > 0 ||\n\t\t\t\t\t\tscope.idToInvalidComponentName.size > 0\n\t\t\t\t\t) {\n\t\t\t\t\t\tif (providerImportSource) {\n\t\t\t\t\t\t\timportProvider = true\n\t\t\t\t\t\t\tparameters.push({\n\t\t\t\t\t\t\t\ttype: 'CallExpression',\n\t\t\t\t\t\t\t\tcallee: { type: 'Identifier', name: '_provideComponents' },\n\t\t\t\t\t\t\t\targuments: [],\n\t\t\t\t\t\t\t\toptional: false\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Accept `components` as a prop if this is the `OrgContent` or\n\t\t\t\t\t\t// `_createOrgContent` function.\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tisNamedFunction(scope.node, 'OrgContent') ||\n\t\t\t\t\t\t\tisNamedFunction(scope.node, '_createOrgContent')\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tparameters.push(toIdOrMemberExpression(['props', 'components']))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (defaults.length > 0 || parameters.length > 1) {\n\t\t\t\t\t\t\tparameters.unshift({\n\t\t\t\t\t\t\t\ttype: 'ObjectExpression',\n\t\t\t\t\t\t\t\tproperties: defaults\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// If we’re getting components from several sources, merge them.\n\t\t\t\t\t\t/** @type {Expression} */\n\t\t\t\t\t\tlet componentsInit =\n\t\t\t\t\t\t\tparameters.length > 1\n\t\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t\ttype: 'CallExpression',\n\t\t\t\t\t\t\t\t\t\tcallee: toIdOrMemberExpression(['Object', 'assign']),\n\t\t\t\t\t\t\t\t\t\targuments: parameters,\n\t\t\t\t\t\t\t\t\t\toptional: false\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t: parameters[0].type === 'MemberExpression'\n\t\t\t\t\t\t\t\t\t? // If we’re only getting components from `props.components`,\n\t\t\t\t\t\t\t\t\t\t// make sure it’s defined.\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\ttype: 'LogicalExpression',\n\t\t\t\t\t\t\t\t\t\t\toperator: '||',\n\t\t\t\t\t\t\t\t\t\t\tleft: parameters[0],\n\t\t\t\t\t\t\t\t\t\t\tright: { type: 'ObjectExpression', properties: [] }\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t: parameters[0]\n\n\t\t\t\t\t\t/** @type {ObjectPattern | undefined} */\n\t\t\t\t\t\tlet componentsPattern\n\n\t\t\t\t\t\t// Add components to scope.\n\t\t\t\t\t\t// For `['MyComponent', 'OrgLayout']` this generates:\n\t\t\t\t\t\t// ```js\n\t\t\t\t\t\t// const {MyComponent, wrapper: OrgLayout} = _components\n\t\t\t\t\t\t// ```\n\t\t\t\t\t\t// Note that OrgLayout is special as it’s taken from\n\t\t\t\t\t\t// `_components.wrapper`.\n\t\t\t\t\t\tif (actual.length > 0) {\n\t\t\t\t\t\t\tcomponentsPattern = {\n\t\t\t\t\t\t\t\ttype: 'ObjectPattern',\n\t\t\t\t\t\t\t\tproperties: actual.map((name) => ({\n\t\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\t\tkind: 'init',\n\t\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\tname: name === 'OrgLayout' ? 'wrapper' : name\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tvalue: { type: 'Identifier', name },\n\t\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\t\tshorthand: name !== 'OrgLayout',\n\t\t\t\t\t\t\t\t\tcomputed: false\n\t\t\t\t\t\t\t\t}))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (scope.tags.length > 0) {\n\t\t\t\t\t\t\tdeclarations.push({\n\t\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\t\tid: { type: 'Identifier', name: '_components' },\n\t\t\t\t\t\t\t\tinit: componentsInit\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\tcomponentsInit = { type: 'Identifier', name: '_components' }\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (isNamedFunction(scope.node, '_createOrgContent')) {\n\t\t\t\t\t\t\tfor (const [\n\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\tcomponentName\n\t\t\t\t\t\t\t] of scope.idToInvalidComponentName) {\n\t\t\t\t\t\t\t\t// For JSX IDs that can’t be represented as JavaScript IDs (as in,\n\t\t\t\t\t\t\t\t// those with dashes, such as `custom-element`), generate a\n\t\t\t\t\t\t\t\t// separate variable that is a valid JS ID (such as `_component0`),\n\t\t\t\t\t\t\t\t// and takes it from components:\n\t\t\t\t\t\t\t\t// `const _component0 = _components['custom-element']`\n\t\t\t\t\t\t\t\tdeclarations.push({\n\t\t\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\t\t\tid: { type: 'Identifier', name: componentName },\n\t\t\t\t\t\t\t\t\tinit: {\n\t\t\t\t\t\t\t\t\t\ttype: 'MemberExpression',\n\t\t\t\t\t\t\t\t\t\tobject: { type: 'Identifier', name: '_components' },\n\t\t\t\t\t\t\t\t\t\tproperty: { type: 'Literal', value: id },\n\t\t\t\t\t\t\t\t\t\tcomputed: true,\n\t\t\t\t\t\t\t\t\t\toptional: false\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (componentsPattern) {\n\t\t\t\t\t\t\tdeclarations.push({\n\t\t\t\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\t\t\t\tid: componentsPattern,\n\t\t\t\t\t\t\t\tinit: componentsInit\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (declarations.length > 0) {\n\t\t\t\t\t\t\tstatements.push({\n\t\t\t\t\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\t\t\t\t\tkind: 'const',\n\t\t\t\t\t\t\t\tdeclarations\n\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t/** @type {string} */\n\t\t\t\t\tlet key\n\n\t\t\t\t\t// Add partials (so for `x.y.z` it’d generate `x` and `x.y` too).\n\t\t\t\t\tfor (key in scope.references) {\n\t\t\t\t\t\tif (own.call(scope.references, key)) {\n\t\t\t\t\t\t\tconst parts = key.split('.')\n\t\t\t\t\t\t\tlet index = 0\n\t\t\t\t\t\t\twhile (++index < parts.length) {\n\t\t\t\t\t\t\t\tconst partial = parts.slice(0, index).join('.')\n\t\t\t\t\t\t\t\tif (!own.call(scope.references, partial)) {\n\t\t\t\t\t\t\t\t\tscope.references[partial] = {\n\t\t\t\t\t\t\t\t\t\tnode: scope.references[key].node,\n\t\t\t\t\t\t\t\t\t\tcomponent: false\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst references = Object.keys(scope.references).sort()\n\t\t\t\t\tlet index = -1\n\t\t\t\t\twhile (++index < references.length) {\n\t\t\t\t\t\tconst id = references[index]\n\t\t\t\t\t\tconst info = scope.references[id]\n\t\t\t\t\t\tconst place = stringifyPosition(positionFromEstree(info.node))\n\t\t\t\t\t\t/** @type {Array<Expression>} */\n\t\t\t\t\t\tconst parameters = [\n\t\t\t\t\t\t\t{ type: 'Literal', value: id },\n\t\t\t\t\t\t\t{ type: 'Literal', value: info.component }\n\t\t\t\t\t\t]\n\n\t\t\t\t\t\tcreateErrorHelper = true\n\n\t\t\t\t\t\tif (development && place !== '1:1-1:1') {\n\t\t\t\t\t\t\tparameters.push({ type: 'Literal', value: place })\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstatements.push({\n\t\t\t\t\t\t\ttype: 'IfStatement',\n\t\t\t\t\t\t\ttest: {\n\t\t\t\t\t\t\t\ttype: 'UnaryExpression',\n\t\t\t\t\t\t\t\toperator: '!',\n\t\t\t\t\t\t\t\tprefix: true,\n\t\t\t\t\t\t\t\targument: toIdOrMemberExpression(id.split('.'))\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tconsequent: {\n\t\t\t\t\t\t\t\ttype: 'ExpressionStatement',\n\t\t\t\t\t\t\t\texpression: {\n\t\t\t\t\t\t\t\t\ttype: 'CallExpression',\n\t\t\t\t\t\t\t\t\tcallee: { type: 'Identifier', name: '_missingMdxReference' },\n\t\t\t\t\t\t\t\t\targuments: parameters,\n\t\t\t\t\t\t\t\t\toptional: false\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\talternate: null\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\n\t\t\t\t\tif (statements.length > 0) {\n\t\t\t\t\t\t// Arrow functions with an implied return:\n\t\t\t\t\t\tif (fn.body.type !== 'BlockStatement') {\n\t\t\t\t\t\t\tfn.body = {\n\t\t\t\t\t\t\t\ttype: 'BlockStatement',\n\t\t\t\t\t\t\t\tbody: [{ type: 'ReturnStatement', argument: fn.body }]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfn.body.body.unshift(...statements)\n\t\t\t\t\t}\n\n\t\t\t\t\tfnStack.pop()\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\t// If a provider is used (and can be used), import it.\n\t\tif (importProvider && providerImportSource) {\n\t\t\ttree.body.unshift(\n\t\t\t\tcreateImportProvider(providerImportSource, outputFormat)\n\t\t\t)\n\t\t}\n\n\t\t// If potentially missing components are used.\n\t\tif (createErrorHelper) {\n\t\t\t/** @type {Array<Expression>} */\n\t\t\tconst message = [\n\t\t\t\t{ type: 'Literal', value: 'Expected ' },\n\t\t\t\t{\n\t\t\t\t\ttype: 'ConditionalExpression',\n\t\t\t\t\ttest: { type: 'Identifier', name: 'component' },\n\t\t\t\t\tconsequent: { type: 'Literal', value: 'component' },\n\t\t\t\t\talternate: { type: 'Literal', value: 'object' }\n\t\t\t\t},\n\t\t\t\t{ type: 'Literal', value: ' `' },\n\t\t\t\t{ type: 'Identifier', name: 'id' },\n\t\t\t\t{\n\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\tvalue:\n\t\t\t\t\t\t'` to be defined: you likely forgot to import, pass, or provide it.'\n\t\t\t\t}\n\t\t\t]\n\n\t\t\t/** @type {Array<Identifier>} */\n\t\t\tconst parameters = [\n\t\t\t\t{ type: 'Identifier', name: 'id' },\n\t\t\t\t{ type: 'Identifier', name: 'component' }\n\t\t\t]\n\n\t\t\tif (development) {\n\t\t\t\tmessage.push({\n\t\t\t\t\ttype: 'ConditionalExpression',\n\t\t\t\t\ttest: { type: 'Identifier', name: 'place' },\n\t\t\t\t\tconsequent: toBinaryAddition([\n\t\t\t\t\t\t{ type: 'Literal', value: '\\nIt’s referenced in your code at `' },\n\t\t\t\t\t\t{ type: 'Identifier', name: 'place' },\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\t\tvalue: `${file.path ? `\\` in \\`${file.path}` : ''}\\``\n\t\t\t\t\t\t}\n\t\t\t\t\t]),\n\t\t\t\t\talternate: { type: 'Literal', value: '' }\n\t\t\t\t})\n\n\t\t\t\tparameters.push({ type: 'Identifier', name: 'place' })\n\t\t\t}\n\n\t\t\ttree.body.push({\n\t\t\t\ttype: 'FunctionDeclaration',\n\t\t\t\tid: { type: 'Identifier', name: '_missingMdxReference' },\n\t\t\t\tgenerator: false,\n\t\t\t\tasync: false,\n\t\t\t\tparams: parameters,\n\t\t\t\tbody: {\n\t\t\t\t\ttype: 'BlockStatement',\n\t\t\t\t\tbody: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'ThrowStatement',\n\t\t\t\t\t\t\targument: {\n\t\t\t\t\t\t\t\ttype: 'NewExpression',\n\t\t\t\t\t\t\t\tcallee: { type: 'Identifier', name: 'Error' },\n\t\t\t\t\t\t\t\targuments: [toBinaryAddition(message)]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t})\n\t\t}\n\t}\n}\n\n/**\n * @param {string} providerImportSource\n * @param {RecmaJsxRewriteOptions['outputFormat']} outputFormat\n * @returns {Statement | ModuleDeclaration}\n */\nfunction createImportProvider(providerImportSource, outputFormat) {\n\t/** @type {Array<ImportSpecifier>} */\n\tconst specifiers = [\n\t\t{\n\t\t\ttype: 'ImportSpecifier',\n\t\t\timported: { type: 'Identifier', name: 'useOrgComponents' },\n\t\t\tlocal: { type: 'Identifier', name: '_provideComponents' }\n\t\t}\n\t]\n\n\treturn outputFormat === 'function-body'\n\t\t? {\n\t\t\t\ttype: 'VariableDeclaration',\n\t\t\t\tkind: 'const',\n\t\t\t\tdeclarations: specifiersToDeclarations(\n\t\t\t\t\tspecifiers,\n\t\t\t\t\ttoIdOrMemberExpression(['arguments', 0])\n\t\t\t\t)\n\t\t\t}\n\t\t: {\n\t\t\t\ttype: 'ImportDeclaration',\n\t\t\t\tspecifiers,\n\t\t\t\tsource: { type: 'Literal', value: providerImportSource }\n\t\t\t}\n}\n\n/**\n * @param {EstreeFunction} node\n * @param {string} name\n * @returns {boolean}\n */\nfunction isNamedFunction(node, name) {\n\treturn Boolean(node && 'id' in node && node.id && node.id.name === name)\n}\n\n/**\n * @param {Scope} scope\n * @param {string} id\n * @returns {boolean}\n */\nfunction inScope(scope, id) {\n\t/** @type {Scope | undefined} */\n\tlet currentScope = scope\n\n\twhile (currentScope) {\n\t\tif (currentScope.declarations.has(id)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// @ts-expect-error: `node`s have been added when entering.\n\t\tcurrentScope = currentScope.parent\n\t}\n\n\treturn false\n}\n"
  },
  {
    "path": "packages/orgx/lib/plugin/rehype-recma.js",
    "content": "/**\n * @import {Root} from 'hast'\n * @import {Program, Expression, ModuleDeclaration} from 'estree'\n * @typedef {import('hast-util-to-estree').Options} Options\n */\n\nimport { Parser } from 'acorn'\nimport jsx from 'acorn-jsx'\nimport { toEstree } from 'hast-util-to-estree'\nimport renderError from '../util/render-error.js'\n\n/**\n * Plugin to transform HTML (hast) to JS (estree).\n *\n * @param {Options | null | undefined} [options]\n *   Configuration (optional).\n * @returns\n *   Transform.\n */\nexport default function rehypeRecma(options) {\n\t/**\n\t * @param {Root} tree\n\t *   Tree (hast).\n\t * @returns {Program}\n\t *   Program (esast).\n\t */\n\treturn function (tree) {\n\t\tconst data = tree.data || {}\n\t\t/** @type {ModuleDeclaration[]} */\n\t\tconst prepend = []\n\t\tObject.entries(data).forEach(([k, v]) => {\n\t\t\tif (k === 'layout') {\n\t\t\t\tprepend.push({\n\t\t\t\t\ttype: 'ImportDeclaration',\n\t\t\t\t\tspecifiers: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'ImportDefaultSpecifier',\n\t\t\t\t\t\t\tlocal: {\n\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\tname: 'OrgLayout'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t],\n\t\t\t\t\tsource: {\n\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\tvalue: `${v}`,\n\t\t\t\t\t\traw: `'${v}'`\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\tprepend.push(createExport(k, v))\n\t\t\t}\n\t\t})\n\n\t\tconst estree = toEstree(tree, { ...options, handlers: { jsx: handleJsx } })\n\t\testree.body.unshift(...prepend)\n\t\treturn estree\n\t}\n}\n\nconst jsxParser = Parser.extend(jsx())\n\n/**\n * @param {import('acorn').Node | Program} node\n * @returns {node is Program}\n */\nfunction isProgram(node) {\n\treturn node.type === 'Program'\n}\n\n/**\n * @param {string} code\n */\nfunction parse(code) {\n\ttry {\n\t\treturn jsxParser.parse(code, {\n\t\t\tsourceType: 'module',\n\t\t\tecmaVersion: 2020\n\t\t})\n\t} catch (err) {\n\t\t// @ts-expect-error\n\t\treturn renderError(err)\n\t}\n}\n\n/** @type {import(\"hast-util-to-estree\").Handle} */\nexport const handleJsx = (node, state) => {\n\tconst skipImport = false\n\tconst estree = parse(node.value)\n\n\t/** @type {Expression[]} */\n\tconst expressions = []\n\n\tif (isProgram(estree)) {\n\t\testree.body.forEach((child) => {\n\t\t\tif (child.type === 'ImportDeclaration') {\n\t\t\t\tif (!skipImport) {\n\t\t\t\t\tstate.esm.push(child)\n\t\t\t\t}\n\t\t\t} else if (child.type === 'ExpressionStatement') {\n\t\t\t\texpressions.push(child.expression)\n\t\t\t} else if (\n\t\t\t\tchild.type === 'ExportDefaultDeclaration' ||\n\t\t\t\tchild.type === 'ExportNamedDeclaration'\n\t\t\t) {\n\t\t\t\tstate.esm.push(child)\n\t\t\t} else {\n\t\t\t\tthrow new Error(`unexpected node: ${child.type}`)\n\t\t\t}\n\t\t})\n\t}\n\n\t// @ts-expect-error: array works\n\t// https://github.com/syntax-tree/hast-util-to-estree/blob/c0c4bd33583abade25c4f4e248a06cb1ec8c3aff/lib/state.js#L215\n\treturn expressions\n}\n\n/**\n * @param {string} text\n * @returns {string}\n */\nfunction removeQuotes(text) {\n\treturn text.trim().replace(/^[\"'](.+(?=[\"']$))[\"']$/, '$1')\n}\n\n/**\n * @param {string} k\n * @param {any} v\n * @returns {ModuleDeclaration}\n */\nfunction createExport(k, v) {\n\t/** @type {(text: string) => Expression} */\n\tconst createLiteral = (text) => {\n\t\tconst value = removeQuotes(`${text}`)\n\t\treturn { type: 'Literal', value, raw: `'${value}'` }\n\t}\n\t/** @type {Expression} */\n\tconst init = Array.isArray(v)\n\t\t? {\n\t\t\t\ttype: 'ArrayExpression',\n\t\t\t\telements: v.map(createLiteral)\n\t\t\t}\n\t\t: createLiteral(v)\n\treturn {\n\t\ttype: 'ExportNamedDeclaration',\n\t\tdeclaration: {\n\t\t\ttype: 'VariableDeclaration',\n\t\t\tdeclarations: [\n\t\t\t\t{\n\t\t\t\t\ttype: 'VariableDeclarator',\n\t\t\t\t\tid: { type: 'Identifier', name: k },\n\t\t\t\t\tinit\n\t\t\t\t}\n\t\t\t],\n\t\t\tkind: 'const'\n\t\t},\n\t\tspecifiers: [],\n\t\tsource: null\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/run.js",
    "content": "/** @type {new (code: string, ...args: Array<unknown>) => Function} **/\nconst AsyncFunction = Object.getPrototypeOf(run).constructor\n\n/**\n * Asynchronously run code.\n *\n * @param {{toString(): string}} file\n *   JS document to run.\n * @param {unknown} options\n *   Parameter.\n * @return {Promise<any>}\n *   Anything.\n */\nexport async function run(file, options) {\n\treturn new AsyncFunction(String(file))(options)\n}\n\n/**\n * Synchronously run code.\n *\n * @param {{toString(): string}} file\n *   JS document to run.\n * @param {unknown} options\n *   Parameter.\n * @return {any}\n *   Anything.\n */\nexport function runSync(file, options) {\n\t// eslint-disable-next-line no-new-func\n\treturn new Function(String(file))(options)\n}\n"
  },
  {
    "path": "packages/orgx/lib/types.ts",
    "content": "type FunctionComponent<Props> = (props: Props) => React.JSX.Element | null\ntype ClassComponent<Props> = new (props: Props) => React.JSX.ElementClass\ntype Component<Props> =\n\t| FunctionComponent<Props>\n\t| ClassComponent<Props>\n\t| keyof React.JSX.IntrinsicElements\n\ninterface NestedOrgComponents {\n\t[key: string]: NestedOrgComponents | Component<any>\n}\n\nexport type OrgComponents = NestedOrgComponents & {\n\t[Key in keyof React.JSX.IntrinsicElements]?: Component<\n\t\tReact.JSX.IntrinsicElements[Key]\n\t>\n} & {\n\t/**\n\t * If a wrapper component is defined, the org content will be wrapped inside of it.\n\t */\n\twrapper?: Component<any>\n}\n\nexport interface OrgProps {\n\t/**\n\t * Which props exactly may be passed into the component depends on the contents of the org\n\t * file.\n\t */\n\t[key: string]: unknown\n\n\t/**\n\t * This prop may be used to customize how certain components are rendered.\n\t */\n\tcomponents?: OrgComponents\n}\n\nexport type OrgContent = (props: OrgProps) => React.JSX.Element\n\nexport interface OrgModule {\n\t/**\n\t * This could be any value that is exported from the org file.\n\t */\n\t[key: string]: unknown\n\n\t/**\n\t * A functional React.JSX component which renders the content of the org file.\n\t */\n\tdefault: OrgContent\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-create.js",
    "content": "/**\n * @typedef {import('estree-jsx').Node} Node\n */\n\n/**\n * @param {Node} from\n *   Node to take from.\n * @param {Node} to\n *   Node to add to.\n * @returns {void}\n *   Nothing.\n */\nexport function create(from, to) {\n\t/** @type {Array<keyof Node>} */\n\t// @ts-expect-error: `start`, `end`, `comments` are custom Acorn fields.\n\tconst fields = ['start', 'end', 'loc', 'range', 'comments']\n\tlet index = -1\n\n\twhile (++index < fields.length) {\n\t\tconst field = fields[index]\n\n\t\tif (field in from) {\n\t\t\t// @ts-expect-error: assume they’re settable.\n\t\t\tto[field] = from[field]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-declaration-to-expression.js",
    "content": "/**\n * @typedef {import('estree-jsx').Declaration} Declaration\n * @typedef {import('estree-jsx').Expression} Expression\n */\n\n/**\n * Turn a declaration into an expression.\n *\n * Doesn’t work for variable declarations, but that’s fine for our use case\n * because currently we’re using this utility for export default declarations,\n * which can’t contain variable declarations.\n *\n * @param {Declaration} declaration\n *   Declaration.\n * @returns {Expression}\n *   Expression.\n */\nexport function declarationToExpression(declaration) {\n\tif (declaration.type === 'FunctionDeclaration') {\n\t\treturn { ...declaration, type: 'FunctionExpression' }\n\t}\n\n\tif (declaration.type === 'ClassDeclaration') {\n\t\treturn { ...declaration, type: 'ClassExpression' }\n\t\t/* Internal utility so the next shouldn’t happen or a maintainer is making a\n\t\t * mistake. */\n\t\t/* c8 ignore next 4 */\n\t}\n\n\t// Probably `VariableDeclaration`.\n\tthrow new Error(`Cannot turn \\`${declaration.type}\\` into an expression`)\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-is-declaration.js",
    "content": "/**\n * @typedef {import('estree-jsx').Node} Node\n * @typedef {import('estree-jsx').Declaration} Declaration\n */\n\n/**\n * Check if `node` is a declaration.\n *\n * @param {Node} node\n *   Node to check.\n * @returns {node is Declaration}\n *   Whether `node` is a declaration.\n */\nexport function isDeclaration(node) {\n\treturn Boolean(\n\t\tnode.type === 'FunctionDeclaration' ||\n\t\t\tnode.type === 'ClassDeclaration' ||\n\t\t\tnode.type === 'VariableDeclaration'\n\t)\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-specifiers-to-declarations.js",
    "content": "/**\n * @typedef {import('estree-jsx').AssignmentProperty} AssignmentProperty\n * @typedef {import('estree-jsx').ExportSpecifier} ExportSpecifier\n * @typedef {import('estree-jsx').Expression} Expression\n * @typedef {import('estree-jsx').Identifier} Identifier\n * @typedef {import('estree-jsx').ImportDefaultSpecifier} ImportDefaultSpecifier\n * @typedef {import('estree-jsx').ImportNamespaceSpecifier} ImportNamespaceSpecifier\n * @typedef {import('estree-jsx').ImportSpecifier} ImportSpecifier\n * @typedef {import('estree-jsx').VariableDeclarator} VariableDeclarator\n */\n\nimport { create } from './estree-util-create.js'\n\n/**\n * @param {Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier | ExportSpecifier>} specifiers\n * @param {Expression} init\n * @returns {Array<VariableDeclarator>}\n */\nexport function specifiersToDeclarations(specifiers, init) {\n\tlet index = -1\n\t/** @type {Array<VariableDeclarator>} */\n\tconst declarations = []\n\t/** @type {Array<ImportSpecifier | ImportDefaultSpecifier | ExportSpecifier>} */\n\tconst otherSpecifiers = []\n\t// Can only be one according to JS syntax.\n\t/** @type {ImportNamespaceSpecifier | undefined} */\n\tlet importNamespaceSpecifier\n\n\twhile (++index < specifiers.length) {\n\t\tconst specifier = specifiers[index]\n\n\t\tif (specifier.type === 'ImportNamespaceSpecifier') {\n\t\t\timportNamespaceSpecifier = specifier\n\t\t} else {\n\t\t\totherSpecifiers.push(specifier)\n\t\t}\n\t}\n\n\tif (importNamespaceSpecifier) {\n\t\t/** @type {VariableDeclarator} */\n\t\tconst declarator = {\n\t\t\ttype: 'VariableDeclarator',\n\t\t\tid: importNamespaceSpecifier.local,\n\t\t\tinit\n\t\t}\n\t\tcreate(importNamespaceSpecifier, declarator)\n\t\tdeclarations.push(declarator)\n\t}\n\n\tdeclarations.push({\n\t\ttype: 'VariableDeclarator',\n\t\tid: {\n\t\t\ttype: 'ObjectPattern',\n\t\t\tproperties: otherSpecifiers.map((specifier) => {\n\t\t\t\t/** @type {Identifier} */\n\t\t\t\t// @ts-expect-error: fine.\n\t\t\t\tlet key =\n\t\t\t\t\tspecifier.type === 'ImportSpecifier'\n\t\t\t\t\t\t? specifier.imported\n\t\t\t\t\t\t: specifier.type === 'ExportSpecifier'\n\t\t\t\t\t\t\t? specifier.exported\n\t\t\t\t\t\t\t: { type: 'Identifier', name: 'default' }\n\t\t\t\tlet value = specifier.local\n\n\t\t\t\t// Switch them around if we’re exporting.\n\t\t\t\tif (specifier.type === 'ExportSpecifier') {\n\t\t\t\t\tvalue = key\n\t\t\t\t\t// @ts-expect-error: fine.\n\t\t\t\t\tkey = specifier.local\n\t\t\t\t}\n\n\t\t\t\t/** @type {AssignmentProperty} */\n\t\t\t\tconst property = {\n\t\t\t\t\ttype: 'Property',\n\t\t\t\t\tkind: 'init',\n\t\t\t\t\t// @ts-expect-error: fine.\n\t\t\t\t\tshorthand: key.name === value.name,\n\t\t\t\t\tmethod: false,\n\t\t\t\t\tcomputed: false,\n\t\t\t\t\tkey,\n\t\t\t\t\t// @ts-expect-error: fine.\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t\tcreate(specifier, property)\n\t\t\t\treturn property\n\t\t\t})\n\t\t},\n\t\tinit: importNamespaceSpecifier\n\t\t\t? { type: 'Identifier', name: importNamespaceSpecifier.local.name }\n\t\t\t: init\n\t})\n\n\treturn declarations\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-to-binary-addition.js",
    "content": "/**\n * @typedef {import('estree-jsx').Expression} Expression\n */\n\n/**\n * @param {Array<Expression>} expressions\n */\nexport function toBinaryAddition(expressions) {\n\tlet index = -1\n\t/** @type {Expression | undefined} */\n\tlet left\n\n\twhile (++index < expressions.length) {\n\t\tconst right = expressions[index]\n\t\tleft = left\n\t\t\t? { type: 'BinaryExpression', left, operator: '+', right }\n\t\t\t: right\n\t}\n\n\t// Just for types.\n\t/* c8 ignore next */\n\tif (!left) throw new Error('Expected non-empty `expressions` to be passed')\n\n\treturn left\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/estree-util-to-id-or-member-expression.js",
    "content": "/**\n * @typedef {import('estree-jsx').Identifier} Identifier\n * @typedef {import('estree-jsx').JSXIdentifier} JSXIdentifier\n * @typedef {import('estree-jsx').JSXMemberExpression} JSXMemberExpression\n * @typedef {import('estree-jsx').Literal} Literal\n * @typedef {import('estree-jsx').MemberExpression} MemberExpression\n */\n\nimport {\n\tcont as esCont,\n\tstart as esStart,\n\tname as isIdentifierName\n} from 'estree-util-is-identifier-name'\n\nexport const toIdOrMemberExpression = toIdOrMemberExpressionFactory(\n\t'Identifier',\n\t'MemberExpression',\n\tisIdentifierName\n)\n\nexport const toJsxIdOrMemberExpression =\n\t// @ts-expect-error: fine\n\t/** @type {(ids: Array<string | number>) => JSXIdentifier | JSXMemberExpression)} */\n\t(\n\t\ttoIdOrMemberExpressionFactory(\n\t\t\t'JSXIdentifier',\n\t\t\t'JSXMemberExpression',\n\t\t\tisJsxIdentifierName\n\t\t)\n\t)\n\n/**\n * @param {string} idType\n * @param {string} memberType\n * @param {(value: string) => boolean} isIdentifier\n */\nfunction toIdOrMemberExpressionFactory(idType, memberType, isIdentifier) {\n\treturn toIdOrMemberExpression\n\t/**\n\t * @param {Array<string | number>} ids\n\t * @returns {Identifier | MemberExpression}\n\t */\n\tfunction toIdOrMemberExpression(ids) {\n\t\tlet index = -1\n\t\t/** @type {Identifier | Literal | MemberExpression | undefined} */\n\t\tlet object\n\n\t\twhile (++index < ids.length) {\n\t\t\tconst name = ids[index]\n\t\t\tconst valid = typeof name === 'string' && isIdentifier(name)\n\n\t\t\t// A value of `asd.123` could be turned into `asd['123']` in the JS form,\n\t\t\t// but JSX does not have a form for it, so throw.\n\t\t\t/* c8 ignore next 3 */\n\t\t\tif (idType === 'JSXIdentifier' && !valid) {\n\t\t\t\tthrow new Error(`Cannot turn \\`${name}\\` into a JSX identifier`)\n\t\t\t}\n\n\t\t\t/** @type {Identifier | Literal} */\n\t\t\t// @ts-expect-error: JSX is fine.\n\t\t\tconst id = valid\n\t\t\t\t? { type: idType, name }\n\t\t\t\t: { type: 'Literal', value: name }\n\t\t\t// @ts-expect-error: JSX is fine.\n\t\t\tobject = object\n\t\t\t\t? {\n\t\t\t\t\t\ttype: memberType,\n\t\t\t\t\t\tobject,\n\t\t\t\t\t\tproperty: id,\n\t\t\t\t\t\tcomputed: id.type === 'Literal',\n\t\t\t\t\t\toptional: false\n\t\t\t\t\t}\n\t\t\t\t: id\n\t\t}\n\n\t\t// Just for types.\n\t\t/* c8 ignore next 3 */\n\t\tif (!object) throw new Error('Expected non-empty `ids` to be passed')\n\t\tif (object.type === 'Literal')\n\t\t\tthrow new Error('Expected identifier as left-most value')\n\n\t\treturn object\n\t}\n}\n\n/**\n * Checks if the given string is a valid JSX identifier name.\n * @param {string} name\n */\nfunction isJsxIdentifierName(name) {\n\tlet index = -1\n\n\twhile (++index < name.length) {\n\t\t// We currently receive valid input, but this catches bugs and is needed\n\t\t// when externalized.\n\t\t/* c8 ignore next */\n\t\tif (!(index ? jsxCont : esStart)(name.charCodeAt(index))) return false\n\t}\n\n\t// `false` if `name` is empty.\n\treturn index > 0\n}\n\n/**\n * Checks if the given character code can continue a JSX identifier.\n * @param {number} code\n */\nfunction jsxCont(code) {\n\treturn code === 45 /* `-` */ || esCont(code)\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/is-org-content.js",
    "content": "/**\n * Check if a node is an org content node.\n * @param {import('react').ReactNode} node\n * @returns {boolean}\n */\nexport function isOrgContent(node) {\n\treturn (\n\t\t!!node &&\n\t\ttypeof node === 'object' &&\n\t\t'type' in node &&\n\t\ttypeof node.type === 'function' &&\n\t\tnode.type.name === 'OrgContent'\n\t)\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/render-error.js",
    "content": "/**\n * @param {SyntaxError} error\n * @param {string} bg\n * @param {string} color\n * @returns {import('estree-jsx').Program}\n */\nexport default (error, bg = '#F44336', color = 'white') => {\n\treturn {\n\t\ttype: 'Program',\n\t\tbody: [\n\t\t\t{\n\t\t\t\ttype: 'ExpressionStatement',\n\t\t\t\texpression: {\n\t\t\t\t\ttype: 'JSXElement',\n\t\t\t\t\topeningElement: {\n\t\t\t\t\t\ttype: 'JSXOpeningElement',\n\t\t\t\t\t\tattributes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'JSXAttribute',\n\t\t\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\t\t\ttype: 'JSXIdentifier',\n\t\t\t\t\t\t\t\t\tname: 'style'\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\ttype: 'JSXExpressionContainer',\n\t\t\t\t\t\t\t\t\texpression: {\n\t\t\t\t\t\t\t\t\t\ttype: 'ObjectExpression',\n\t\t\t\t\t\t\t\t\t\tproperties: [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\t\t\t\t\tshorthand: false,\n\t\t\t\t\t\t\t\t\t\t\t\tcomputed: false,\n\t\t\t\t\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'backgroundColor'\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: bg,\n\t\t\t\t\t\t\t\t\t\t\t\t\traw: `'${bg}'`\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tkind: 'init'\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Property',\n\t\t\t\t\t\t\t\t\t\t\t\tmethod: false,\n\t\t\t\t\t\t\t\t\t\t\t\tshorthand: false,\n\t\t\t\t\t\t\t\t\t\t\t\tcomputed: false,\n\t\t\t\t\t\t\t\t\t\t\t\tkey: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Identifier',\n\t\t\t\t\t\t\t\t\t\t\t\t\tname: 'color'\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tvalue: {\n\t\t\t\t\t\t\t\t\t\t\t\t\ttype: 'Literal',\n\t\t\t\t\t\t\t\t\t\t\t\t\tvalue: color,\n\t\t\t\t\t\t\t\t\t\t\t\t\traw: `'${color}'`\n\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\tkind: 'init'\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t],\n\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\ttype: 'JSXIdentifier',\n\t\t\t\t\t\t\tname: 'pre'\n\t\t\t\t\t\t},\n\t\t\t\t\t\tselfClosing: false\n\t\t\t\t\t},\n\t\t\t\t\tclosingElement: {\n\t\t\t\t\t\ttype: 'JSXClosingElement',\n\t\t\t\t\t\tname: {\n\t\t\t\t\t\t\ttype: 'JSXIdentifier',\n\t\t\t\t\t\t\tname: 'pre'\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tchildren: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'JSXText',\n\t\t\t\t\t\t\tvalue: error.message,\n\t\t\t\t\t\t\traw: error.message\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\tsourceType: 'module'\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/resolve-evaluate-options.js",
    "content": "/**\n * @typedef {import('../core.js').ProcessorOptions} ProcessorOptions\n *\n * @typedef RunnerOptions\n *   Configuration with JSX runtime.\n * @property {any} Fragment\n *   Symbol to use for fragments.\n * @property {any} [jsx]\n *   Function to generate an element with static children in production mode.\n * @property {any} [jsxs]\n *   Function to generate an element with dynamic children in production mode.\n * @property {any} [jsxDEV]\n *   Function to generate an element in development mode.\n * @property {any} [useOrgComponents]\n *   Function to get `MDXComponents` from context.\n *\n * @typedef {Omit<ProcessorOptions, 'jsx' | 'jsxImportSource' | 'jsxRuntime' | 'pragma' | 'pragmaFrag' | 'pragmaImportSource' | 'providerImportSource' | 'outputFormat'> } EvaluateProcessorOptions\n *   Compile configuration without JSX options for evaluation.\n *\n * @typedef {EvaluateProcessorOptions & RunnerOptions} EvaluateOptions\n *   Configuration for evaluation.\n */\n\n/**\n * Split compiletime options from runtime options.\n *\n * @param {EvaluateOptions | null | undefined} options\n * @returns {{compiletime: ProcessorOptions, runtime: RunnerOptions}}\n */\nexport function resolveEvaluateOptions(options) {\n\tconst {\n\t\tdevelopment,\n\t\tFragment,\n\t\tjsx,\n\t\tjsxs,\n\t\tjsxDEV,\n\t\tuseOrgComponents,\n\t\t...rest\n\t} = options || {}\n\n\tif (!Fragment) throw new Error('Expected `Fragment` given to `evaluate`')\n\tif (development) {\n\t\tif (!jsxDEV) throw new Error('Expected `jsxDEV` given to `evaluate`')\n\t} else {\n\t\tif (!jsx) throw new Error('Expected `jsx` given to `evaluate`')\n\t\tif (!jsxs) throw new Error('Expected `jsxs` given to `evaluate`')\n\t}\n\n\treturn {\n\t\tcompiletime: {\n\t\t\t...rest,\n\t\t\tdevelopment,\n\t\t\toutputFormat: 'function-body',\n\t\t\tproviderImportSource: useOrgComponents ? '#' : undefined\n\t\t},\n\t\truntime: {\n\t\t\tFragment,\n\t\t\tjsx,\n\t\t\tjsxs,\n\t\t\tjsxDEV,\n\t\t\tuseOrgComponents\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/lib/util/resolve-file-and-options.js",
    "content": "/**\n * @typedef {import('vfile').VFileCompatible} VFileCompatible\n * @typedef {import('../core.js').ProcessorOptions} ProcessorOptions\n * @typedef {import('../compile.js').CompileOptions} CompileOptions\n */\n\nimport { VFile } from 'vfile'\n\n/**\n * Create a file and options from a given `vfileCompatible` and options that\n * might contain `format: 'detect'`.\n *\n * @param {VFileCompatible} vfileCompatible\n * @param {CompileOptions | null | undefined} [options]\n * @returns {{file: VFile, options: ProcessorOptions}}\n */\nexport function resolveFileAndOptions(vfileCompatible, options) {\n\tconst file = looksLikeAVFile(vfileCompatible)\n\t\t? vfileCompatible\n\t\t: new VFile(vfileCompatible)\n\treturn {\n\t\tfile,\n\t\toptions: {\n\t\t\t...options\n\t\t}\n\t}\n}\n\n/**\n * @param {VFileCompatible | null | undefined} [value]\n * @returns {value is VFile}\n */\nfunction looksLikeAVFile(value) {\n\treturn Boolean(\n\t\tvalue &&\n\t\t\ttypeof value === 'object' &&\n\t\t\t'message' in value &&\n\t\t\t'messages' in value\n\t)\n}\n"
  },
  {
    "path": "packages/orgx/package.json",
    "content": "{\n\t\"name\": \"@orgajs/orgx\",\n\t\"version\": \"2.6.1\",\n\t\"description\": \"orga compiler with jsx support\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/orgx#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/orgx\"\n\t},\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\",\n\t\t\"types.d.ts\"\n\t],\n\t\"exports\": {\n\t\t\".\": \"./index.js\"\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"node --test tests/*.test.js\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/estree\": \"^1.0.6\",\n\t\t\"@types/estree-jsx\": \"^1.0.5\",\n\t\t\"@types/hast\": \"^3.0.4\",\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"@types/react\": \"^19.0.8\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"typescript\": \"^5.9.2\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/reorg-parse\": \"workspace:^\",\n\t\t\"@orgajs/reorg-rehype\": \"workspace:^\",\n\t\t\"acorn\": \"^8.14.0\",\n\t\t\"acorn-jsx\": \"^5.3.2\",\n\t\t\"astring\": \"^1.8.6\",\n\t\t\"estree-util-build-jsx\": \"3.0.1\",\n\t\t\"estree-util-is-identifier-name\": \"3.0.0\",\n\t\t\"estree-util-to-js\": \"^2.0.0\",\n\t\t\"estree-walker\": \"3.0.3\",\n\t\t\"hast-util-to-estree\": \"^3.1.1\",\n\t\t\"periscopic\": \"3.1.0\",\n\t\t\"recma-build-jsx\": \"^1.0.0\",\n\t\t\"recma-jsx\": \"^1.0.0\",\n\t\t\"recma-stringify\": \"^1.0.0\",\n\t\t\"source-map\": \"^0.7.4\",\n\t\t\"unified\": \"^11.0.5\",\n\t\t\"unist-util-position-from-estree\": \"^2.0.0\",\n\t\t\"unist-util-stringify-position\": \"^4.0.0\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/orgx/tests/compile.test.js",
    "content": "import * as assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { compile } from '../lib/compile.js'\n\nconst fixture = `\n#+title: Hello World\n* Hi\n`\nconst code = `\n/*@jsxRuntime classic @jsx React.createElement @jsxFrag React.Fragment*/\nimport React from \"react\";\nexport const title = 'Hello World';\nfunction _createOrgContent(props) {\n  const _components = Object.assign({\n    div: \"div\",\n    h1: \"h1\"\n  }, props.components);\n  return <_components.div className=\"section\"><_components.h1>{\"Hi\"}</_components.h1></_components.div>;\n}\nfunction OrgContent(props = {}) {\n  const {wrapper: OrgLayout} = props.components || ({});\n  return OrgLayout ? <OrgLayout {...props}><_createOrgContent {...props} /></OrgLayout> : _createOrgContent(props);\n}\nexport default OrgContent;\n`\n\ndescribe('compile', () => {\n\tit('can compile org file', async () => {\n\t\tconst result = await compile(fixture, {\n\t\t\tjsxRuntime: 'classic',\n\t\t\tjsx: true,\n\t\t\toutputFormat: 'program'\n\t\t})\n\n\t\tassert.strictEqual(`${result}`.trim(), code.trim())\n\t})\n})\n"
  },
  {
    "path": "packages/orgx/tests/evaluate.test.js",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { createElement } from 'react'\nimport * as runtime from 'react/jsx-runtime'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { evaluate } from '../lib/evaluate.js'\n\ndescribe('evaluate', () => {\n\tit('can evaluate org file', async () => {\n\t\tconst text = `\n* hi\n`\n\t\tconst Content = (await evaluate(text, runtime)).default\n\t\tconst rendered = renderToStaticMarkup(createElement(Content))\n\t\tassert.equal(rendered, '<div class=\"section\"><h1>hi</h1></div>')\n\t})\n})\n"
  },
  {
    "path": "packages/orgx/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/react/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.2.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 4.2.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n## 4.1.2\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n\n## 4.1.1\n\n### Patch Changes\n\n- df80497a: Fix package\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n## 3.0.1\n\n### Patch Changes\n\n- 8c6f440b: - better layout support\n  - rename MDXxxx to Orgaxxx\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n\n## 2.4.9 (2021-07-13)\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n**Note:** Version bump only for package @orgajs/react\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/react\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/react\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/react\n"
  },
  {
    "path": "packages/react/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/react/index.js",
    "content": "/**\n * @typedef {import('react').ReactNode} ReactNode\n * @typedef {import('@orgajs/orgx').OrgComponents} Components\n *\n * @typedef Props\n *   Configuration.\n * @property {Components | MergeComponents | null | undefined} [components]\n *   Mapping of names for JSX components to React components.\n * @property {boolean | null | undefined} [disableParentContext=false]\n *   Turn off outer component context.\n * @property {ReactNode | null | undefined} [children]\n *   Children.\n *\n * @callback MergeComponents\n *   Custom merge function.\n * @param {Components} currentComponents\n *   Current components from the context.\n * @returns {Components}\n *   Merged components.\n */\n\nimport React from 'react'\n\n/** @type {import('react').Context<Components>} */\nconst OrgContext = React.createContext({})\n\n/**\n * Get current components from the org context.\n *\n * @param {Components | MergeComponents | null | undefined} [components]\n *   Additional components to use or a function that takes the current\n *   components and filters/merges/changes them.\n * @returns {Components}\n *   Current components.\n */\nexport function useOrgComponents(components) {\n\tconst contextComponents = React.useContext(OrgContext)\n\n\t// Memoize to avoid unnecessary top-level context changes\n\treturn React.useMemo(() => {\n\t\t// Custom merge via a function prop\n\t\tif (typeof components === 'function') {\n\t\t\treturn components(contextComponents)\n\t\t}\n\n\t\treturn { ...contextComponents, ...components }\n\t}, [contextComponents, components])\n}\n\n/** @type {Components} */\nconst emptyObject = {}\n\n/**\n * Provider for org context\n *\n * @param {Props} props\n * @returns {React.JSX.Element}\n */\nexport function OrgProvider({ components, children, disableParentContext }) {\n\tconst contextComponents = React.useContext(OrgContext)\n\tconst allComponents = React.useMemo(() => {\n\t\tconst baseComponents = disableParentContext\n\t\t\t? emptyObject\n\t\t\t: contextComponents\n\t\tif (typeof components === 'function') {\n\t\t\treturn components(baseComponents)\n\t\t}\n\t\treturn { ...baseComponents, ...components }\n\t}, [components, contextComponents, disableParentContext])\n\n\treturn React.createElement(\n\t\tOrgContext.Provider,\n\t\t{ value: allComponents },\n\t\tchildren\n\t)\n}\n"
  },
  {
    "path": "packages/react/package.json",
    "content": "{\n\t\"name\": \"@orgajs/react\",\n\t\"version\": \"4.2.1\",\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs\",\n\t\t\"directory\": \"packages/react\"\n\t},\n\t\"files\": [\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"scripts\": {},\n\t\"peerDependencies\": {\n\t\t\"react\": \">=16\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@babel/plugin-transform-react-jsx\": \"^7.22.5\",\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"@types/react\": \"^19.0.8\",\n\t\t\"@types/react-dom\": \"^19.0.3\",\n\t\t\"babel-plugin-remove-export-keywords\": \"^1.6.22\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t}\n}\n"
  },
  {
    "path": "packages/react/tests/remove-export-keywords.js",
    "content": "module.exports = () => {\n\treturn {\n\t\tvisitor: {\n\t\t\tExportNamedDeclaration(path) {\n\t\t\t\tconst declaration = path.node.declaration\n\n\t\t\t\t// Ignore \"export { Foo as default }\" syntax\n\t\t\t\tif (declaration) {\n\t\t\t\t\tpath.replaceWith(declaration)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/react/tests/test.tsx",
    "content": "/* @jsx React.createElement */\n/* @jsxFrag React.Fragment */\nimport { transformAsync as babelTransform } from '@babel/core'\nimport toJsx from '@orgajs/estree-jsx'\nimport toEstree from '@orgajs/rehype-estree'\nimport reorg from '@orgajs/reorg'\nimport removeExport from 'babel-plugin-remove-export-keywords'\nimport { renderToString } from 'react-dom/server'\nimport { orga } from '../src'\n\nconst run = async (value) => {\n\tconst processor = reorg().use(toHast).use(toEstree).use(toJsx)\n\n\tconst doc = await processor.process(value)\n\n\tconsole.log({ doc })\n\n\t// …and that into serialized JS.\n\tconst { code } = await babelTransform(doc.toString('utf-8'), {\n\t\tconfigFile: false,\n\t\tplugins: ['@babel/plugin-transform-react-jsx', removeExport]\n\t})\n\n\tconsole.dir(code)\n\n\t// …and finally run it, returning the component.\n\t// eslint-disable-next-line no-new-func\n\treturn new Function('orga', `${code}; return OrgaContent`)(orga)\n}\n\ndescribe.skip('@orgajs/react', () => {\n\ttest('should work', async () => {\n\t\tconst Content = await run('* hi')\n\t\tconst string = renderToString(<Content />)\n\t\tconsole.dir(string)\n\t})\n})\n"
  },
  {
    "path": "packages/react/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/react-cm/CHANGELOG.md",
    "content": "# @orgajs/react-cm\n\n## 0.1.3\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 0.1.2\n\n### Patch Changes\n\n- 94ae77a: fix cursor jumping issue\n\n## 0.1.1\n\n### Patch Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n"
  },
  {
    "path": "packages/react-cm/index.js",
    "content": "import { EditorState } from '@codemirror/state'\nimport { EditorView } from '@codemirror/view'\nimport { useEffect, useRef } from 'react'\nimport { jsx } from 'react/jsx-runtime'\n\n/**\n * A React component that renders an Orga editor.\n *\n * @param {Object} props - The component props\n * @param {string} [props.content=''] - The initial content for the editor\n * @param {string} [props.className] - CSS class name to apply to the editor container\n * @param {Function} [props.onChange] - Callback function that receives the updated content when changes occur\n * @param {import('@codemirror/state').Extension} [props.extensions] - Array of CodeMirror extensions to customize the editor\n * @returns {import('react').ReactElement} A div element containing the editor\n */\nexport function ReactCodeMirror({\n\tclassName = '',\n\tcontent = '',\n\textensions = [],\n\tonChange\n}) {\n\t/** @type {import('react').RefObject<HTMLElement|undefined>} */\n\tconst container = useRef(undefined)\n\t/** @type {import('react').RefObject<import('@codemirror/view').EditorView|undefined>} */\n\tconst editor = useRef(undefined)\n\t/** @type {import('react').RefObject<Function|undefined>} */\n\tconst onChangeRef = useRef(onChange)\n\t/** @type {import('react').RefObject<string>} */\n\tconst initialContent = useRef(content)\n\t/** @type {import('react').RefObject<import('@codemirror/state').Extension>} */\n\tconst initialExtensions = useRef(extensions)\n\n\tuseEffect(() => {\n\t\tonChangeRef.current = onChange\n\t}, [onChange])\n\n\tuseEffect(() => {\n\t\tif (!container.current || editor.current) return\n\t\tconst state = EditorState.create({\n\t\t\tdoc: initialContent.current,\n\t\t\textensions: initialExtensions.current\n\t\t})\n\t\tconst ed = new EditorView({\n\t\t\tstate,\n\t\t\tparent: container.current,\n\t\t\tdispatch(tr) {\n\t\t\t\ted.update([tr])\n\t\t\t\tif (tr.docChanged) {\n\t\t\t\t\tonChangeRef.current?.(ed.state)\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\t\teditor.current = ed\n\t\treturn () => {\n\t\t\ted.destroy()\n\t\t\teditor.current = undefined\n\t\t}\n\t}, [])\n\n\tuseEffect(() => {\n\t\tif (!editor.current) return\n\t\tif (editor.current.state.doc.toString() === content) return\n\t\teditor.current.dispatch({\n\t\t\tchanges: {\n\t\t\t\tfrom: 0,\n\t\t\t\tto: editor.current.state.doc.length,\n\t\t\t\tinsert: content\n\t\t\t}\n\t\t})\n\t}, [content])\n\n\treturn jsx('div', { ref: container, className })\n}\n"
  },
  {
    "path": "packages/react-cm/package.json",
    "content": "{\n\t\"name\": \"@orgajs/react-cm\",\n\t\"version\": \"0.1.3\",\n\t\"type\": \"module\",\n\t\"description\": \"\",\n\t\"main\": \"index.js\",\n\t\"scripts\": {},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs\",\n\t\t\"directory\": \"packages/react-cm\"\n\t},\n\t\"keywords\": [],\n\t\"author\": \"\",\n\t\"license\": \"ISC\",\n\t\"packageManager\": \"pnpm@10.4.1\",\n\t\"devDependencies\": {\n\t\t\"@types/react\": \"^19.1.2\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t},\n\t\"dependencies\": {\n\t\t\"@codemirror/state\": \"^6.5.2\",\n\t\t\"@codemirror/view\": \"^6.36.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-editor/CHANGELOG.md",
    "content": "# @orgajs/react-editor\n\n## 0.1.3\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/react-cm@0.1.3\n  - @orgajs/editor@1.4.1\n\n## 0.1.2\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/editor@1.4.0\n\n## 0.1.1\n\n### Patch Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n- Updated dependencies [60ad38f]\n  - @orgajs/react-cm@0.1.1\n  - @orgajs/editor@1.3.1\n"
  },
  {
    "path": "packages/react-editor/index.js",
    "content": "import { setup } from '@orgajs/editor'\nimport { ReactCodeMirror } from '@orgajs/react-cm'\nimport { jsx } from 'react/jsx-runtime'\n\n/**\n * A React component that renders an Orga editor.\n *\n * @param {Object} props - The component props\n * @param {string} [props.content=''] - The initial content for the editor\n * @param {string} [props.className] - CSS class name to apply to the editor container\n * @param {Function} [props.onChange] - Callback function that receives the updated content when changes occur\n * @param {import('@codemirror/state').Extension} [props.extensions] - Array of CodeMirror extensions to customize the editor\n * @returns {import('react').ReactElement} A div element containing the editor\n */\nexport function Editor({ content = '', className, onChange, extensions = [] }) {\n\treturn jsx(ReactCodeMirror, {\n\t\tclassName,\n\t\tcontent,\n\t\tonChange,\n\t\textensions: [setup, extensions]\n\t})\n}\n"
  },
  {
    "path": "packages/react-editor/package.json",
    "content": "{\n\t\"name\": \"@orgajs/react-editor\",\n\t\"version\": \"0.1.3\",\n\t\"type\": \"module\",\n\t\"description\": \"@orgajs/editor in react\",\n\t\"files\": [\n\t\t\"index.js\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./index.d.ts\",\n\t\t\t\"import\": \"./index.js\"\n\t\t}\n\t},\n\t\"scripts\": {},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/react-editor\"\n\t},\n\t\"keywords\": [\n\t\t\"org-mode\",\n\t\t\"react\",\n\t\t\"editor\"\n\t],\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"packageManager\": \"pnpm@10.4.1\",\n\t\"dependencies\": {\n\t\t\"@orgajs/editor\": \"workspace:^\",\n\t\t\"@orgajs/react-cm\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@codemirror/state\": \"^6.5.2\",\n\t\t\"@types/react\": \"^19.1.2\",\n\t\t\"@types/react-dom\": \"^19.1.2\",\n\t\t\"esbuild\": \"^0.24.2\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\"\n\t}\n}\n"
  },
  {
    "path": "packages/react-editor/tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\"\n\t}\n}\n"
  },
  {
    "path": "packages/reorg/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.3.3\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/reorg-parse@4.4.1\n  - orga@4.7.1\n\n## 4.3.2\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/reorg-parse@4.4.0\n\n## 4.3.1\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.3.1\n\n## 4.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/reorg-parse@4.3.0\n\n## 4.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/reorg-parse@4.2.0\n\n## 4.1.2\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.1.2\n\n## 4.1.1\n\n### Patch Changes\n\n- @orgajs/reorg-parse@4.1.1\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/reorg-parse@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - @orgajs/reorg-parse@4.0.0\n\n## 3.1.7\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.7\n\n## 3.1.6\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.6\n\n## 3.1.5\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.5\n\n## 3.1.4\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.4\n\n## 3.1.3\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.3\n\n## 3.1.2\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.2\n\n## 3.1.1\n\n### Patch Changes\n\n- @orgajs/reorg-parse@3.1.1\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - @orgajs/reorg-parse@3.1.0\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - @orgajs/reorg-parse@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - @orgajs/reorg-parse@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n\n## 2.4.9 (2021-07-13)\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/reorg\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg\n"
  },
  {
    "path": "packages/reorg/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/reorg/README.org",
    "content": "#+TITLE: @orgajs/reorg\n\n[[https://github.com/unifiedjs/unified][unified]] processor to parse [[https://orgmode.org][org-mode]].\n"
  },
  {
    "path": "packages/reorg/index.js",
    "content": "import parse from '@orgajs/reorg-parse'\nimport { unified } from 'unified'\n\nexport const reorg = unified().use(parse).freeze()\n"
  },
  {
    "path": "packages/reorg/package.json",
    "content": "{\n\t\"name\": \"@orgajs/reorg\",\n\t\"version\": \"4.3.3\",\n\t\"description\": \"orga processor for unifiedjs\",\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"type\": \"module\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/reorg#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/reorg\"\n\t},\n\t\"scripts\": {},\n\t\"dependencies\": {\n\t\t\"@orgajs/reorg-parse\": \"workspace:^\",\n\t\t\"orga\": \"workspace:^\",\n\t\t\"unified\": \"^11.0.5\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/unist\": \"^3.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-parse/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.4.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - orga@4.7.1\n\n## 4.4.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - orga@4.6.0\n\n## 4.3.1\n\n### Patch Changes\n\n- Updated dependencies [60ad38f]\n  - orga@4.5.1\n\n## 4.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - orga@4.5.0\n\n## 4.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - orga@4.4.0\n\n## 4.1.2\n\n### Patch Changes\n\n- Updated dependencies [7cfff79a]\n  - orga@4.3.0\n\n## 4.1.1\n\n### Patch Changes\n\n- Updated dependencies [ac322714]\n  - orga@4.2.0\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - orga@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - orga@4.0.0\n\n## 3.1.7\n\n### Patch Changes\n\n- Updated dependencies [eeccc870]\n  - orga@3.2.1\n\n## 3.1.6\n\n### Patch Changes\n\n- Updated dependencies [6c1ddb9f]\n  - orga@3.2.0\n\n## 3.1.5\n\n### Patch Changes\n\n- Updated dependencies [4bde5155]\n  - orga@3.1.5\n\n## 3.1.4\n\n### Patch Changes\n\n- Updated dependencies [ae83a3b0]\n  - orga@3.1.4\n\n## 3.1.3\n\n### Patch Changes\n\n- Updated dependencies [09a3b5c6]\n  - orga@3.1.3\n\n## 3.1.2\n\n### Patch Changes\n\n- Updated dependencies [594bf16b]\n  - orga@3.1.2\n\n## 3.1.1\n\n### Patch Changes\n\n- Updated dependencies [19156b8a]\n  - orga@3.1.1\n\n## 3.1.0\n\n### Minor Changes\n\n- eeea0c54: introduce new token: empty line\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - orga@3.1.0\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - orga@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - orga@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n\n## 2.4.9 (2021-07-13)\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n### Bug Fixes\n\n- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/reorg-parse\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg-parse\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg-parse\n"
  },
  {
    "path": "packages/reorg-parse/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/reorg-parse/README.org",
    "content": "#+TITLE: @orgajs/reorg-parse\n\nParser for [[https://github.com/unifiedjs/unified][unified]]. Parses org-mode to oast syntax trees. Used in [[https://github.com/orgapp/orgajs/tree/main/packages/reorg][@orgajs/reorg]] processor.\n"
  },
  {
    "path": "packages/reorg-parse/index.d.ts",
    "content": "import type { Document, ParseOptions } from 'orga'\nimport type { Plugin } from 'unified'\n\ndeclare const reorgParse: Plugin<\n\t[(Readonly<ParseOptions> | null | undefined)?],\n\tstring,\n\tDocument\n>\nexport default reorgParse\n"
  },
  {
    "path": "packages/reorg-parse/index.js",
    "content": "/**\n * @import {Document, ParseOptions} from 'orga'\n * @import {Processor} from 'unified'\n */\n\n/**\n * @typedef {ParseOptions} Options\n */\n\nimport { parse } from 'orga'\n\n/**\n * Aadd support for parsing from org-mode.\n *\n * @this {Processor<Document>}\n *   Processor instance.\n * @param {Partial<ParseOptions> | undefined} [options]\n *   Configuration (optional).\n * @returns {undefined}\n *   Nothing.\n */\nexport default function reorgParse(options) {\n\tthis.parser = function (document) {\n\t\treturn parse(document, options)\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-parse/package.json",
    "content": "{\n\t\"name\": \"@orgajs/reorg-parse\",\n\t\"version\": \"4.4.1\",\n\t\"description\": \"orga parser for unifiedjs\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib/\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/reorg-parse#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/reorg-parse\"\n\t},\n\t\"scripts\": {},\n\t\"dependencies\": {\n\t\t\"orga\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"typescript\": \"^5.9.3\",\n\t\t\"unified\": \"^11.0.5\"\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-parse/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/reorg-prose/CHANGELOG.md",
    "content": "# @orgajs/reorg-prose\n\n## 1.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - oast-to-prose@1.3.0\n\n## 1.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - oast-to-prose@1.2.0\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - oast-to-prose@1.1.0\n"
  },
  {
    "path": "packages/reorg-prose/index.js",
    "content": "export { schema } from 'oast-to-prose'\nexport { default } from './lib/index.js'\n"
  },
  {
    "path": "packages/reorg-prose/lib/index.js",
    "content": "/**\n * @import {Document as OastRoot} from 'orga'\n * @import {Node as ProseNode} from 'prosemirror-model'\n * @import {Options} from 'oast-to-prose'\n * @import {VFile} from 'vfile'\n */\n\nimport { toProse } from 'oast-to-prose'\n\n/**\n *\n * @param {Options | null | undefined} [options]\n *   Configuration (optional).\n * @returns\n *   Transform.\n */\nexport default function reorgProse(options) {\n\t/**\n\t * @param {OastRoot} tree\n\t *   Tree (hast).\n\t * @param {VFile} file\n\t *   File.\n\t * @returns {ProseNode}\n\t *   Prose Node.\n\t */\n\treturn function (tree, file) {\n\t\treturn /** @type {ProseNode} */ toProse(tree, file, options)\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-prose/package.json",
    "content": "{\n\t\"name\": \"@orgajs/reorg-prose\",\n\t\"version\": \"1.3.0\",\n\t\"description\": \"\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/reorg-prose#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/reorg-prose\"\n\t},\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"scripts\": {},\n\t\"keywords\": [],\n\t\"dependencies\": {\n\t\t\"oast-to-prose\": \"workspace:^\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/unist\": \"^3.0.3\",\n\t\t\"orga\": \"workspace:^\",\n\t\t\"prosemirror-model\": \"^1.19.3\",\n\t\t\"unified\": \"^11.0.5\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-prose/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/reorg-rehype/.projectile",
    "content": ""
  },
  {
    "path": "packages/reorg-rehype/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.3.11\n\n### Patch Changes\n\n- Updated dependencies [850bcf9]\n  - oast-to-hast@4.5.3\n\n## 4.3.10\n\n### Patch Changes\n\n- Updated dependencies [be20652]\n  - oast-to-hast@4.5.2\n\n## 4.3.9\n\n### Patch Changes\n\n- Updated dependencies [bd2365a]\n  - oast-to-hast@4.5.1\n\n## 4.3.8\n\n### Patch Changes\n\n- Updated dependencies [761c484]\n  - oast-to-hast@4.5.0\n\n## 4.3.7\n\n### Patch Changes\n\n- Updated dependencies [68430c7]\n  - oast-to-hast@4.4.3\n\n## 4.3.6\n\n### Patch Changes\n\n- Updated dependencies [d8da621]\n  - oast-to-hast@4.4.2\n\n## 4.3.5\n\n### Patch Changes\n\n- Updated dependencies [20f5a03]\n  - oast-to-hast@4.4.1\n\n## 4.3.4\n\n### Patch Changes\n\n- Updated dependencies [da20dcc]\n  - oast-to-hast@4.4.0\n\n## 4.3.3\n\n### Patch Changes\n\n- oast-to-hast@4.3.3\n\n## 4.3.2\n\n### Patch Changes\n\n- oast-to-hast@4.3.2\n\n## 4.3.1\n\n### Patch Changes\n\n- Updated dependencies [7c3c600]\n  - oast-to-hast@4.3.1\n\n## 4.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - oast-to-hast@4.3.0\n\n## 4.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - oast-to-hast@4.2.0\n\n## 4.1.3\n\n### Patch Changes\n\n- Updated dependencies [ab38e4b0]\n  - oast-to-hast@4.1.3\n\n## 4.1.2\n\n### Patch Changes\n\n- oast-to-hast@4.1.2\n\n## 4.1.1\n\n### Patch Changes\n\n- oast-to-hast@4.1.1\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - oast-to-hast@4.1.0\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - oast-to-hast@4.0.0\n\n## 3.0.10\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n- Updated dependencies [eeccc870]\n  - oast-to-hast@3.2.1\n\n## 3.0.9\n\n### Patch Changes\n\n- Updated dependencies [6c1ddb9f]\n  - oast-to-hast@3.2.0\n\n## 3.0.8\n\n### Patch Changes\n\n- oast-to-hast@3.1.6\n\n## 3.0.7\n\n### Patch Changes\n\n- Updated dependencies [ae83a3b0]\n  - oast-to-hast@3.1.5\n\n## 3.0.6\n\n### Patch Changes\n\n- oast-to-hast@3.1.4\n\n## 3.0.5\n\n### Patch Changes\n\n- oast-to-hast@3.1.3\n\n## 3.0.4\n\n### Patch Changes\n\n- Updated dependencies [19156b8a]\n  - oast-to-hast@3.1.2\n\n## 3.0.3\n\n### Patch Changes\n\n- 7f209ff5: export Options type\n- Updated dependencies [7f209ff5]\n  - oast-to-hast@3.1.1\n\n## 3.0.2\n\n### Patch Changes\n\n- Updated dependencies [eeea0c54]\n  - oast-to-hast@3.1.0\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n- Updated dependencies [6ed76057]\n- Updated dependencies [759e6149]\n  - oast-to-hast@3.0.1\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\n### Patch Changes\n\n- Updated dependencies [8b02d10]\n  - oast-to-hast@3.0.0\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n\n## 2.4.9 (2021-07-13)\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n**Note:** Version bump only for package @orgajs/reorg-rehype\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package @orgajs/reorg-rehype\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg-rehype\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package @orgajs/reorg-rehype\n"
  },
  {
    "path": "packages/reorg-rehype/LICENSE.org",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n"
  },
  {
    "path": "packages/reorg-rehype/index.js",
    "content": "/**\n * @import {Document} from 'orga'\n * @import {Root as HastRoot} from 'hast'\n * @import {VFile} from 'vfile'\n *\n * @typedef {import('oast-to-hast').Options} Options\n *\n * @callback TransformMutate\n *  Mutate-mode.\n *\n *  Further transformers run on the hast tree.\n * @param {Document} tree\n *   Tree.\n * @param {VFile} file\n *   File.\n * @returns {HastRoot}\n *   Tree (hast).\n */\n\nimport toHAST from 'oast-to-hast'\n\n/**\n * @param {Partial<Options>} [options]\n * @returns {TransformMutate}\n */\nfunction reorg2rehype(options = {}) {\n\treturn transformer\n\n\t/**\n\t * @type {TransformMutate}\n\t */\n\tfunction transformer(tree) {\n\t\treturn /** @type {HastRoot} */ (toHAST(tree, options))\n\t}\n}\n\nexport default reorg2rehype\n"
  },
  {
    "path": "packages/reorg-rehype/package.json",
    "content": "{\n\t\"name\": \"@orgajs/reorg-rehype\",\n\t\"version\": \"4.3.11\",\n\t\"description\": \"rehype support for orga\",\n\t\"files\": [\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"type\": \"module\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"license\": \"MIT\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/reorg-rehype#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/reorg-rehype\"\n\t},\n\t\"scripts\": {},\n\t\"dependencies\": {\n\t\t\"oast-to-hast\": \"workspace:*\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/hast\": \"^3.0.4\",\n\t\t\"@types/unist\": \"^3.0.3\",\n\t\t\"orga\": \"workspace:*\",\n\t\t\"unified\": \"^11.0.5\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/reorg-rehype/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/rollup/CHANGELOG.md",
    "content": "# @orgajs/rollup\n\n## 1.3.4\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs/orgx@2.6.1\n\n## 1.3.3\n\n### Patch Changes\n\n- Updated dependencies [a53cfea]\n  - @orgajs/orgx@2.6.0\n\n## 1.3.2\n\n### Patch Changes\n\n- 60ad38f: migrate orga-build to be based on vite\n  - @orgajs/orgx@2.5.2\n\n## 1.3.1\n\n### Patch Changes\n\n- @orgajs/orgx@2.5.1\n\n## 1.3.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n### Patch Changes\n\n- Updated dependencies [188d30f]\n  - @orgajs/orgx@2.5.0\n\n## 1.2.2\n\n### Patch Changes\n\n- e3ef3a5: build website with orga-build\n- Updated dependencies [e3ef3a5]\n  - @orgajs/orgx@2.4.1\n\n## 1.2.1\n\n### Patch Changes\n\n- Updated dependencies [351f690]\n  - @orgajs/orgx@2.4.0\n\n## 1.2.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n### Patch Changes\n\n- Updated dependencies [d8861c2]\n  - @orgajs/orgx@2.3.0\n\n## 1.1.3\n\n### Patch Changes\n\n- @orgajs/orgx@2.2.2\n\n## 1.1.2\n\n### Patch Changes\n\n- @orgajs/orgx@2.2.1\n\n## 1.1.1\n\n### Patch Changes\n\n- Updated dependencies [ac322714]\n  - @orgajs/orgx@2.2.0\n\n## 1.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n### Patch Changes\n\n- Updated dependencies [4d8efbb7]\n  - @orgajs/orgx@2.1.0\n\n## 1.0.1\n\n### Patch Changes\n\n- Updated dependencies [1dbf674d]\n  - @orgajs/orgx@2.0.1\n\n## 1.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n### Patch Changes\n\n- Updated dependencies [176a3b5d]\n  - @orgajs/orgx@2.0.0\n"
  },
  {
    "path": "packages/rollup/index.js",
    "content": "/**\n * @typedef {import('@rollup/pluginutils').FilterPattern} FilterPattern\n * @typedef {import('rollup').SourceDescription} SourceDescription\n * @typedef Plugin\n *   Plugin that is compatible with both Rollup and Vite.\n * @property {string} name\n *   The name of the plugin\n * @property {ViteConfig} config\n *   Function used by Vite to set additional configuration options.\n * @property {Transform} transform\n *   Function to transform the source content.\n *\n * @callback Transform\n *   Callback called by Rollup and Vite to transform.\n * @param {string} value\n *   File contents.\n * @param {string} path\n *   File path.\n * @returns {Promise<SourceDescription | undefined>}\n *   Result.\n *\n * @callback ViteConfig\n *   Callback called by Vite to set additional configuration options.\n * @param {unknown} config\n *   Configuration object (unused).\n * @param {ViteEnv} env\n *   Environment variables.\n * @returns {undefined}\n *   Nothing.\n *\n * @typedef ViteEnv\n *   Environment variables used by Vite.\n * @property {string} mode\n *   Mode.\n */\n\n/**\n * @typedef {Omit<import('@orgajs/orgx').CompileOptions, 'SourceMapGenerator'>} CompileOptions\n *   Default configuration.\n *\n * @typedef RollupPluginOptions\n *   Extra configuration.\n * @property {FilterPattern} [include]\n *   List of picomatch patterns to include\n * @property {FilterPattern} [exclude]\n *   List of picomatch patterns to exclude\n *\n * @typedef {CompileOptions & RollupPluginOptions} Options\n *   Configuration.\n */\n\nimport { createProcessor } from '@orgajs/orgx'\nimport { createFilter } from '@rollup/pluginutils'\nimport { SourceMapGenerator } from 'source-map'\nimport { VFile } from 'vfile'\n\n/**\n * Compile org-mode w/ rollup.\n *\n * @param {Options | null | undefined} [options]\n *   Configuration.\n * @return {Plugin}\n *   Rollup plugin.\n */\nexport default function rollup(options) {\n\tconst { include, exclude, ...rest } = options || {}\n\t/** @type {ReturnType<typeof import('@orgajs/orgx').createProcessor>} */\n\tlet processor\n\tconst filter = createFilter(include, exclude)\n\n\treturn {\n\t\tname: '@orgajs/rollup',\n\t\tconfig(_config, env) {\n\t\t\tprocessor = createProcessor({\n\t\t\t\tSourceMapGenerator,\n\t\t\t\tdevelopment: env.mode === 'development',\n\t\t\t\t...rest\n\t\t\t})\n\t\t},\n\t\tasync transform(value, path) {\n\t\t\tprocessor ||= createProcessor({\n\t\t\t\tSourceMapGenerator,\n\t\t\t\t...rest\n\t\t\t})\n\n\t\t\tconst file = new VFile({ value, path })\n\n\t\t\tif (file.extname === '.org' && filter(file.path)) {\n\t\t\t\tconst compiled = await processor.process(file)\n\t\t\t\tconst code = String(compiled.value)\n\t\t\t\t/** @type {SourceDescription} */\n\t\t\t\tconst result = {\n\t\t\t\t\tcode,\n\t\t\t\t\tmap: compiled.map\n\t\t\t\t}\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "packages/rollup/package.json",
    "content": "{\n\t\"name\": \"@orgajs/rollup\",\n\t\"version\": \"1.3.4\",\n\t\"description\": \"Rollup plugin for Orga\",\n\t\"license\": \"MIT\",\n\t\"files\": [\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": {\n\t\t\".\": {\n\t\t\t\"types\": \"./index.d.ts\",\n\t\t\t\"import\": \"./index.js\"\n\t\t}\n\t},\n\t\"type\": \"module\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"homepage\": \"https://orga.js.org\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/rollup\"\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"node --test test.js\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/node\": \"^25.3.2\",\n\t\t\"@types/react\": \"^19.0.8\",\n\t\t\"@types/react-dom\": \"^19.0.3\",\n\t\t\"react\": \"^19.0.0\",\n\t\t\"react-dom\": \"^19.0.0\",\n\t\t\"rollup\": \"^4.59.0\"\n\t},\n\t\"peerDependencies\": {\n\t\t\"rollup\": \">=2\"\n\t},\n\t\"dependencies\": {\n\t\t\"@orgajs/orgx\": \"workspace:^\",\n\t\t\"@rollup/pluginutils\": \"^5.1.4\",\n\t\t\"source-map\": \"^0.7.4\",\n\t\t\"vfile\": \"^6.0.3\"\n\t}\n}\n"
  },
  {
    "path": "packages/rollup/test.js",
    "content": "import assert from 'node:assert'\nimport { promises as fs } from 'node:fs'\nimport test from 'node:test'\nimport { fileURLToPath } from 'node:url'\nimport { createElement } from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { rollup } from 'rollup'\nimport rollupOrg from './index.js'\n\ntest('@orgajs/rollup', async () => {\n\tawait fs.writeFile(new URL('rollup.org', import.meta.url), '* Hi')\n\n\tconst bundle = await rollup({\n\t\tinput: fileURLToPath(new URL('rollup.org', import.meta.url)),\n\t\texternal: ['react/jsx-runtime'],\n\t\tplugins: [rollupOrg()]\n\t})\n\n\tconst { output } = await bundle.generate({ format: 'es', sourcemap: true })\n\n\tawait fs.writeFile(new URL('rollup.js', import.meta.url), output[0].code)\n\n\t/* @ts-expect-error file is dynamically generated */\n\n\tconst { default: Content } = await import('./rollup.js')\n\n\t// T.is(output[0].map ? output[0].map.mappings : undefined, undefined)\n\n\tassert.equal(\n\t\trenderToStaticMarkup(createElement(Content)),\n\t\t'<div class=\"section\"><h1>Hi</h1></div>'\n\t)\n\n\tawait fs.unlink(new URL('rollup.org', import.meta.url))\n\tawait fs.unlink(new URL('rollup.js', import.meta.url))\n})\n"
  },
  {
    "path": "packages/rollup/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/text-kit/CHANGELOG.md",
    "content": "# Change Log\n\n## 4.5.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n\n## 4.5.0\n\n### Minor Changes\n\n- a53cfea: all about the editor\n\n  This release improves the editor with new fold/shift/todo actions and settings, while also refactoring orga tokenization/parsing and lezer conversion to improve TODO handling, context hashing, and tree generation consistency.\n\n## 4.4.0\n\n### Minor Changes\n\n- 188d30f: - migrate most of modules to js\n  - fix types during the process\n  - remove unmaintained modules\n\n## 4.3.0\n\n### Minor Changes\n\n- d8861c2: update unified ecosystem\n\n## 4.2.0\n\n### Minor Changes\n\n- ac322714: implement editor\n\n## 4.1.0\n\n### Minor Changes\n\n- 4d8efbb7: Add increamental parsing ability for the editor.\n\n## 4.0.0\n\n### Major Changes\n\n- 176a3b5d: # Migrate most of the ecosystem to ESM\n\n  We are excited to announce that we have migrated most of our ecosystem to ESM! This move was necessary as the unified ecosystem had already transitioned to ESM, leaving our orgajs system stuck on an older version if we wanted to stay on commonjs. We understand that this transition may come with some inevitable breaking changes, but we have done our best to make it as gentle as possible.\n\n  In the past, ESM support in popular frameworks like webpack, gatsby, and nextjs was problematic, but the JS world has steadily moved forward, and we are now in a much better state. We have put in a lot of effort to bring this project up to speed, and we are happy to say that it's in a pretty good state now.\n\n  We acknowledge that there are still some missing features that we will gradually add back over time. However, we feel that the changes are now in a great state to be released to the world. If you want to use the new versions, we recommend checking out the `examples` folder to get started.\n\n  We understand that this upgrade path may not be compatible with older versions, and we apologize for any inconvenience this may cause. However, we encourage you to consider starting fresh, as the most important part of your site should always be your content (org-mode files). Thank you for your understanding, and we hope you enjoy the new and improved ecosystem!\n\n## 3.0.2\n\n### Patch Changes\n\n- eeccc870: - get image links out of paragraph\n  - some other minor fixes\n\n## 3.0.1\n\n### Patch Changes\n\n- 6ed76057: # rename gatsby themes\n\n  - gatsby-theme-orga -> gatsby-theme-orga-posts-core\n  - gatsby-theme-blorg -> gatsby-theme-orga-posts\n\n  # add example projects\n\n  - gatsby-posts\n  - gatsby-posts-core\n\n- 759e6149: # Bug Fixes\n\n  - fix lexer for parsing headline with todo keyword\n  - fix properties drawer issue\n  - fix orga-theme-ui-preset package\n  - fix gatsby-transformer-orga & gatsby-theme-blorg\n\n  # Improved Playground\n\n  - add `tokens` view\n  - show node type in tree views\n\n## 3.0.0\n\n### Major Changes\n\n- 8b02d10: # Features\n\n  - more powerful and flexible lexer and parser\n  - webpack support\n  - `jsx` support\n  - better code block rendering\n  - better image processing in gatsby\n  - updated examples\n  - tons of bug fixes\n  - brand new `gatsby-plugin-orga`\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://conventionalcommits.org) for commit guidelines.\n\n# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)\n\n### Bug Fixes\n\n- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))\n- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))\n\n# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)\n\n**Note:** Version bump only for package text-kit\n\n## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)\n\n**Note:** Version bump only for package text-kit\n\n## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)\n\n**Note:** Version bump only for package text-kit\n\n## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)\n\n**Note:** Version bump only for package text-kit\n"
  },
  {
    "path": "packages/text-kit/README.md",
    "content": "# `text-kit`\n\n> TODO: description\n\n## Usage\n\n```\nconst textKit = require('text-kit');\n\n// TODO: DEMONSTRATE API\n```\n"
  },
  {
    "path": "packages/text-kit/index.js",
    "content": "/**\n * @import {Point} from 'unist'\n * @typedef {ReturnType<typeof reader>} Reader\n * @typedef {object} Range\n * @property {Point | number} start\n * @property {Point | number} end\n */\n\nimport core from './lib/core.js'\nimport reader from './lib/reader.js'\n\n/**\n * @param {string} text\n * @param {Partial<Range>} [range={}]\n * @returns {Reader}\n */\nexport function read(text, range = {}) {\n\treturn reader(core(text), range)\n}\n"
  },
  {
    "path": "packages/text-kit/lib/core.js",
    "content": "/**\n * @import {Point,Position} from 'unist'\n */\n\n/**\n * @typedef {object} CoreAPI\n * @property {string} text\n * @property {number} numberOfLines\n * @property {(index: number) => Point} toPoint\n * @property {(point: Point | number) => number} toIndex\n * @property {(ln: number) => Point | null} bol\n * @property {(ln: number) => Point | null} eol\n * @property {(point: Point, offset: number) => Point} shift\n */\n\n/**\n * @param {number} num\n * @param {number} min\n * @param {number} max\n */\nfunction clamp(num, min, max) {\n\treturn num > max ? max : num < min ? min : num\n}\n\n/**\n * @param {string} text\n * @returns {CoreAPI}\n */\nfunction core(text) {\n\tconst strLines = text.split(/^/gm)\n\tconst lines = strLines.length > 0 ? [0] : [] // index of line starts\n\tstrLines.slice(0, strLines.length - 1).forEach((l, i) => {\n\t\tlines.push(lines[i] + l.length)\n\t})\n\n\tfunction eof() {\n\t\tif (lines.length === 0) {\n\t\t\treturn { line: 1, column: 1, offset: 0 }\n\t\t}\n\t\treturn {\n\t\t\tline: lines.length,\n\t\t\tcolumn: text.length - lines[lines.length - 1] + 1,\n\t\t\toffset: text.length\n\t\t}\n\t}\n\n\t/**\n\t * @param {number} ln\n\t * @returns {Point | null}\n\t */\n\tfunction bol(ln) {\n\t\tconst lineIndex = ln - 1\n\t\tif (lineIndex >= lines.length || lineIndex < 0) return null\n\t\treturn { line: ln, column: 1, offset: lines[ln - 1] }\n\t}\n\n\t/**\n\t * @param {number} ln\n\t * @returns {Point | null}\n\t */\n\tfunction eol(ln) {\n\t\tif (ln > lines.length || ln < 1) return null\n\t\tconst lastLine = ln === lines.length\n\t\treturn lastLine ? eof() : toPoint(lines[ln] - 1)\n\t}\n\n\t/**\n\t * @param {Point} point\n\t * @param {number} offset\n\t */\n\tfunction shift(point, offset) {\n\t\treturn toPoint(toIndex(point) + offset)\n\t}\n\n\t/**\n\t * @param {number} index\n\t * @returns {Point}\n\t */\n\tfunction toPoint(index) {\n\t\tif (index <= 0) return { line: 1, column: 1, offset: 0 }\n\t\tif (index >= text.length) return eof()\n\t\tlet lineIndex = lines.findIndex((l) => l > index)\n\t\tif (lineIndex < 0) {\n\t\t\tlineIndex = lines.length\n\t\t}\n\n\t\treturn {\n\t\t\tline: lineIndex,\n\t\t\tcolumn: index - lines[lineIndex - 1] + 1,\n\t\t\toffset: index\n\t\t}\n\t}\n\n\t/**\n\t * @param {Point|number} point\n\t * @returns {number}\n\t */\n\tfunction toIndex(point) {\n\t\tif (typeof point === 'number') return clamp(point, 0, text.length)\n\t\tif (point.offset) return clamp(point.offset, 0, text.length)\n\t\tconst lineIndex = point.line - 1\n\t\tif (lineIndex < 0 || lines.length === 0) return 0\n\t\tif (lineIndex >= lines.length) return text.length\n\t\tconst i = lines[lineIndex] + point.column - 1\n\t\treturn Math.min(i, text.length)\n\t}\n\n\treturn {\n\t\tget text() {\n\t\t\treturn text\n\t\t},\n\t\tget numberOfLines() {\n\t\t\treturn lines.length\n\t\t},\n\t\tshift,\n\t\ttoPoint,\n\t\ttoIndex,\n\t\tbol,\n\t\teol\n\t}\n}\n\nexport default core\n"
  },
  {
    "path": "packages/text-kit/lib/reader.js",
    "content": "/**\n * @import {Point,Position} from 'unist'\n * @import {CoreAPI} from './core.js'\n * @import {Range} from '../index.js'\n */\n\n/**\n * @typedef {'char'|'line'|'whitespaces'|'newline'|RegExp|number} eatable\n */\n\nimport enhance from './utils/index.js'\n\n/**\n * @type {Record<string,string>}\n */\nconst PAIRS = [\n\t['{', '}'],\n\t['[', ']'],\n\t['(', ')'],\n\t['<', '>']\n].reduce((all, [l, r]) => {\n\treturn {\n\t\t...all,\n\t\t[l]: r,\n\t\t[r]: l\n\t}\n}, {})\n\n/**\n * @param {CoreAPI} _core\n * @param {Partial<Range>} [range={}]\n */\nfunction reader(_core, range = {}) {\n\tconst core = enhance(_core)\n\n\tlet cursor = core.toIndex(range.start || 0)\n\tconst end = core.toIndex(range.end || Infinity)\n\n\tconst getChar = (offset = 0) => {\n\t\tconst index = cursor + offset\n\t\tif (index >= end || index < 0) return undefined\n\t\treturn core.text.charAt(index)\n\t}\n\n\t/**\n\t * Get the current line\n\t * returns null if cursor is at the end of the document\n\t */\n\tfunction getLine() {\n\t\tconst pos = core.linePosition(cursor)\n\t\tif (!pos) return null\n\t\treturn core.substring(cursor, pos.end)\n\t}\n\n\t/**\n\t * @param {Point|number} point\n\t */\n\tfunction jump(point) {\n\t\tcursor = Math.min(end, core.toIndex(point))\n\t}\n\n\tconst now = () => core.toPoint(cursor)\n\n\t/**\n\t * @param {eatable} [param='char']\n\t * @returns {{position:Position,value:string}|undefined}\n\t */\n\tfunction eat(param = 'char') {\n\t\tlet value\n\n\t\tconst position = {\n\t\t\tstart: core.toPoint(cursor),\n\t\t\tend: core.toPoint(cursor)\n\t\t}\n\n\t\tif (cursor >= end) return undefined\n\t\tif (param === 'char') {\n\t\t\tvalue = getChar()\n\t\t\tcursor += 1\n\t\t} else if (param === 'line') {\n\t\t\tconst lineEnd = core.linePosition(cursor)\n\t\t\tconst e =\n\t\t\t\tlineEnd === null ? end : Math.min(end, lineEnd.end.offset ?? end)\n\t\t\tvalue = core.substring(cursor, e)\n\t\t\tcursor = e\n\t\t} else if (param === 'whitespaces') {\n\t\t\treturn eat(/^[ \\t]+/)\n\t\t} else if (param === 'newline') {\n\t\t\treturn eat(/^[\\n\\r]/)\n\t\t} else if (typeof param === 'number') {\n\t\t\tconst adv = Math.min(param, end - cursor)\n\t\t\tvalue = core.text.substring(cursor, cursor + adv)\n\t\t\tcursor += adv\n\t\t} else {\n\t\t\tconst m = match(param)\n\t\t\tif (!m) return\n\t\t\tif (m.position.end.offset !== undefined) cursor = m.position.end.offset\n\t\t\tvalue = m.result[0]\n\t\t}\n\n\t\tposition.end = core.toPoint(cursor)\n\t\treturn {\n\t\t\tposition,\n\t\t\tvalue: value || ''\n\t\t}\n\t}\n\n\t/**\n\t * @param {RegExp} pattern\n\t * @param {Partial<Position>} [range={}]\n\t */\n\tfunction match(pattern, range = {}) {\n\t\tconst s = range.start?.offset || cursor\n\t\tconst e = range.end?.offset || end\n\t\tconst str = core.text.substring(s, e)\n\t\tconst m = pattern.exec(str)\n\t\tif (!m) return\n\t\treturn {\n\t\t\tresult: m,\n\t\t\tposition: {\n\t\t\t\tstart: core.toPoint(cursor + m.index),\n\t\t\t\tend: core.toPoint(cursor + m.index + m[0].length)\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Find the closing pair of a character\n\t * @param {Point|number} [index=cursor]\n\t */\n\tfunction findClosing(index = cursor) {\n\t\tlet cursor = core.toIndex(index)\n\t\tconst opening = core.text.charAt(cursor)\n\t\tif (!opening) return\n\t\tconst closing = PAIRS[opening] || opening\n\n\t\tlet balance = 1\n\t\tcursor += 1\n\t\twhile (cursor < end) {\n\t\t\tconst char = core.text.charAt(cursor)\n\t\t\tif (char === opening) {\n\t\t\t\tbalance += 1\n\t\t\t}\n\n\t\t\tif (char === closing) {\n\t\t\t\tif (opening !== closing) {\n\t\t\t\t\tbalance -= 1\n\t\t\t\t} else {\n\t\t\t\t\tbalance = 0\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (balance === 0) {\n\t\t\t\treturn core.toPoint(cursor)\n\t\t\t}\n\t\t\tcursor += 1\n\t\t}\n\t}\n\n\tconst isStartOfLine = () => {\n\t\treturn cursor === 0 || getChar(-1) === '\\n'\n\t}\n\n\t/**\n\t * Find the first index of a string\n\t * @param {string }str\n\t * @param {Partial<Position>} [range={}]\n\t */\n\tfunction indexOf(str, range = {}) {\n\t\tconst s = range.start?.offset || cursor\n\t\tconst e = range.end?.offset || core.endOfLine(cursor)?.offset || end\n\t\tconst substr = core.text.substring(s, e)\n\t\tconst i = substr.indexOf(str)\n\t\tif (i === -1) return null\n\t\treturn core.toPoint(cursor + i)\n\t}\n\n\treturn {\n\t\t...core,\n\t\tgetChar,\n\t\tgetLine,\n\t\teat,\n\t\tjump,\n\t\tmatch,\n\t\tindexOf,\n\t\tfindClosing,\n\t\tisStartOfLine,\n\t\tnow: () => {\n\t\t\treturn now()\n\t\t},\n\n\t\tbeginOfLine: () => core.beginOfLine(cursor),\n\t\tendOfLine: () => core.endOfLine(cursor),\n\n\t\t/**\n\t\t * Read a range of text\n\t\t * @param {Partial<Range>} [range={}]\n\t\t */\n\t\tread: (range = {}) => {\n\t\t\treturn reader(_core, {\n\t\t\t\tstart: range.start || cursor,\n\t\t\t\tend: range.end || end\n\t\t\t})\n\t\t}\n\t}\n}\n\nexport default reader\n"
  },
  {
    "path": "packages/text-kit/lib/utils/index.js",
    "content": "/**\n * @import {CoreAPI} from '../core.js'\n */\n\nimport lines from './lines.js'\nimport substring from './substring.js'\n\n/**\n * @param {CoreAPI} core\n */\nexport default function enhance(core) {\n\treturn substring(lines(core))\n}\n"
  },
  {
    "path": "packages/text-kit/lib/utils/lines.js",
    "content": "/**\n * @import {Point,Position} from 'unist'\n * @import {CoreAPI} from '../core.js'\n */\n\n/**\n * @callback linePosition\n * @param {Point|number} start\n * @param {Point|number} [end]\n * @returns {Position|null}\n *\n * @callback endOfLine\n * @param {Point|number} ln\n * @returns {Point|undefined}\n *\n * @callback beginOfLine\n * @param {Point|number} ln\n * @returns {Point|undefined}\n *\n */\n\n/**\n * @template {CoreAPI} T\n * @param {T} core\n * @returns {T & {linePosition: linePosition, endOfLine: endOfLine, beginOfLine: beginOfLine}}\n */\nexport default function (core) {\n\t/**\n\t * @type {linePosition}\n\t */\n\tfunction linePosition(start, end) {\n\t\tlet result = null\n\n\t\tif (typeof start === 'number') {\n\t\t\tresult = linePosition(core.toPoint(start))\n\t\t} else {\n\t\t\tconst s = core.bol(start.line)\n\t\t\tconst e = core.eol(start.line)\n\t\t\tif (!s || !e) return null\n\t\t\tresult = {\n\t\t\t\tstart: s,\n\t\t\t\tend: e\n\t\t\t}\n\t\t}\n\n\t\tif (end && result) {\n\t\t\tconst endLR = linePosition(end)\n\t\t\tif (!endLR) return null\n\t\t\tresult.end = endLR.end\n\t\t}\n\n\t\treturn result\n\t}\n\n\t/**\n\t * @type {endOfLine}\n\t */\n\tfunction endOfLine(ln) {\n\t\tconst pos = linePosition(ln)\n\t\tif (!pos) return undefined\n\t\treturn pos.end\n\t}\n\n\t/**\n\t * @type {beginOfLine}\n\t */\n\tconst beginOfLine = (ln) => {\n\t\tconst pos = linePosition(ln)\n\t\tif (!pos) return undefined\n\t\treturn pos.start\n\t}\n\n\treturn {\n\t\t...core,\n\t\tlinePosition,\n\t\tendOfLine,\n\t\tbeginOfLine\n\t}\n}\n"
  },
  {
    "path": "packages/text-kit/lib/utils/substring.js",
    "content": "/**\n * @import {Point} from 'unist'\n * @import {CoreAPI} from '../core.js'\n */\n\n/**\n * @callback substring\n * @param {Point|number} start\n * @param {Point|number} [end]\n * @returns {string}\n */\n\n/**\n * @template {CoreAPI} T\n * @param {T} core\n * @returns {T & {substring: substring}}\n */\nexport default function addSubstring(core) {\n\t/**\n\t * @type {substring}\n\t */\n\tfunction substring(start, end) {\n\t\tconst { toIndex } = core\n\t\treturn core.text.substring(toIndex(start), end && toIndex(end))\n\t}\n\treturn {\n\t\t...core,\n\t\tsubstring\n\t}\n}\n"
  },
  {
    "path": "packages/text-kit/package.json",
    "content": "{\n\t\"name\": \"text-kit\",\n\t\"version\": \"4.5.1\",\n\t\"description\": \"bundle of useful tools for manipulating text\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\",\n\t\"homepage\": \"https://github.com/orgapp/orgajs/tree/main/packages/text-kit#readme\",\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/orgapp/orgajs.git\",\n\t\t\"directory\": \"packages/text-kit\"\n\t},\n\t\"license\": \"MIT\",\n\t\"type\": \"module\",\n\t\"files\": [\n\t\t\"lib\",\n\t\t\"index.js\",\n\t\t\"index.d.ts\",\n\t\t\"index.d.ts.map\"\n\t],\n\t\"exports\": \"./index.js\",\n\t\"scripts\": {\n\t\t\"test\": \"node --test --no-warnings tests/*.js\"\n\t},\n\t\"bugs\": {\n\t\t\"url\": \"https://github.com/orgapp/orgajs/issues\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@types/unist\": \"3.0.3\",\n\t\t\"tsx\": \"^4.19.2\",\n\t\t\"typescript\": \"^5.9.2\"\n\t}\n}\n"
  },
  {
    "path": "packages/text-kit/tests/core.js",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport core from '../lib/core.js'\n\ndescribe('numberOfLines', () => {\n\tconst testCases = [\n\t\t{ desc: 'empty string', input: '', expected: 0 },\n\t\t{ desc: 'just a newline', input: '\\n', expected: 1 },\n\t\t{ desc: 'with one newline', input: 'test\\n', expected: 1 },\n\t\t{ desc: 'with some newlines', input: 'test1\\ntest2\\n', expected: 2 },\n\t\t{ desc: 'starts with newline', input: '\\ntest', expected: 2 },\n\t\t{ desc: 'ends with newline', input: 'test\\n', expected: 1 },\n\t\t{ desc: 'ends with carriage return', input: 'test\\r', expected: 1 },\n\t\t{ desc: 'split with carriage return', input: 'test\\rtest', expected: 2 }\n\t]\n\n\ttestCases.forEach(({ desc, input, expected }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(input)\n\t\t\tassert.deepStrictEqual(c.numberOfLines, expected)\n\t\t})\n\t})\n})\n\nconst multilineText = ['abcd', '1234', 'xy'].join('\\n')\n\nconst shared = [\n\t{\n\t\tdesc: 'begining of file',\n\t\ttext: multilineText,\n\t\tindex: 0,\n\t\tpoint: { line: 1, column: 1, offset: 0 }\n\t},\n\t{\n\t\tdesc: 'end of file',\n\t\ttext: multilineText,\n\t\tindex: 11,\n\t\tpoint: { line: 3, column: 2, offset: 11 }\n\t},\n\t{\n\t\tdesc: 'on newline',\n\t\ttext: multilineText,\n\t\tindex: 4,\n\t\tpoint: { line: 1, column: 5, offset: 4 }\n\t},\n\t{\n\t\tdesc: 'on last newline',\n\t\ttext: 'abcd\\n',\n\t\tindex: 4,\n\t\tpoint: { line: 1, column: 5, offset: 4 }\n\t},\n\t{\n\t\tdesc: 'no newline',\n\t\ttext: 'abcd',\n\t\tindex: 1,\n\t\tpoint: { line: 1, column: 2, offset: 1 }\n\t}\n]\n\ndescribe('toPoint', () => {\n\tconst testCases = [\n\t\t...shared,\n\t\t{\n\t\t\tdesc: 'before begining',\n\t\t\ttext: multilineText,\n\t\t\tindex: -1,\n\t\t\tpoint: { line: 1, column: 1, offset: 0 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after end',\n\t\t\ttext: multilineText,\n\t\t\tindex: 20,\n\t\t\tpoint: { line: 3, column: 3, offset: 12 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after last newline',\n\t\t\ttext: 'abcd\\n',\n\t\t\tindex: 10,\n\t\t\tpoint: { line: 1, column: 6, offset: 5 }\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, index, point, text }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(text)\n\t\t\tassert.deepStrictEqual(c.toPoint(index), point)\n\t\t})\n\t})\n})\n\ndescribe('toIndex', () => {\n\tconst testCases = [\n\t\t...shared,\n\t\t{\n\t\t\tdesc: 'before begining with negative offset',\n\t\t\ttext: multilineText,\n\t\t\tindex: 0,\n\t\t\tpoint: { line: -1, column: 1, offset: -1 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'before begining with negative line',\n\t\t\ttext: multilineText,\n\t\t\tindex: 0,\n\t\t\tpoint: { line: -1, column: 1 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'wrong line and column',\n\t\t\ttext: multilineText,\n\t\t\tindex: 2,\n\t\t\tpoint: { line: 10, column: 99, offset: 2 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after end with offset',\n\t\t\ttext: multilineText,\n\t\t\tindex: 12,\n\t\t\tpoint: { line: -1, column: 1, offset: 20 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after end with line 1',\n\t\t\ttext: multilineText,\n\t\t\tindex: 12,\n\t\t\tpoint: { line: 4, column: 1 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after end with line 2',\n\t\t\ttext: multilineText,\n\t\t\tindex: 12,\n\t\t\tpoint: { line: 10, column: 1 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'after end with column',\n\t\t\ttext: multilineText,\n\t\t\tindex: 12,\n\t\t\tpoint: { line: 3, column: 5 }\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, point, index, text }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(text)\n\t\t\tassert.deepStrictEqual(c.toIndex(point), index)\n\t\t})\n\t})\n})\n\ndescribe('shift', () => {\n\tconst testCases = [\n\t\t{\n\t\t\tdesc: 'move forward',\n\t\t\tpoint: { line: 1, column: 1 },\n\t\t\toffset: 2,\n\t\t\ttext: multilineText,\n\t\t\texpected: { line: 1, column: 3, offset: 2 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'move backward',\n\t\t\tpoint: { line: 2, column: 1 },\n\t\t\toffset: -2,\n\t\t\ttext: multilineText,\n\t\t\texpected: { line: 1, column: 4, offset: 3 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'move beyond end',\n\t\t\tpoint: { line: 2, column: 1 },\n\t\t\toffset: 99,\n\t\t\ttext: multilineText,\n\t\t\texpected: { line: 3, column: 3, offset: 12 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'move beyond begining',\n\t\t\tpoint: { line: 2, column: 1 },\n\t\t\toffset: -99,\n\t\t\ttext: multilineText,\n\t\t\texpected: { line: 1, column: 1, offset: 0 }\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, point, offset, expected, text }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(text)\n\t\t\tassert.deepStrictEqual(c.shift(point, offset), expected)\n\t\t})\n\t})\n})\n\ndescribe('bol', () => {\n\tconst testCases = [\n\t\t{ desc: 'empty document', text: '', ln: 1, expected: null },\n\t\t{\n\t\t\tdesc: 'line before start of document',\n\t\t\ttext: 'text',\n\t\t\tln: -1,\n\t\t\texpected: null\n\t\t},\n\t\t{\n\t\t\tdesc: 'line after end of document',\n\t\t\ttext: 'text',\n\t\t\tln: 2,\n\t\t\texpected: null\n\t\t},\n\t\t{\n\t\t\tdesc: 'some text, no newline',\n\t\t\ttext: 'text',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 1, offset: 0 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'some text, newline',\n\t\t\ttext: 'text\\n',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 1, offset: 0 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'just a newline',\n\t\t\ttext: '\\n',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 1, offset: 0 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'multiline',\n\t\t\ttext: 'test1\\ntest2',\n\t\t\tln: 2,\n\t\t\texpected: { line: 2, column: 1, offset: 6 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'multiline, empty line',\n\t\t\ttext: 'test1\\n\\n',\n\t\t\tln: 2,\n\t\t\texpected: { line: 2, column: 1, offset: 6 }\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, text, ln, expected }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(text)\n\t\t\tassert.deepStrictEqual(c.bol(ln), expected)\n\t\t})\n\t})\n})\n\ndescribe('eol', () => {\n\tconst testCases = [\n\t\t{ desc: 'empty document', text: '', ln: 1, expected: null },\n\t\t{\n\t\t\tdesc: 'line before start of document',\n\t\t\ttext: 'text',\n\t\t\tln: -1,\n\t\t\texpected: null\n\t\t},\n\t\t{\n\t\t\tdesc: 'line after end of document',\n\t\t\ttext: 'text',\n\t\t\tln: 2,\n\t\t\texpected: null\n\t\t},\n\t\t{\n\t\t\tdesc: 'some text, no newline',\n\t\t\ttext: 'text',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 5, offset: 4 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'some text, newline',\n\t\t\ttext: 'text\\n',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 6, offset: 5 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'just a newline',\n\t\t\ttext: '\\n',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 2, offset: 1 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'multiline',\n\t\t\ttext: 'text1\\ntext2',\n\t\t\tln: 2,\n\t\t\texpected: { line: 2, column: 6, offset: 11 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'multiline, empty line',\n\t\t\ttext: 'text1\\n\\n',\n\t\t\tln: 2,\n\t\t\texpected: { line: 2, column: 2, offset: 7 }\n\t\t},\n\t\t{\n\t\t\tdesc: 'newline (carriage return)',\n\t\t\ttext: 'text\\r',\n\t\t\tln: 1,\n\t\t\texpected: { line: 1, column: 6, offset: 5 }\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, text, ln, expected }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = core(text)\n\t\t\tassert.deepStrictEqual(c.eol(ln), expected)\n\t\t})\n\t})\n})\n\n// describe('linePosition', () => {\n\n//   const c = core('hello\\nworld\\n')\n\n//   it('could get by middle of line', () => {\n//     expect(c.linePosition(7)).toEqual({\n//       start: { line: 2, column: 1, offset: 6 },\n//       end: { line: 2, column: 7, offset: 12 },\n//     })\n//   })\n\n//   it('could get by begin of line', () => {\n//     expect(c.linePosition(6)).toEqual({\n//       start: { line: 2, column: 1, offset: 6 },\n//       end: { line: 2, column: 7, offset: 12 },\n//     })\n//   })\n\n//   it('could get by end of line', () => {\n//     expect(c.linePosition(5)).toEqual({\n//       start: { line: 1, column: 1, offset: 0 },\n//       end: { line: 2, column: 1, offset: 6 },\n//     })\n//   })\n\n//   it('could handle index out of bound', () => {\n//     expect(c.linePosition(12)).toEqual({\n//       start: { line: 2, column: 7, offset: 12 },\n//       end: { line: 2, column: 7, offset: 12 },\n//     })\n//   })\n\n//   it('could handle negative index', () => {\n//     expect(c.linePosition(-1)).toEqual({\n//       start: { line: 1, column: 1, offset: 0 },\n//       end: { line: 1, column: 1, offset: 0 },\n//     })\n//   })\n\n//   it('could handle begin of file', () => {\n//     expect(c.linePosition(0)).toEqual({\n//       start: { line: 1, column: 1, offset: 0 },\n//       end: { line: 2, column: 1, offset: 6 },\n//     })\n//   })\n\n//   it('could get by last char', () => {\n//     expect(c.linePosition(11)).toEqual({\n//       start: { line: 2, column: 1, offset: 6 },\n//       end: { line: 2, column: 7, offset: 12 },\n//     })\n//   })\n\n// })\n"
  },
  {
    "path": "packages/text-kit/tests/lines.js",
    "content": "import assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport core from '../lib/core.js'\nimport lines from '../lib/utils/lines.js'\n\n// TODO: add more tests\ndescribe('linePosition', () => {\n\tconst testCases = [\n\t\t{\n\t\t\tdesc: 'begin of line',\n\t\t\ttext: 'abcd',\n\t\t\tpoint: { line: 1, column: 1, offset: 0 },\n\t\t\texpected: {\n\t\t\t\tstart: { line: 1, column: 1, offset: 0 },\n\t\t\t\tend: { line: 1, column: 5, offset: 4 }\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdesc: 'middle of line',\n\t\t\ttext: 'abcd',\n\t\t\tpoint: { line: 1, column: 2, offset: 0 },\n\t\t\texpected: {\n\t\t\t\tstart: { line: 1, column: 1, offset: 0 },\n\t\t\t\tend: { line: 1, column: 5, offset: 4 }\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdesc: 'end of line',\n\t\t\ttext: 'abcd',\n\t\t\tpoint: { line: 1, column: 4, offset: 0 },\n\t\t\texpected: {\n\t\t\t\tstart: { line: 1, column: 1, offset: 0 },\n\t\t\t\tend: { line: 1, column: 5, offset: 4 }\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\tdesc: 'out of bound (before)',\n\t\t\ttext: 'abcd',\n\t\t\tpoint: { line: -1, column: 1, offset: -1 },\n\t\t\texpected: null\n\t\t},\n\t\t{\n\t\t\tdesc: 'out of bound (after)',\n\t\t\ttext: 'abcd',\n\t\t\tpoint: { line: 10, column: 1, offset: 100 },\n\t\t\texpected: null\n\t\t}\n\t]\n\n\ttestCases.forEach(({ desc, text, point, expected }) => {\n\t\tit(desc, () => {\n\t\t\tconst c = lines(core(text))\n\t\t\tassert.deepStrictEqual(c.linePosition(point), expected)\n\t\t})\n\t})\n})\n"
  },
  {
    "path": "packages/text-kit/tsconfig.json",
    "content": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "pnpm-workspace.yaml",
    "content": "packages:\n  - 'packages/*'\n  - 'examples/*'\n"
  },
  {
    "path": "shell.nix",
    "content": "let\n  pkgs = import <main> {};\n  nodejs = pkgs.nodejs_20;\n\tpnpm = pkgs.pnpm;\nin\npkgs.mkShell {\n  buildInputs = [ nodejs pnpm ];\n}\n"
  },
  {
    "path": "tsconfig.base.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \".\",\n    \"composite\": true,\n    \"declarationMap\": true,\n    \"module\": \"commonjs\",\n    \"noImplicitAny\": false,\n    \"removeComments\": true,\n    \"noLib\": false,\n    \"emitDecoratorMetadata\": true,\n    \"experimentalDecorators\": true,\n    \"target\": \"ES2020\",\n    \"sourceMap\": true,\n    \"moduleResolution\": \"node\",\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true,\n    \"jsx\": \"react\",\n    \"allowJs\": true,\n    \"lib\": [\"ES2020\", \"dom\"]\n  },\n  \"exclude\": [\n    \"node_modules\",\n    \"**/*.spec.ts\",\n    \"**/*.test.ts\",\n    \"**/__tests__/**\",\n    \"tests/**\"\n  ]\n}\n"
  },
  {
    "path": "tsconfig.esm.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"target\": \"ESNEXT\",\n\t\t\"module\": \"ESNEXT\",\n\t\t\"declaration\": true,\n\t\t\"moduleResolution\": \"node\",\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"skipLibCheck\": true,\n\t\t\"esModuleInterop\": true,\n\t\t\"allowJs\": true,\n\t\t\"lib\": [\"ESNEXT\", \"DOM\"],\n\t\t\"checkJs\": true\n\t},\n\t\"exclude\": [\n\t\t\"node_modules\",\n\t\t\"**/*.spec.ts\",\n\t\t\"**/*.test.ts\",\n\t\t\"**/__tests__/**\",\n\t\t\"tests/**\"\n\t]\n}\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n\t\"compilerOptions\": {\n\t\t\"checkJs\": true,\n\t\t\"allowJs\": true,\n\t\t\"declaration\": true,\n\t\t\"declarationMap\": true,\n\t\t\"emitDeclarationOnly\": true,\n\t\t\"exactOptionalPropertyTypes\": true,\n\t\t\"jsx\": \"preserve\",\n\t\t\"lib\": [\"esnext\", \"dom\"],\n\t\t\"module\": \"esnext\",\n\t\t\"moduleResolution\": \"bundler\",\n\t\t\"skipLibCheck\": true,\n\t\t\"strict\": true,\n\t\t\"target\": \"esnext\"\n\t},\n\t\"exclude\": [\n\t\t\"**/coverage/\",\n\t\t\"**/node_modules/\",\n\t\t\"**/tests/\",\n\t\t\"**/dist/\",\n\t\t\"./packages/reorg-parse/\",\n\t\t\"./packages/reorg/\",\n\t\t\"./packages/loader/\"\n\t],\n\t\"include\": [\"packages/**/*.js\"]\n}\n"
  },
  {
    "path": "tsconfig.packages.json",
    "content": "{\n\t\"files\": [],\n\t\"references\": [\n\t\t{ \"path\": \"packages/text-kit\" },\n\t\t{ \"path\": \"packages/orga\" },\n\t\t{ \"path\": \"packages/oast-to-hast\" },\n\t\t{ \"path\": \"packages/reorg\" },\n\t\t{ \"path\": \"packages/reorg-parse\" },\n\t\t{ \"path\": \"packages/reorg-rehype\" },\n\t\t{ \"path\": \"packages/next\" },\n\t\t{ \"path\": \"packages/react\" },\n\t\t{ \"path\": \"packages/metadata\" },\n\t\t{ \"path\": \"packages/orgx\" },\n\t\t{ \"path\": \"packages/rollup\" }\n\t]\n}\n"
  }
]