Full Code of xiaoxinghu/orgajs for AI

main 511bbeef8998 cached
439 files
820.0 KB
236.4k tokens
340 symbols
1 requests
Download .txt
Showing preview only (924K chars total). Download the full file or copy to clipboard to get everything.
Repository: xiaoxinghu/orgajs
Branch: main
Commit: 511bbeef8998
Files: 439
Total size: 820.0 KB

Directory structure:
gitextract_ms15wv5a/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── ci.yml
│       ├── release.yml
│       └── website.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── CONTRIBUTING.org
├── LICENSE.org
├── README.org
├── biome.json
├── docs/
│   ├── .gitignore
│   ├── _components.tsx
│   ├── _layout.tsx
│   ├── _snippets/
│   │   └── hey.org
│   ├── advanced/
│   │   ├── _layout.tsx
│   │   ├── api.org
│   │   ├── ast.org
│   │   ├── index.org
│   │   └── latex.org
│   ├── contribute.org
│   ├── guides/
│   │   ├── _layout.tsx
│   │   ├── astro.org
│   │   ├── gatsby.org
│   │   ├── index.org
│   │   ├── next.org
│   │   ├── orga-build.org
│   │   └── webpack.org
│   ├── index.org
│   ├── playground.tsx
│   ├── style.css
│   └── tsconfig.json
├── examples/
│   ├── README.org
│   ├── build/
│   │   ├── index.org
│   │   ├── more.org
│   │   ├── package.json
│   │   └── test-content.tsx
│   ├── editor/
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── content.org
│   │   ├── index.html
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── main.ts
│   │   │   └── style.css
│   │   └── tsconfig.json
│   ├── getting-started/
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   └── package.json
│   └── webpack/
│       ├── .babelrc
│       ├── CHANGELOG.md
│       ├── README.org
│       ├── package.json
│       ├── public/
│       │   └── index.html
│       ├── src/
│       │   ├── box.js
│       │   ├── hello.org
│       │   └── index.js
│       └── webpack.config.mjs
├── orga.config.js
├── package.json
├── packages/
│   ├── astro/
│   │   └── README.org
│   ├── codemirror-lang/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── editor/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── actions/
│   │   │   │   ├── fold.js
│   │   │   │   ├── shift.js
│   │   │   │   ├── todo.js
│   │   │   │   └── utils.js
│   │   │   ├── editor.js
│   │   │   ├── extensions/
│   │   │   │   └── cleanup.js
│   │   │   ├── settings.js
│   │   │   ├── setup.js
│   │   │   └── theme.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── esbuild/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── lezer/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── context.js
│   │   │   ├── fragments.js
│   │   │   ├── handlers.js
│   │   │   ├── index.js
│   │   │   ├── nodes.js
│   │   │   ├── oast-to-lezer.js
│   │   │   ├── tree.js
│   │   │   └── types.ts
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── compare-tree.js
│   │   │   └── incremental.test.js
│   │   └── tsconfig.json
│   ├── loader/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.cjs
│   │   ├── index.d.ts
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   └── tests/
│   │       ├── compiler.js
│   │       ├── example.md
│   │       ├── fixture.org
│   │       └── loader.test.js
│   ├── metadata/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   └── test.js
│   │   └── tsconfig.json
│   ├── next/
│   │   └── README.org
│   ├── node-loader/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── oast-to-hast/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── handlers/
│   │   │   │   ├── block.js
│   │   │   │   ├── document.js
│   │   │   │   ├── footnote.js
│   │   │   │   ├── headline.js
│   │   │   │   ├── hr.js
│   │   │   │   ├── html.js
│   │   │   │   ├── index.js
│   │   │   │   ├── keyword.js
│   │   │   │   ├── latex.js
│   │   │   │   ├── link.js
│   │   │   │   ├── list.js
│   │   │   │   ├── newline.js
│   │   │   │   ├── paragraph.js
│   │   │   │   ├── section.js
│   │   │   │   ├── table.js
│   │   │   │   └── text.js
│   │   │   ├── index.js
│   │   │   └── state.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── block.js
│   │   │   ├── classname.js
│   │   │   ├── heading.js
│   │   │   ├── list.js
│   │   │   └── paragraph.js
│   │   └── tsconfig.json
│   ├── oast-to-prose/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── handlers/
│   │   │   │   ├── block.js
│   │   │   │   ├── headline.js
│   │   │   │   ├── index.js
│   │   │   │   ├── link.js
│   │   │   │   ├── newline.js
│   │   │   │   ├── paragraph.js
│   │   │   │   ├── section.js
│   │   │   │   ├── stars.js
│   │   │   │   ├── tags.js
│   │   │   │   ├── text.js
│   │   │   │   └── todo.js
│   │   │   ├── index.js
│   │   │   ├── schema.js
│   │   │   └── state.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   └── text.js
│   │   └── tsconfig.json
│   ├── orga/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── __tests__/
│   │   │   │   ├── block/
│   │   │   │   │   ├── affiliated keyword.json
│   │   │   │   │   ├── affiliated keyword.org
│   │   │   │   │   ├── export.json
│   │   │   │   │   ├── export.org
│   │   │   │   │   ├── missing begin.json
│   │   │   │   │   ├── missing begin.org
│   │   │   │   │   ├── missing end.json
│   │   │   │   │   ├── missing end.org
│   │   │   │   │   ├── standard.json
│   │   │   │   │   └── standard.org
│   │   │   │   ├── footnote/
│   │   │   │   │   ├── multiline.json
│   │   │   │   │   ├── multiline.org
│   │   │   │   │   ├── standard.json
│   │   │   │   │   ├── standard.org
│   │   │   │   │   ├── stopped by empty lines.json
│   │   │   │   │   ├── stopped by empty lines.org
│   │   │   │   │   ├── stopped by footnote.json
│   │   │   │   │   ├── stopped by footnote.org
│   │   │   │   │   ├── stopped by headline.json
│   │   │   │   │   ├── stopped by headline.org
│   │   │   │   │   ├── with block.json
│   │   │   │   │   └── with block.org
│   │   │   │   ├── headline/
│   │   │   │   │   ├── broken drawer.json
│   │   │   │   │   ├── broken drawer.org
│   │   │   │   │   ├── drawers.json
│   │   │   │   │   ├── drawers.org
│   │   │   │   │   ├── keyword.json
│   │   │   │   │   ├── keyword.org
│   │   │   │   │   ├── nested.json
│   │   │   │   │   ├── nested.org
│   │   │   │   │   ├── planning.json
│   │   │   │   │   ├── planning.org
│   │   │   │   │   ├── with tags.json
│   │   │   │   │   └── with tags.org
│   │   │   │   ├── hr/
│   │   │   │   │   ├── standard.json
│   │   │   │   │   └── standard.org
│   │   │   │   ├── index.test.ts
│   │   │   │   ├── keyword/
│   │   │   │   │   ├── multiple todo.json
│   │   │   │   │   ├── multiple todo.org
│   │   │   │   │   ├── other.json
│   │   │   │   │   ├── other.org
│   │   │   │   │   ├── todo.json
│   │   │   │   │   └── todo.org
│   │   │   │   ├── latex/
│   │   │   │   │   ├── does not match.json
│   │   │   │   │   ├── does not match.org
│   │   │   │   │   ├── latex block.json
│   │   │   │   │   ├── latex block.org
│   │   │   │   │   ├── missing begin.json
│   │   │   │   │   ├── missing begin.org
│   │   │   │   │   ├── missing end.json
│   │   │   │   │   └── missing end.org
│   │   │   │   ├── list/
│   │   │   │   │   ├── broken by empty line.json
│   │   │   │   │   ├── broken by empty line.org
│   │   │   │   │   ├── descriptive.json
│   │   │   │   │   ├── descriptive.org
│   │   │   │   │   ├── multiline.json
│   │   │   │   │   ├── multiline.org
│   │   │   │   │   ├── nested.json
│   │   │   │   │   ├── nested.org
│   │   │   │   │   ├── ordered.json
│   │   │   │   │   ├── ordered.org
│   │   │   │   │   ├── unordered.json
│   │   │   │   │   └── unordered.org
│   │   │   │   ├── paragraph/
│   │   │   │   │   ├── anonymous footnote.json
│   │   │   │   │   ├── anonymous footnote.org
│   │   │   │   │   ├── footnote reference at the end.json
│   │   │   │   │   ├── footnote reference at the end.org
│   │   │   │   │   ├── footnote refernece in the middle.json
│   │   │   │   │   ├── footnote refernece in the middle.org
│   │   │   │   │   ├── footnote without body.json
│   │   │   │   │   ├── footnote without body.org
│   │   │   │   │   ├── inline footnote with style.json
│   │   │   │   │   ├── inline footnote with style.org
│   │   │   │   │   ├── inline footnote.json
│   │   │   │   │   ├── inline footnote.org
│   │   │   │   │   ├── inline math.json
│   │   │   │   │   ├── inline math.org
│   │   │   │   │   ├── link with style.json
│   │   │   │   │   ├── link with style.org
│   │   │   │   │   ├── link.json
│   │   │   │   │   ├── link.org
│   │   │   │   │   ├── nested footnote.json
│   │   │   │   │   ├── nested footnote.org
│   │   │   │   │   ├── styled text.json
│   │   │   │   │   └── styled text.org
│   │   │   │   └── table/
│   │   │   │       ├── standard.json
│   │   │   │       ├── standard.org
│   │   │   │       ├── with inline styles.json
│   │   │   │       └── with inline styles.org
│   │   │   ├── index.ts
│   │   │   ├── nodes.ts
│   │   │   ├── options.ts
│   │   │   ├── parse/
│   │   │   │   ├── _parseSymbols.ts
│   │   │   │   ├── _primitive.ts
│   │   │   │   ├── _utils.ts
│   │   │   │   ├── block.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── drawer.ts
│   │   │   │   ├── footnote.ts
│   │   │   │   ├── headline.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── keyword.ts
│   │   │   │   ├── latex.ts
│   │   │   │   ├── list.ts
│   │   │   │   ├── paragraph.ts
│   │   │   │   ├── phrasing.ts
│   │   │   │   ├── planning.ts
│   │   │   │   ├── section.ts
│   │   │   │   └── table.ts
│   │   │   ├── position.ts
│   │   │   ├── timestamp.test.ts
│   │   │   ├── timestamp.ts
│   │   │   ├── todo.test.ts
│   │   │   ├── todo.ts
│   │   │   ├── tokenize/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── debug.ts
│   │   │   │   │   └── tok.ts
│   │   │   │   ├── blank.test.ts
│   │   │   │   ├── block.test.ts
│   │   │   │   ├── block.ts
│   │   │   │   ├── comment.test.ts
│   │   │   │   ├── comment.ts
│   │   │   │   ├── drawer.test.ts
│   │   │   │   ├── drawer.ts
│   │   │   │   ├── empty.ts
│   │   │   │   ├── footnote.test.ts
│   │   │   │   ├── footnote.ts
│   │   │   │   ├── headline.test.ts
│   │   │   │   ├── headline.ts
│   │   │   │   ├── hr.test.ts
│   │   │   │   ├── hr.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── inline/
│   │   │   │   │   ├── footnote.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── link.ts
│   │   │   │   │   ├── math.ts
│   │   │   │   │   └── text.ts
│   │   │   │   ├── inline.test.ts
│   │   │   │   ├── keyword.ts
│   │   │   │   ├── keywords.test.ts
│   │   │   │   ├── latex.ts
│   │   │   │   ├── list.test.ts
│   │   │   │   ├── list.ts
│   │   │   │   ├── partial.test.ts
│   │   │   │   ├── planning.test.ts
│   │   │   │   ├── planning.ts
│   │   │   │   ├── table.test.ts
│   │   │   │   └── table.ts
│   │   │   ├── types.ts
│   │   │   ├── uri.test.ts
│   │   │   ├── uri.ts
│   │   │   └── utils.ts
│   │   └── tsconfig.json
│   ├── orga-build/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── cli.js
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── __tests__/
│   │   │   │   └── build.test.js
│   │   │   ├── app.jsx
│   │   │   ├── build.js
│   │   │   ├── components.js
│   │   │   ├── config.js
│   │   │   ├── content.d.ts
│   │   │   ├── csr.jsx
│   │   │   ├── endpoint.js
│   │   │   ├── files.js
│   │   │   ├── fs.js
│   │   │   ├── index.html
│   │   │   ├── orga.js
│   │   │   ├── plugin.js
│   │   │   ├── serve.js
│   │   │   ├── ssr.jsx
│   │   │   ├── util.js
│   │   │   ├── vite.js
│   │   │   └── watch.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── orgx/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── compile.js
│   │   │   ├── core.js
│   │   │   ├── evaluate.js
│   │   │   ├── plugin/
│   │   │   │   ├── recma-build-jsx-transform.js
│   │   │   │   ├── recma-document.js
│   │   │   │   ├── recma-jsx-rewrite.js
│   │   │   │   └── rehype-recma.js
│   │   │   ├── run.js
│   │   │   ├── types.ts
│   │   │   └── util/
│   │   │       ├── estree-util-create.js
│   │   │       ├── estree-util-declaration-to-expression.js
│   │   │       ├── estree-util-is-declaration.js
│   │   │       ├── estree-util-specifiers-to-declarations.js
│   │   │       ├── estree-util-to-binary-addition.js
│   │   │       ├── estree-util-to-id-or-member-expression.js
│   │   │       ├── is-org-content.js
│   │   │       ├── render-error.js
│   │   │       ├── resolve-evaluate-options.js
│   │   │       └── resolve-file-and-options.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── compile.test.js
│   │   │   └── evaluate.test.js
│   │   └── tsconfig.json
│   ├── react/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── remove-export-keywords.js
│   │   │   └── test.tsx
│   │   └── tsconfig.json
│   ├── react-cm/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── react-editor/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── index.js
│   │   └── package.json
│   ├── reorg-parse/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg-prose/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg-rehype/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── rollup/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── test.js
│   │   └── tsconfig.json
│   └── text-kit/
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── index.js
│       ├── lib/
│       │   ├── core.js
│       │   ├── reader.js
│       │   └── utils/
│       │       ├── index.js
│       │       ├── lines.js
│       │       └── substring.js
│       ├── package.json
│       ├── tests/
│       │   ├── core.js
│       │   └── lines.js
│       └── tsconfig.json
├── pnpm-workspace.yaml
├── shell.nix
├── tsconfig.base.json
├── tsconfig.esm.json
├── tsconfig.json
└── tsconfig.packages.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .changeset/README.md
================================================
# Changesets

Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)

We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)


================================================
FILE: .changeset/config.json
================================================
{
  "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "linked": [],
  "access": "public",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}


================================================
FILE: .editorconfig
================================================
root = true

[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab

[*.{yml,yaml}]
indent_style = space
indent_size = 2

[vcbuild.bat]
end_of_line = crlf

[Makefile]
indent_style = tab
indent_size = 8

[{deps}/**]
indent_style = ignore
indent_size = ignore
end_of_line = ignore
trim_trailing_whitespace = ignore
charset = ignore

[{test/fixtures,deps,tools/node_modules,tools/gyp,tools/icu,tools/msvs}/**]
insert_final_newline = false


================================================
FILE: .eslintignore
================================================
node_modules
**/dist/**
**/__tests__/**/*.json


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms

github: ['xiaoxinghu']


================================================
FILE: .github/workflows/ci.yml
================================================
name: CI

on:
  push:
    branches:
      - main
    paths-ignore:
      - 'docs/**'
      - '**/README.org'
      - '**/README.md'
  pull_request:
    paths-ignore:
      - 'docs/**'
      - '**/README.org'
      - '**/README.md'

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Use Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 24
      - uses: pnpm/action-setup@v4
        with:
          version: 10
          cache: 'pnpm'
      - name: install dependencies
        run: pnpm install
      - name: build packages
        run: pnpm build
      - name: run unit tests
        run: pnpm test


================================================
FILE: .github/workflows/release.yml
================================================
name: Release

on:
  push:
    branches:
      - main

env:
  CI: true

permissions: {}

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    permissions:
      id-token: write      # Required for OIDC trusted publishing
      contents: write      # Required for changesets to commit
      pull-requests: write # Required for changesets to create PRs
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v4
        with:
          # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
          fetch-depth: 0

      - name: Setup Node.js 24
        uses: actions/setup-node@v4
        with:
          node-version: 24

      - uses: pnpm/action-setup@v4
        with:
          version: 10
      - name: install dependencies
        run: pnpm install --no-frozen-lockfile
      - name: Create Release Pull Request or Publish to npm
        uses: changesets/action@v1
        with:
          version: pnpm ci:version
          commit: 'chore: update versions'
          title: 'chore: update versions'
          publish: pnpm ci:publish
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_CONFIG_PROVENANCE: true


================================================
FILE: .github/workflows/website.yml
================================================
name: Deploy to GitHub Pages

on:
  # Trigger the workflow every time you push to the `main` branch
  # Using a different branch name? Replace `main` with your branch’s name
  push:
    branches: [main]
  # Allows you to run this workflow manually from the Actions tab on GitHub.
  workflow_dispatch:

# Allow this job to clone the repo and create a page deployment
permissions:
  contents: read
  pages: write
  id-token: write

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout your repository using git
        uses: actions/checkout@v3

      - name: Setup PNPM
        uses: pnpm/action-setup@v4
        with:
          version: 10

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: pnpm
          cache-dependency-path: pnpm-lock.yaml

      - name: Install
        run: |
          pnpm install
          pnpm run build
          pnpm run docs

      - name: Upload Page Artifact
        uses: actions/upload-pages-artifact@v3
        with:
          path: '.out/'

  deploy:
    needs: build
    # Grant GITHUB_TOKEN the permissions required to make a Pages deployment
    permissions:
      pages: write # to deploy to Pages
      id-token: write # to verify the deployment originates from an appropriate source
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4


================================================
FILE: .gitignore
================================================
# macOS
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon


# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

.npmrc

# private
.archive

/.idea
.vscode

# build artifacts
dist
*.tsbuildinfo

*.d.ts
*.d.ts.map
!packages/reorg-parse/index.d.ts
!packages/loader/index.d.ts
!packages/orga-build/lib/content.d.ts

.meta.json
.orga-build

.turbo
.aider*

.out

.direnv
.website
deprecated


================================================
FILE: .prettierignore
================================================
.archive
.cache
node_modules
.next
public
lib
**/dist/**
.yarn/*
**/__tests__/**/*.json


================================================
FILE: .prettierrc
================================================
{
	"singleQuote": true,
	"semi": false,
	"trailingComma": "none",
	"bracketSpacing": true,
	"useTabs": true
}


================================================
FILE: CHANGELOG.md
================================================
# Change Log

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)

- feat!: major version bump ([998c0f3](https://github.com/orgapp/orgajs/commit/998c0f30a7c8f9af27243b3cb48b650708cdc4b3))

### Bug Fixes

- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))
- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))
- fix headline tags parsing issue [#126](https://github.com/orgapp/orgajs/issues/126) ([71d7f82](https://github.com/orgapp/orgajs/commit/71d7f8277708fc72d3b5be01ed0f72233bf7057b))
- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))
- fix publish script ([7fc1bdf](https://github.com/orgapp/orgajs/commit/7fc1bdfc6880e825cd10d99d108da9685f58638c))
- fix publish script ([f175e5b](https://github.com/orgapp/orgajs/commit/f175e5bb3cad0ce31cc118c1c675fe30b4065fc9))
- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))
- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))
- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))
- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))
- update yarn.lock file ([bf0e695](https://github.com/orgapp/orgajs/commit/bf0e6954246f7ed78a014601aca756cd47fa4fec))

### Features

- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))
- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))
- **gatsby:** process images ([76fdade](https://github.com/orgapp/orgajs/commit/76fdaded0d87a3bc2e188392b520f62ad789598c))

### BREAKING CHANGES

- due to my own lack of knowledge about how conventional commits works in
  lerna, I published the breaking change as a minor version 2.5.0. Here I am
  trying to get it right. It might not work... Sorry for the inconvenience.

## 2.4.9 (2021-07-13)

# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)

### Bug Fixes

- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))
- fix headline regex issue ([a36b75d](https://github.com/orgapp/orgajs/commit/a36b75d87da125f56edf7da1ddaf23771040ce1b))
- fix phrasing content in headline ([31ca41c](https://github.com/orgapp/orgajs/commit/31ca41cb3b9b65a19dbc71a906f86ee4d725ad8f))
- fix publish script ([7fc1bdf](https://github.com/orgapp/orgajs/commit/7fc1bdfc6880e825cd10d99d108da9685f58638c))
- fix publish script ([f175e5b](https://github.com/orgapp/orgajs/commit/f175e5bb3cad0ce31cc118c1c675fe30b4065fc9))
- inline markup check post ([d3d31c6](https://github.com/orgapp/orgajs/commit/d3d31c622dde2a2d469ac41884f2320497f811c6))
- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))
- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))
- update yarn.lock file ([bf0e695](https://github.com/orgapp/orgajs/commit/bf0e6954246f7ed78a014601aca756cd47fa4fec))

### Features

- add jsx support ([0d22499](https://github.com/orgapp/orgajs/commit/0d224990b412e064ebf6816608eea6766f93d60c))
- better code block in website ([3efe4cd](https://github.com/orgapp/orgajs/commit/3efe4cd96a63623e2f70028bd66346960ec90bec))
- **gatsby:** process images ([76fdade](https://github.com/orgapp/orgajs/commit/76fdaded0d87a3bc2e188392b520f62ad789598c))
- **gatsby-plugin-orga:** better code block ([e6d7d20](https://github.com/orgapp/orgajs/commit/e6d7d20f63fa1871d8f53b0534b50ac6d7d99fc9))

## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)

**Note:** Version bump only for package orgajs

## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)

## 2.4.6 (2021-04-25)

**Note:** Version bump only for package orgajs

## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)

**Note:** Version bump only for package orgajs


================================================
FILE: CONTRIBUTING.org
================================================
#+title: How to contribute to orgajs

Hi 👋 🦄.

* Getting Started
Make sure you have latest yarn installed locally.
To get started with the repo, after cloning the repo.

#+begin_src sh
yarn install
#+end_src

* Ways to Contribute

** Improve documentation
Documentations 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.

** Write code and tests
It'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.

** Discussion
Have some cool ideas? Let's talk about it in the [[https://github.com/orgapp/orgajs/discussions][Discussions]] tab.

* Commit Messages

We are following the [[https://www.conventionalcommits.org/en/v1.0.0/][conventional commits]] standards, an example would be:

#+begin_example
feat(parser): add new syntax

this is a body
#+end_example

The 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.

* Run Unit Tests

#+begin_src sh
yarn build # always build before running tests
yarn test
#+end_src

* Submitting Pull Requests
Please submit pull requests against =develop= branch. =master= is for releasing.

* Releasing
All 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=.



================================================
FILE: LICENSE.org
================================================
The MIT License (MIT)

Copyright (c) 2015 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: README.org
================================================
#+title: Orga
#+subtitle: org-mode < JavaScript

* What Is It

=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.

* Why
org-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.

* Compatible Eco-systems
It integrates natively with popular tools.

** [[https://unifiedjs.com][Unified]]

#+BEGIN_QUOTE
☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees
#+END_QUOTE

The =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]].

** [[https://webpack.js.org][Webpack]]
=@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]].


** [[https://reactjs.org/][React]]
#+begin_quote
A JavaScript library for building user interfaces
#+end_quote

You can render react components directly in your org file. Something like this:
#+begin_src org
,* Hello World

Let's render *the box*.

,#+begin_export jsx
<div style={{
  backgroundColor: 'gold',
  padding: '1em',
  border: '1px solid black',
  boxShadow: '5px 5px'
}}>I am a box with shadow</div>
,#+end_export
#+end_src

[[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]].

** [[https://vitejs.dev][Vite]]
#+begin_quote
Next generation frontend tooling
#+end_quote

=@orgajs/rollup= is a plugin compatible with both Rollup and Vite. It lets you import =.org= files directly in your project.

- Package: =@orgajs/rollup=

** [[https://astro.build][Astro]]
#+begin_quote
The web framework for content-driven websites
#+end_quote

Astro integration is maintained in a standalone repository.

- [[https://github.com/orgapp/orga-astro][orga-astro repository]]
- Package: =@orgajs/astro=

** [[https://nextjs.org][Nextjs]]
#+begin_quote
The React Framework
#+end_quote

Next.js integration is maintained in a standalone repository.

- [[https://github.com/orgapp/orga-next][orga-next repository]]
- Package: =@orgajs/next=
- Guide: [[https://orga.js.org/guides/next][Next.js integration guide]]


* Examples
Take a look at the [[https://github.com/orgapp/orgajs/tree/main/examples][collection of examples]] to quickly get started.

* Contribute

See the [[file:CONTRIBUTING.org][contributing file]] for ways to get started.


================================================
FILE: biome.json
================================================
{
	"$schema": "https://biomejs.dev/schemas/2.4.4/schema.json",
	"files": {
		"includes": ["packages/**", "!packages/**/__tests__/**/*.json"]
	},
	"vcs": {
		"enabled": true,
		"clientKind": "git",
		"useIgnoreFile": true
	},
	"formatter": {
		"indentStyle": "tab",
		"bracketSpacing": true
	},
	"javascript": {
		"formatter": {
			"quoteStyle": "single",
			"semicolons": "asNeeded",
			"trailingCommas": "none"
		}
	},
	"linter": {
		"rules": {
			"complexity": {
				"useArrowFunction": "off"
			}
		}
	}
}


================================================
FILE: docs/.gitignore
================================================
out


================================================
FILE: docs/_components.tsx
================================================
import { Editor } from '@orgajs/react-editor'
import { ReactCodeMirror } from '@orgajs/react-cm'
import { tags as t } from '@lezer/highlight'
import { EditorView } from '@codemirror/view'
import {
	HighlightStyle,
	defaultHighlightStyle,
	syntaxHighlighting,
	foldGutter
} from '@codemirror/language'
import { javascript } from '@codemirror/lang-javascript'

export function Notice({
	title,
	children
}: {
	title?: string
	children: React.ReactNode
}) {
	return (
		<div role="alert" className="alert">
			<svg
				xmlns="http://www.w3.org/2000/svg"
				fill="none"
				viewBox="0 0 24 24"
				className="stroke-info h-6 w-6 shrink-0"
			>
				<path
					strokeLinecap="round"
					strokeLinejoin="round"
					strokeWidth="2"
					d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
				></path>
			</svg>
			<span>{children}</span>
		</div>
	)
}

const nord0 = '#2E3440',
	nord1 = '#3B4252',
	nord2 = '#434C5E',
	nord3 = '#4C566A',
	nord4 = '#D8DEE9',
	nord5 = '#E5E9F0',
	nord6 = '#ECEFF4',
	nord7 = '#8FBCBB',
	nord8 = '#88C0D0',
	nord9 = '#81A1C1',
	nord10 = '#5E81AC',
	nord11 = '#BF616A',
	nord12 = '#D08770',
	nord13 = '#EBCB8B',
	nord14 = '#A3BE8C',
	nord15 = '#B48EAD'

const nordTheme = EditorView.theme(
	{
		'&': {
			color: nord4,
			backgroundColor: nord0
		},
		'.cm-content': {
			caretColor: nord4
		},
		'.cm-cursor, .cm-dropCursor': { borderLeftColor: nord4 },
		'&.cm-focused .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection':
			{
				backgroundColor: nord2
			},
		'.cm-panels': { backgroundColor: nord1, color: nord5 },
		'.cm-panels.cm-panels-top': { borderBottom: `2px solid ${nord3}` },
		'.cm-panels.cm-panels-bottom': { borderTop: `2px solid ${nord3}` },
		'.cm-searchMatch': {
			backgroundColor: nord13,
			outline: `1px solid ${nord3}`
		},
		'.cm-searchMatch.cm-searchMatch-selected': {
			backgroundColor: nord12
		},
		'.cm-activeLine': { backgroundColor: nord1 },
		'.cm-activeLineGutter': { backgroundColor: nord2 },
		'.cm-selectionMatch': { backgroundColor: nord3 },
		'.cm-matchingBracket, .cm-nonmatchingBracket': {
			backgroundColor: nord8,
			outline: `none`
		},
		'.cm-gutters': {
			backgroundColor: nord0,
			color: nord3,
			border: 'none'
		},
		'.cm-lineNumbers .cm-gutterElement': {
			padding: '0 3px 0 5px'
		},
		'.cm-tooltip': {
			border: `1px solid ${nord3}`,
			backgroundColor: nord2
		},
		'.cm-tooltip-autocomplete': {
			'& > ul > li[aria-selected]': {
				backgroundColor: nord3,
				color: nord6
			}
		}
	},
	{ dark: true }
)

const nordHighlightStyle = HighlightStyle.define([
	{ tag: t.keyword, color: nord9 },
	{
		tag: [t.name, t.deleted, t.character, t.propertyName, t.macroName],
		color: nord4
	},
	{ tag: [t.function(t.variableName), t.labelName], color: nord8 },
	{ tag: [t.color, t.constant(t.name), t.standard(t.name)], color: nord7 },
	{ tag: [t.definition(t.name), t.separator], color: nord4 },
	{ tag: [t.className], color: nord7 },
	{
		tag: [t.number, t.changed, t.annotation, t.modifier, t.self, t.namespace],
		color: nord15
	},
	{ tag: [t.typeName], color: nord7 },
	{ tag: [t.operator, t.operatorKeyword], color: nord9 },
	{ tag: [t.url, t.escape, t.regexp, t.link], color: nord13 },
	{ tag: [t.meta, t.comment], color: nord3, fontStyle: 'italic' },
	{ tag: [t.strong], fontWeight: 'bold' },
	{ tag: [t.emphasis], fontStyle: 'italic' },
	{ tag: [t.strikethrough], textDecoration: 'line-through' },
	{ tag: [t.string], color: nord14 },
	{ tag: [t.invalid], color: nord11 }
])

const nord = [nordTheme, syntaxHighlighting(nordHighlightStyle)]

export function JSEditor({
	className,
	children
}: {
	className?: string
	children: string
}) {
	return (
		<div className={className}>
			<ReactCodeMirror
				extensions={[
					foldGutter(),
					syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
					javascript(),
					EditorView.editable.of(false),
					nord
				]}
				content={children}
			/>
		</div>
	)
}

export function OrgEditor({ className = '', content, onChange }) {
	return (
		<Editor
			className={className}
			content={content}
			onChange={onChange}
			extensions={[nord]}
		/>
	)
}


================================================
FILE: docs/_layout.tsx
================================================
import { ReactNode } from 'react'
import { Link } from 'orga-build/components'

import type { SVGProps } from 'react'
const GitHub = (props: SVGProps<SVGSVGElement>) => (
	<svg
		width="1em"
		height="1em"
		viewBox="0 0 1024 1024"
		fill="none"
		xmlns="http://www.w3.org/2000/svg"
		{...props}
	>
		<path
			fillRule="evenodd"
			clipRule="evenodd"
			d="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"
			transform="scale(64)"
			fill="#1B1F23"
		/>
	</svg>
)

interface LayoutProps {
	title: string
	children: ReactNode
}

const navItems = [
	{ name: 'Orga', href: '/' },
	{ name: 'Documents', href: '/guides' },
	{ name: 'Playground', href: '/playground' }
]

export default function Layout({ children }: LayoutProps) {
	return (
		<>
			<nav className="navbar bg-base-200 shadow-sm">
				<ol className="flex flex-1 gap-4">
					{navItems.map((item) => (
						<li key={item.name}>
							<Link href={item.href} className="btn btn-ghost">
								{item.name}
							</Link>
						</li>
					))}
				</ol>
				<div className="navbar-end">
					<a
						className="btn btn-ghost btn-circle"
						target="_blank"
						href="https://github.com/orgapp/orgajs"
					>
						<div className="indicator">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								width="24"
								height="24"
								viewBox="0 0 24 24"
								fill="none"
								stroke="currentColor"
								strokeWidth="2"
								strokeLinecap="round"
								strokeLinejoin="round"
							>
								<path stroke="none" d="M0 0h24v24H0z" fill="none" />
								<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" />
							</svg>
						</div>
					</a>
				</div>
			</nav>
			<main className="flex-grow flex-row overflow-hidden">{children}</main>
			<footer className="footer sm:footer-horizontal footer-center bg-base-200 text-base-content p-4">
				<aside>
					<p>Copyright © {new Date().getFullYear()} - All right reserved</p>
				</aside>
			</footer>
			{/* Client-side JS is now added by build process */}
		</>
	)
}

type Page = {
	slug: string
	title: string
	position: number
	type: string
}

function findParentSlug(slug: string, pages: Page[]): string | null {
	const parts = slug.split('/').filter(Boolean)
	while (parts.length > 0) {
		parts.pop()
		const parentSlug = '/' + parts.join('/')
		if (pages.some((p) => p.slug === parentSlug)) return parentSlug
	}
	return null
}

function renderMenu(path: string, pages: Page[]) {
	const children = pages
		.filter(
			(p) => findParentSlug(p.slug, pages) === path && p.type === 'document'
		)
		.sort((a, b) => (Number(a.position) || 0) - (Number(b.position) || 0))

	if (children.length === 0) return null

	return (
		<ul>
			{children.map((child) => (
				<li key={child.slug}>
					<Link href={child.slug}>{child.title}</Link>
					{renderMenu(child.slug, pages)}
				</li>
			))}
		</ul>
	)
}

export function DocumentLayout({ title, pages = [], children }) {
	return (
		<div className="flex h-full w-full">
			<ul className="menu bg-base-300 w-56">{renderMenu('/', pages)}</ul>
			<Content>
				<h1>{title}</h1>
				{children}
			</Content>
		</div>
	)
}

function Content({ children }: { children: ReactNode }) {
	return (
		<div className="overflow-auto h-full w-full">
			<article className="prose p-4">{children}</article>
		</div>
	)
}


================================================
FILE: docs/_snippets/hey.org
================================================
* Hey, there

The /beauty/ of org *must* be shared.
[[https://upload.wikimedia.org/wikipedia/commons/a/a6/Org-mode-unicorn.svg][org-mode logo]]


================================================
FILE: docs/advanced/_layout.tsx
================================================
import { DocumentLayout } from '../_layout.tsx'
export default DocumentLayout


================================================
FILE: docs/advanced/api.org
================================================
#+title: API
#+published: true
#+position: 201
#+type: document

#+jsx: <Notice>This page is a WIP</Notice>

Describe the API.


================================================
FILE: docs/advanced/ast.org
================================================
#+title: AST
#+published: true
#+position: 202
#+type: document

#+jsx: <Notice>This page is a WIP</Notice>

Orga Abstract Syntax Tree.


================================================
FILE: docs/advanced/index.org
================================================
#+title: Advanced
#+published: true
#+type: document
#+position: 200

#+jsx: <Notice>This page is a WIP</Notice>


================================================
FILE: docs/advanced/latex.org
================================================
#+title: Latex Support
#+published: true
#+position: 203
#+type: document


** Inline Math
Orgajs supports inline math with latex math delimiters.

#+begin_src org
If $$a^2=b$$ and \( b=2 \), then the solution must be either $$ a=+\sqrt{2} $$ or \[ a=-\sqrt{2} \].
#+end_src

With be rendered as follows.

If $$a^2=b$$ and \( b=2 \), then the solution must be either $$ a=+\sqrt{2} $$ or \[ a=-\sqrt{2} \].

** Latex Block

It also supports =\begin= commands.

#+begin_src org
\begin{equation}
x=\sqrt{b}
\end{equation}
#+end_src

Will be rendered

\begin{equation}
x=\sqrt{b}
\end{equation}

** Styling

=@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=.


================================================
FILE: docs/contribute.org
================================================
#+title: Contribute
#+published: true
#+position: 300
#+type: document

#+jsx: <Notice>This page is a WIP</Notice>

* Need Some Inspiration?

You 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.


================================================
FILE: docs/guides/_layout.tsx
================================================
import { DocumentLayout } from '../_layout.tsx'
export default DocumentLayout


================================================
FILE: docs/guides/astro.org
================================================
#+title: Astro
#+published: true
#+type: document
#+position: 5

Use =@orgajs/astro= to write Astro pages in Org Mode (=.org=) and compile them with orgx.

* Quick Start

1. Install the integration:

#+begin_src sh
pnpm add @orgajs/astro
#+end_src

2. Register it in =astro.config.mjs=:

#+begin_src javascript
import { defineConfig } from 'astro/config'
import orgMode from '@orgajs/astro'

export default defineConfig({
  integrations: [orgMode()]
})
#+end_src

3. Create a page at =src/pages/index.org=:

#+begin_src org
,* Hello from Org Mode

This page is rendered from Org Mode in Astro.
#+end_src

4. Start Astro:

#+begin_src sh
pnpm astro dev
#+end_src

* Major Features

** Native =.org= pages in Astro
Any file in =src/pages/*.org= is treated as a page route, just like Astro files in other supported formats.

** Org metadata support
Org keywords such as =#+title:=, =#+description:=, and =#+slug:= are parsed and exposed as entry metadata for Astro content handling.

** orgx-powered compilation
Under the hood, this integration uses orgx (via =@orgajs/rollup=), so you get:
- Org Mode parsing to JSX-compatible output
- JavaScript imports/exports inside Org documents
- Unified/rehype/recma pipeline compatibility

** Inline JSX components
You can embed JSX directly in Org files, including imported components.

#+begin_src org
,#+jsx: import Card from '../components/Card.astro'

Here is a Card rendered inline:

,#+jsx: <Card title="Inline component">Hello from Org + JSX</Card>

,#+begin_export jsx
<section className="hero">
  <h2>JSX export block</h2>
  <p>You can also write larger JSX blocks.</p>
</section>
,#+end_export
#+end_src

Use =#+jsx:= for single-line JSX/imports and =#+begin_export jsx= for multi-line blocks.


================================================
FILE: docs/guides/gatsby.org
================================================
#+title: Gatsby
#+published: true
#+type: document
#+position: 102

#+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>

* Create Gatsby Project

Create a new gatsby website following the [[https://www.gatsbyjs.com/get-started/][documentation]]. Or simply

#+begin_src sh
npx gatsby new gatsby-site
#+end_src

* Installation

Install packages.

#+begin_src sh
cd gatsby-site
yarn add gatsby-plugin-orga @orgajs/react @orgajs/loader
#+end_src

* Configuration

Add =gatsby-plugin-orga= to =gatsby-config.js=.

#+begin_src javascript
module.exports = {
  plugins: ['gatsby-plugin-orga']
}
#+end_src

Add a org file in folder =src/pages= directory. It should work out of the box.

For more advanced usage, please checkout code of [[https://github.com/orgapp/orgajs][orgajs project]], which generate this website via =gatsby-theme-orga-docs=.


================================================
FILE: docs/guides/index.org
================================================
#+title: Getting Started
#+published: true
#+type: document
#+position: 100

** Basic Setup
Orga is built on the [[https://unifiedjs.com][unified]] ecosystem. The core parser package =@orgajs/reorg= is the minimum requirement to get started.

** Simple HTML Compilation
To transform Org-mode content into HTML, install the required packages:

#+begin_src sh
npm install @orgajs/reorg @orgajs/reorg-rehype rehype-stringify unified-stream
#+end_src

Create a basic compilation script:

#+begin_src javascript
// compile.js
const stream = require('unified-stream')
const reorg = require('@orgajs/reorg')
const mutate = require('@orgajs/reorg-rehype')
const html = require('rehype-stringify')

const processor = reorg()
      .use(mutate)
      .use(html)

process.stdin.pipe(stream(processor)).pipe(process.stdout)
#+end_src

Convert your Org files to HTML:

#+begin_src sh
node compile.js < input.org > output.html
#+end_src
#+end_src

Example Input (input.org)
#+begin_src org
,* Hello Orga
Orga is *awesome*.
#+end_src

Yields Output (output.html)
#+begin_src html
<div class="section">
	<h1>Hello Orga</h1>
	<p>Orga is <strong class="">awesome</strong>. </p>
</div>
#+end_src


================================================
FILE: docs/guides/next.org
================================================
#+title: Next.js
#+published: true
#+type: document
#+position: 4

Use =@orgajs/next= to write Next.js pages in Org Mode (=.org=) and compile them with orgx.

Standalone repository:

- [[https://github.com/orgapp/orga-next][orgapp/orga-next]]

* Quick Start

1. Install the integration:

#+begin_src sh
pnpm add @orgajs/next @orgajs/loader @orgajs/react
#+end_src

2. Register it in =next.config.js=:

#+begin_src javascript
const withOrg = require('@orgajs/next')()

module.exports = withOrg({
  pageExtensions: ['js', 'jsx', 'ts', 'tsx', 'org'],
})
#+end_src

3. Create a page at =app/page.org= (or =pages/index.org=):

#+begin_src org
,* Hello from Org Mode

This page is rendered from Org Mode in Next.js.
#+end_src

4. Start Next.js:

#+begin_src sh
pnpm next dev
#+end_src

* Major Features

** Native =.org= routes in Next.js
Org files can be used as top-level routes in Next.js once =pageExtensions= includes =org=.

** Works with App Router and Pages Router
You can place Org pages in either:
- =app/**/page.org=
- =pages/**/*.org=

** Global Org component mapping
Create =org-components.js= at project root to override rendered elements globally.

#+begin_src javascript
export function useOrgComponents() {
  return {
    h1: (props) => <h1 style={{ color: 'tomato' }} {...props} />,
  }
}
#+end_src

** orgx-powered compilation
This integration uses =@orgajs/loader= under the hood, providing Org Mode to JSX compilation and compatibility with orgx features.

* Notes

- Package name: =@orgajs/next=
- Repository: [[https://github.com/orgapp/orga-next][orgapp/orga-next]]


================================================
FILE: docs/guides/orga-build.org
================================================
#+title: Build a blog with orga-build
#+position: 2
#+type: document


=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.


Get a bunch of org files in a folder. Run

#+begin_src sh
npx orga-build
#+end_src

This command will generate a static website in the =out= folder, with each Org-mode file translated into an HTML file. The end.

** Layouts

Layout 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.

To 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.

*** Layout Props

Layout 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:

#+begin_src org
,#+title: My Page
,#+author: John
#+end_src

These values will be available as props in your layout file, allowing you to use them dynamically.

Additionally, 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.

** Build Commands

=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:

#+begin_src javascript
export const preBuild = ['npm run build:css']
#+end_src

The =preBuild= and =postBuild= variables should be arrays of strings, where each string represents a shell command to be executed by the build process.

** Custom Components

=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:

#+begin_src jsx
export function FancyBox({ children }) {
  return <div className="fancy">{children}</div>;
}
#+end_src

You can then use these components directly in your Org-mode files using the =#+jsx:= syntax:

#+begin_src org
#+jsx: <FancyBox>hey, box</FancyBox>
#+end_src

This powerful feature enables you to extend the functionality of your website and create rich, interactive experiences.


================================================
FILE: docs/guides/webpack.org
================================================
#+title: Webpack
#+published: true
#+type: document
#+position: 3

=@orgajs/loader= is a webpack loader taht can be used natrually with webpack setup.
For hassle free experience, use [[file:orga-build.org][orga-build]].

* Installation

#+begin_src sh
npm install --save-dev @orgajs/loader @orgajs/estree-jsx @orgajs/rehype-estree @orgajs/reorg-rehype
#+end_src

* Configuration

An example =webpack.config.js= file.

#+begin_src javascript
import toEstree from '@orgajs/rehype-estree'
import toRehype from '@orgajs/reorg-rehype'
import toJsx from '@orgajs/estree-jsx'

const config = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/
      },
      {
        test: /\.org$/,
        use: [
          'babel-loader',
          {
            loader: '@orgajs/loader',
            options: {
              plugins: [
                toRehype,
                toEstree,
                toJsx,
              ]
            }
          }],
      },
    ]
  },
}

export default config
#+end_src

As 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.

* Babel Configuration

YOu will need to configure babel to support react syntax. An example of =.babelrc= file.

#+begin_src json
{
  "presets": ["@babel/env", "@babel/react"]
}
#+end_src

Take a look at webpack documentation for creating a basic react project for more details.


================================================
FILE: docs/index.org
================================================
#+title: Orgajs
#+jsx: import code from './index.org?raw'

* What Is It

=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.

* What can I do with it

** Editor

Introducing org editor. This the source code of *this page*.

#+jsx: <OrgEditor className='h-64 not-prose' content={code}/>

** Publication

Build a website with org-mode files and [[/guides/orga-build][orga-build]].

# the "orga-editor" is a web-component, the following line defines it
#+jsx: <script type="module" src="/editor.js"/>


================================================
FILE: docs/playground.tsx
================================================
import { ReactNode, useEffect, useMemo, useState } from 'react'
import { VFile } from 'vfile'
import { evaluate } from '@orgajs/orgx'
import * as runtime from 'react/jsx-runtime'
import { map } from 'unist-util-map'
import { JSEditor, OrgEditor } from './_components'
import initContent from './_snippets/hey.org?raw'

const tabs = ['Rendered', 'Oast (Org-mode)', 'Hast (HTML)', 'JSX Code']

export default function Playground() {
	const [content, setContent] = useState<string>(initContent)
	const [parsed, setParsed] = useState({
		oast: '',
		hast: '',
		jsx: '',
		preview: <div>rendering...</div>
	})
	const [activeTab, setActiveTab] = useState(0)

	const showPosition = false

	const code = useMemo(() => {
		switch (activeTab) {
			case 1:
				return parsed.oast
			case 2:
				return parsed.hast
			case 3:
				return parsed.jsx
			default:
				return ''
		}
	}, [activeTab, parsed])

	useEffect(() => {
		const url = new URL(window.location.href)
		const text = url.searchParams.get('text')
		if (text) {
			setContent(decodeURIComponent(text))
		}
	}, [])

	useEffect(() => {
		render(content).then(setParsed)
	}, [content])

	return (
		<div className="flex h-full w-full">
			{/* Editor panel */}
			<div className="h-full w-1/2 border-1 border-gray-600">
				<OrgEditor
					className="h-full"
					content={content}
					onChange={(state) => setContent(state.doc.toString())}
				/>
			</div>

			{/* Preview panel */}
			<div className="h-full w-1/2 flex flex-col">
				<ul className="tabs tabs-border">
					{tabs.map((tab, i) => (
						<input
							key={`tab-${i}`}
							type="radio"
							name="tabs"
							className="tab"
							aria-label={tab}
							onChange={() => setActiveTab(i)}
							checked={activeTab === i}
						/>
					))}
				</ul>
				<div className="h-full overflow-auto">
					<div className={`p-4 ${activeTab === 0 ? 'block' : 'hidden'}`}>
						{parsed.preview}
					</div>
					<div className={activeTab === 0 ? 'hidden' : 'block'}>
						<JSEditor>{code}</JSEditor>
					</div>
				</div>
				<div className="menu lg:menu-horizontal rounded-box w-full justify-end">
					<li>
						<button onClick={generateLink}>
							<svg
								xmlns="http://www.w3.org/2000/svg"
								height="24px"
								viewBox="0 -960 960 960"
								width="24px"
								fill="#e3e3e3"
							>
								<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" />
							</svg>
							Generate Link
						</button>
					</li>
				</div>
			</div>
		</div>
	)

	// Generate shareable link
	function generateLink() {
		const url = new URL(window.location.href)
		const encoded = encodeURIComponent(content)
		url.searchParams.set('text', encoded)
		navigator.clipboard.writeText(url.toString())
		// This assumes window.echo is available globally
		if (typeof window.echo === 'function') {
			window.echo('Link copied to clipboard')
		} else {
			console.log('Link copied to clipboard')
		}
	}

	async function render(content: string) {
		const file = new VFile(content)
		let oast = ''
		let hast = ''
		let jsx = ''

		const { default: Content } = await evaluate(file, {
			...runtime,
			rehypePlugins: [capture((v) => (hast = toJSON(v)))],
			reorgPlugins: [capture((v) => (oast = toJSON(v)))]
		})

		jsx = String(file)
		return {
			oast,
			hast,
			jsx,
			preview: (
				<div className="prose h-full overflow-auto">
					<Content />
				</div>
			)
		}
	}

	function capture(fn: (v: any) => void) {
		return function () {
			return function (tree) {
				fn(tree)
			}
		}
	}

	function toJSON(tree: any) {
		return JSON.stringify(
			map(tree, (node) => {
				const { position, ...rest } = node
				if (!showPosition) {
					return rest
				}
				return node
			}),
			null,
			2
		)
	}
}


================================================
FILE: docs/style.css
================================================
@import 'tailwindcss';
@plugin "@tailwindcss/typography";
@plugin "daisyui" {
	themes: nord --default, dark --prefersdark;
}

#root {
	@apply flex flex-col h-screen;
}

.cm-editor {
	outline: none;
}

.cm-editor.cm-focused {
	outline: none;
}

/* GitHub-like code block styling for rehype-pretty-code output */
.prose pre[data-theme] {
	background-color: #0d1117;
	border: 1px solid #30363d;
	border-radius: 8px;
	color: #c9d1d9;
	margin: 1.25rem 0;
	overflow-x: auto;
	padding: 1rem 0;
}

.prose pre[data-theme] code {
	background: transparent;
	color: inherit;
	counter-reset: line;
	display: grid;
	font-size: 0.875rem;
	line-height: 1.5;
	padding: 0;
}

.prose pre[data-theme] code .line {
	display: inline-block;
	min-height: 1.5rem;
	padding: 0 1rem;
	width: 100%;
}

.prose pre[data-theme] code .line--highlighted {
	background-color: rgba(56, 139, 253, 0.15);
}

.prose pre[data-theme] code .word--highlighted {
	background-color: rgba(56, 139, 253, 0.3);
	border: 1px solid rgba(56, 139, 253, 0.45);
	border-radius: 4px;
	padding: 0.1rem 0.25rem;
}

.prose code:not(pre code) {
	background-color: rgba(175, 184, 193, 0.2);
	border-radius: 6px;
	font-size: 0.875em;
	padding: 0.15rem 0.35rem;
}


================================================
FILE: docs/tsconfig.json
================================================
{
	"compilerOptions": {
		"jsx": "react-jsx",
		"lib": ["esnext", "DOM"],
		"moduleResolution": "node",
		"allowJs": true,
		"esModuleInterop": true,
		"allowSyntheticDefaultImports": true,
		"allowImportingTsExtensions": true,
		"skipLibCheck": true,
		"isolatedModules": true,
		"target": "esnext",
		"module": "esnext"
	}
}


================================================
FILE: examples/README.org
================================================
#+TITLE: Examples

* Setup

Before using any of the examples, you have to build the monorepo.

#+begin_src shell
git clone git@github.com:orgapp/orgajs.git
cd orgajs
yarn
yarn build
#+end_src

Now you can =cd= into specific example project directory and start hacking.

* Which Example To Follow

You should choose...

- [[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.
- [[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.
- [[file:gatsby-posts-core/][gatsby-posts-core]] :: if you want to customize gatsby-posts to the bone.
- [[file:next/][next]] :: if you use next.js
- [[file:webpack/][webpack]] :: if you want total control, build from scratch, use webpack

* A Little Bit Of Details About Gatsby Examples

If you are trying to choose a gatsby example, here are some technical details that you should know.
There are currently two styles of rendering org-mode content in gatsby.

** [[file:~/Code/orgajs/packages/gatsby-transformer-orga/][gatsby-transformer-orga]] (original)
This 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.
- [[file:gatsby-posts/][gatsby-posts]]
- [[file:gatsby-posts-core/][gatsby-posts-core]]

** [[file:~/Code/orgajs/packages/gatsby-plugin-orga/][gatsby-plugin-orga]] (new)
This 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...).

Here is a list of my favorite features:
- render react components in org-mode file, just like mdx
- per file custom layout
- passing arbitrary data to layout component via =#+key: value=
- replace default elements with your own react components

Basically 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).

** The Themes
There 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.

- 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.
- 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]].
- 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)



================================================
FILE: examples/build/index.org
================================================
#+title: Build with Orga

* Hi

You can build a static website with *just* org files.

Here's [[file:more.org][another page]].

#+begin_src sh
orga-build
#+end_src


================================================
FILE: examples/build/more.org
================================================
#+title: Another Page

This is another page.


================================================
FILE: examples/build/package.json
================================================
{
	"name": "@orgajs/example-build",
	"private": true,
	"type": "module",
	"scripts": {
		"dev": "orga-build dev",
		"build": "orga-build"
	},
	"devDependencies": {
		"orga-build": "workspace:^"
	}
}


================================================
FILE: examples/build/test-content.tsx
================================================
import { getPages, getPage } from 'orga-build:content'

export default function TestContent() {
  // Test 1: Get all pages
  const allPages = getPages()

  // Test 2: Get a specific page
  const indexPage = getPage('index')

  // Test 3: Filter pages
  const filtered = getPages('', (entry) => entry.ext === 'org')

  return (
    <div>
      <h1>Content API Test</h1>

      <h2>All Pages ({allPages.length})</h2>
      <ul>
        {allPages.map((page) => (
          <li key={page.id}>
            <strong>{page.id}</strong> - {page.slug} (path: {page.path || '(root)'})
            {page.data && Object.keys(page.data).length > 0 && (
              <pre>{JSON.stringify(page.data, null, 2)}</pre>
            )}
          </li>
        ))}
      </ul>

      <h2>Index Page</h2>
      {indexPage ? (
        <div>
          <p>Found: {indexPage.slug}</p>
          <pre>{JSON.stringify(indexPage, null, 2)}</pre>
        </div>
      ) : (
        <p>Not found</p>
      )}

      <h2>Filtered Pages (org only)</h2>
      <ul>
        {filtered.map((page) => (
          <li key={page.id}>{page.slug} - {page.ext}</li>
        ))}
      </ul>
    </div>
  )
}


================================================
FILE: examples/editor/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?


================================================
FILE: examples/editor/CHANGELOG.md
================================================
# @orgajs/example-editor

## 0.3.0

### Minor Changes

- a53cfea: all about the editor

  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.

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/editor@1.4.0

## 0.2.4

### Patch Changes

- Updated dependencies [60ad38f]
  - @orgajs/editor@1.3.1

## 0.2.3

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/editor@1.3.0

## 0.2.2

### Patch Changes

- Updated dependencies [2f7b62d]
  - @orgajs/editor@1.2.2

## 0.2.1

### Patch Changes

- e3ef3a5: build website with orga-build
- Updated dependencies [e3ef3a5]
  - @orgajs/editor@1.2.1

## 0.2.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- Updated dependencies [d8861c2]
  - @orgajs/editor@1.2.0

## 0.1.7

### Patch Changes

- 0f825de5: update editor dependencies
- Updated dependencies [0f825de5]
  - @orgajs/editor@1.1.7

## 0.1.6

### Patch Changes

- Updated dependencies [e9564ff5]
  - @orgajs/editor@1.1.6

## 0.1.5

### Patch Changes

- Updated dependencies [0ffa3415]
  - @orgajs/editor@1.1.5

## 0.1.4

### Patch Changes

- dc3a9db2: cleanup editor
- Updated dependencies [dc3a9db2]
  - @orgajs/editor@1.1.4

## 0.1.3

### Patch Changes

- Updated dependencies [7cfff79a]
  - @orgajs/editor@1.1.3

## 0.1.2

### Patch Changes

- Updated dependencies [ea032b35]
  - @orgajs/editor@1.1.2

## 0.1.1

### Patch Changes

- ac322714: implement editor
- Updated dependencies [ac322714]
  - @orgajs/editor@1.1.1

## 0.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - @orgajs/editor@1.1.0


================================================
FILE: examples/editor/content.org
================================================
#+title:  Example Org File
#+date:   2023-11-24
#+todo: TODO NEXT | DONE

Org uses single characters to markup *bold* /italic/ _underline_ +strike through+ ~code~ and =verbatim=. Links also use minimal
markup in [[https://orgmode.org][Org]].

* NEXT Blocks

#+begin_src js
console.log('hello')
#+end_src

* Lists

- one
- two
- three


* Tasks

** DONE buy milk
** TODO drink it


================================================
FILE: examples/editor/index.html
================================================
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + TS</title>
  </head>
  <body>
    <div id="container">
      <h1>Org Editor</h1>
      <div id="editor"></div>
    </div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>


================================================
FILE: examples/editor/package.json
================================================
{
	"name": "@orgajs/example-editor",
	"private": true,
	"version": "0.3.0",
	"type": "module",
	"scripts": {
		"dev": "vite --port 3000 --force",
		"build": "tsc && vite build",
		"preview": "vite preview"
	},
	"devDependencies": {
		"@codemirror/view": "^6.36.2",
		"typescript": "^5.9.2",
		"vite": "^6.0.11"
	},
	"dependencies": {
		"@orgajs/editor": "workspace:^",
		"cm6-theme-nord": "^0.2.0"
	}
}


================================================
FILE: examples/editor/src/main.ts
================================================
import { makeEditor } from '@orgajs/editor'
import content from '../content.org?raw'
import './style.css'

const target = document.querySelector('#editor')

if (target === null) {
	throw new Error('No target element found')
}
makeEditor({ target, content, extensions: [] })


================================================
FILE: examples/editor/src/style.css
================================================
body {
	background-color: #e7e6e5;
}

#editor {
	width: 720px;
	height: 800px;
	overflow: auto;
	border: 1px solid #ccc;
	background-color: #fff;
}


================================================
FILE: examples/editor/tsconfig.json
================================================
{
  "compilerOptions": {
    "target": "ES2020",
    "useDefineForClassFields": true,
    "module": "ESNext",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "skipLibCheck": true,

    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}


================================================
FILE: examples/getting-started/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

================================================
FILE: examples/getting-started/CHANGELOG.md
================================================
# Change Log

## 4.2.12

### Patch Changes

- @orgajs/reorg-rehype@4.3.11

## 4.2.11

### Patch Changes

- @orgajs/reorg-rehype@4.3.10

## 4.2.10

### Patch Changes

- Updated dependencies [bd2365a]
  - @orgajs/reorg@4.3.3
  - @orgajs/reorg-rehype@4.3.9

## 4.2.9

### Patch Changes

- @orgajs/reorg-rehype@4.3.8

## 4.2.8

### Patch Changes

- @orgajs/reorg-rehype@4.3.7

## 4.2.7

### Patch Changes

- @orgajs/reorg-rehype@4.3.6

## 4.2.6

### Patch Changes

- @orgajs/reorg-rehype@4.3.5

## 4.2.5

### Patch Changes

- @orgajs/reorg-rehype@4.3.4

## 4.2.4

### Patch Changes

- @orgajs/reorg@4.3.2
- @orgajs/reorg-rehype@4.3.3

## 4.2.3

### Patch Changes

- @orgajs/reorg-rehype@4.3.2
- @orgajs/reorg@4.3.1

## 4.2.2

### Patch Changes

- @orgajs/reorg-rehype@4.3.1

## 4.2.1

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/reorg-rehype@4.3.0
  - @orgajs/reorg@4.3.0

## 4.2.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- Updated dependencies [d8861c2]
  - @orgajs/reorg-rehype@4.2.0
  - @orgajs/reorg@4.2.0

## 4.1.3

### Patch Changes

- @orgajs/reorg-rehype@4.1.3

## 4.1.2

### Patch Changes

- @orgajs/reorg-rehype@4.1.2
- @orgajs/reorg@4.1.2

## 4.1.1

### Patch Changes

- @orgajs/reorg-rehype@4.1.1
- @orgajs/reorg@4.1.1

## 4.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - @orgajs/reorg-rehype@4.1.0
  - @orgajs/reorg@4.1.0

## 4.0.0

### Major Changes

- 176a3b5d: # Migrate most of the ecosystem to ESM

  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.

  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.

  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.

  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!

### Patch Changes

- Updated dependencies [176a3b5d]
  - @orgajs/reorg-rehype@4.0.0
  - @orgajs/reorg@4.0.0

## 3.1.8

### Patch Changes

- Updated dependencies [eeccc870]
  - @orgajs/reorg-rehype@3.0.10
  - @orgajs/reorg@3.1.7

## 3.1.7

### Patch Changes

- @orgajs/reorg-rehype@3.0.9
- @orgajs/reorg@3.1.6

## 3.1.6

### Patch Changes

- 4bde5155: tidy up dependencies
  - @orgajs/reorg-rehype@3.0.8
  - @orgajs/reorg@3.1.5

## 3.1.5

### Patch Changes

- @orgajs/reorg-rehype@3.0.7
- @orgajs/reorg@3.1.4

## 3.1.4

### Patch Changes

- @orgajs/reorg-rehype@3.0.6
- @orgajs/reorg@3.1.3

## 3.1.3

### Patch Changes

- @orgajs/reorg-rehype@3.0.5
- @orgajs/reorg@3.1.2

## 3.1.2

### Patch Changes

- @orgajs/reorg-rehype@3.0.4
- @orgajs/reorg@3.1.1

## 3.1.1

### Patch Changes

- Updated dependencies [7f209ff5]
  - @orgajs/reorg-rehype@3.0.3

## 3.1.0

### Minor Changes

- eeea0c54: introduce new token: empty line

### Patch Changes

- Updated dependencies [eeea0c54]
  - @orgajs/reorg@3.1.0
  - @orgajs/reorg-rehype@3.0.2

## 3.0.1

### Patch Changes

- Updated dependencies [6ed76057]
- Updated dependencies [759e6149]
  - @orgajs/reorg@3.0.1
  - @orgajs/reorg-rehype@3.0.1

## 3.0.0

### Major Changes

- 8b02d10: # Features

  - more powerful and flexible lexer and parser
  - webpack support
  - `jsx` support
  - better code block rendering
  - better image processing in gatsby
  - updated examples
  - tons of bug fixes
  - brand new `gatsby-plugin-orga`

### Patch Changes

- Updated dependencies [8b02d10]
  - @orgajs/reorg@3.0.0
  - @orgajs/reorg-rehype@3.0.0

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)

**Note:** Version bump only for package @orgajs/getting-started

# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)

### Bug Fixes

- lock unified & @types/unist version ([dc72217](https://github.com/orgapp/orgajs/commit/dc72217f0cfcd778436d704021116c8479f8ee1e))

## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)

**Note:** Version bump only for package example

## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)

**Note:** Version bump only for package example

## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)

**Note:** Version bump only for package example


================================================
FILE: examples/getting-started/README.org
================================================
This is an example project, with [[file:index.js][10 lines of code]].

#+BEGIN_SRC sh
npm install
npm run build
#+END_SRC

Take a look at =readme.html= file.


================================================
FILE: examples/getting-started/index.js
================================================
import { reorg } from '@orgajs/reorg'
import { stream } from 'unified-stream'
import mutate from '@orgajs/reorg-rehype'
import html from 'rehype-stringify'

const processor = reorg().use(mutate).use(html)

process.stdin.pipe(stream(processor)).pipe(process.stdout)


================================================
FILE: examples/getting-started/package.json
================================================
{
  "private": true,
  "name": "@orgajs/getting-started",
  "version": "4.2.12",
  "description": "",
  "main": "index.js",
  "type": "module",
  "scripts": {
    "build": "node index.js < README.org > readme.html"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@orgajs/reorg": "workspace:*",
    "@orgajs/reorg-rehype": "workspace:*",
    "rehype-stringify": "^10.0.1",
    "unified": "11.0.5",
    "unified-stream": "^3.0.0"
  }
}


================================================
FILE: examples/webpack/.babelrc
================================================
{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}


================================================
FILE: examples/webpack/CHANGELOG.md
================================================
# Change Log

## 3.2.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

## 3.1.1

### Patch Changes

- e3ef3a5: build website with orga-build

## 3.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

## 3.0.1

### Patch Changes

- 4bde5155: tidy up dependencies

## 3.0.0

### Major Changes

- 8b02d10: # Features

  - more powerful and flexible lexer and parser
  - webpack support
  - `jsx` support
  - better code block rendering
  - better image processing in gatsby
  - updated examples
  - tons of bug fixes
  - brand new `gatsby-plugin-orga`

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)

**Note:** Version bump only for package @orgajs/example-webpack

# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)

### Bug Fixes

- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))

## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)

**Note:** Version bump only for package @orgajs/example-webpack

## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)

**Note:** Version bump only for package @orgajs/example-webpack

## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)

**Note:** Version bump only for package @orgajs/example-webpack


================================================
FILE: examples/webpack/README.org
================================================
#+title: Webpack + Orga

This is a minimal webpack website that recognizes org-mode files as pages.

-----

* Running locally

See the [[file:../README.org][setup instructions]] before using this project.

#+begin_src shell
yarn start
#+end_src



================================================
FILE: examples/webpack/package.json
================================================
{
	"name": "@orgajs/example-webpack",
	"private": true,
	"version": "3.2.0",
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"scripts": {
		"build": "webpack",
		"webpack": "webpack",
		"start": "webpack serve"
	},
	"devDependencies": {
		"@babel/core": "^7.22.11",
		"@babel/preset-env": "^7.22.14",
		"@babel/preset-react": "^7.22.5",
		"@orgajs/loader": "workspace:^",
		"babel-loader": "^9.1.3",
		"react": "^19.0.0",
		"react-dom": "^19.0.0",
		"webpack": "^5.104.1",
		"webpack-cli": "^5.1.4",
		"webpack-dev-server": "^4.15.1"
	}
}


================================================
FILE: examples/webpack/public/index.html
================================================
<!DOCTYPE html>
<meta charset="utf-8" />
<div id="root"></div>
<script src="main.js"></script>


================================================
FILE: examples/webpack/src/box.js
================================================
import React from 'react'

export default ({ children }) => (
  <div
    style={{
      padding: 20,
      backgroundColor: 'tomato',
      color: 'white',
    }}
  >
    {children}
  </div>
)


================================================
FILE: examples/webpack/src/hello.org
================================================
#+jsx: import Box from './box'

* Hello

#+begin_export jsx
export default ({ children }) =>
  <div style={{ padding: 20 }}>
    <h1 style={{ color: 'blue' }}>Orga + Webpack</h1>
    {children}
  </div>
#+end_export

This is *org-mode* with /JSX/!

-----

#+begin_export jsx
<Box>the tomato box</Box>
#+end_export



================================================
FILE: examples/webpack/src/index.js
================================================
import React from 'react'
import { createRoot } from 'react-dom/client'
import Hello from './hello.org'

const root = createRoot(document.getElementById('root'))
root.render(<Hello />)


================================================
FILE: examples/webpack/webpack.config.mjs
================================================
export default {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader',
        exclude: /node_modules/,
      },
      {
        test: /\.org$/,
        use: ['@orgajs/loader'],
      },
    ],
  },
}


================================================
FILE: orga.config.js
================================================
import tailwindcss from '@tailwindcss/vite'
import rehypePrettyCode from 'rehype-pretty-code'

export const containerClass = 'prose p-4'
export const styles = ['docs/style.css']
export const vitePlugins = [tailwindcss()]
export const rehypePlugins = [[rehypePrettyCode, { theme: 'github-dark' }]]
export const root = 'docs'
export const exclude = ['config.d.ts']


================================================
FILE: package.json
================================================
{
	"name": "orgajs",
	"private": true,
	"type": "module",
	"devDependencies": {
		"@biomejs/biome": "^2.4.4",
		"@changesets/cli": "^2.29.8",
		"@codemirror/lang-javascript": "^6.2.3",
		"@codemirror/language": "^6.10.8",
		"@codemirror/theme-one-dark": "^6.1.2",
		"@codemirror/view": "^6.36.2",
		"@lezer/highlight": "^1.2.1",
		"@orgajs/orgx": "workspace:^",
		"@orgajs/react-cm": "workspace:^",
		"@orgajs/react-editor": "workspace:^",
		"@tailwindcss/typography": "^0.5.9",
		"@tailwindcss/vite": "^4.1.4",
		"@types/node": "^25.3.2",
		"@types/react": "^19.1.2",
		"@types/react-dom": "^19.1.2",
		"daisyui": "^5.0.28",
		"orga-build": "workspace:^",
		"react": "^19.0.0",
		"react-dom": "^19.0.0",
		"rehype-pretty-code": "^0.14.1",
		"shiki": "^3.23.0",
		"tailwindcss": "^4.0.3",
		"type-coverage": "^2.29.7",
		"typescript": "^5.9.2",
		"unist-util-map": "4.0.0",
		"vfile": "^6.0.3"
	},
	"scripts": {
		"build": "pnpm -r --filter './packages/*' --if-present run build && tsc --build --clean && tsc --build && type-coverage",
		"clean": "tsc --build --clean",
		"lint": "biome lint .",
		"lint:fix": "biome lint . --write",
		"test": "pnpm run check && pnpm -r --filter './packages/*' --if-present run test",
		"format": "biome format --write .",
		"check": "biome check .",
		"check:fix": "biome check . --write",
		"changeset": "changeset",
		"ci:version": "changeset version",
		"ci:publish": "pnpm build && changeset publish",
		"docs": "orga-build",
		"docs:dev": "orga-build dev"
	}
}


================================================
FILE: packages/astro/README.org
================================================
* @orgajs/astro (Moved)

The Astro integration package has moved to a dedicated repository:

[[https://github.com/orgapp/orga-astro][github.com/orgapp/orga-astro]]

Please use that repository for source code, issues, and releases.


================================================
FILE: packages/codemirror-lang/CHANGELOG.md
================================================
# @orgajs/cm-lang

## 1.3.0

### Minor Changes

- a53cfea: all about the editor

  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.

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/lezer@1.4.0

## 1.2.1

### Patch Changes

- @orgajs/lezer@1.3.1

## 1.2.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/lezer@1.3.0

## 1.1.6

### Patch Changes

- e3ef3a5: build website with orga-build
- Updated dependencies [e3ef3a5]
  - @orgajs/lezer@1.2.1

## 1.1.5

### Patch Changes

- Updated dependencies [d8861c2]
  - @orgajs/lezer@1.2.0

## 1.1.4

### Patch Changes

- 0f825de5: update editor dependencies
- Updated dependencies [0f825de5]
  - @orgajs/lezer@1.1.4

## 1.1.3

### Patch Changes

- @orgajs/lezer@1.1.3

## 1.1.2

### Patch Changes

- Updated dependencies [ea032b35]
  - @orgajs/lezer@1.1.2

## 1.1.1

### Patch Changes

- ac322714: implement editor
- Updated dependencies [ac322714]
  - @orgajs/lezer@1.1.1

## 1.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - @orgajs/lezer@1.1.0


================================================
FILE: packages/codemirror-lang/index.js
================================================
/** @typedef {import('@lezer/common').SyntaxNode} SyntaxNode */

import {
	defineLanguageFacet,
	foldNodeProp,
	foldService,
	Language,
	LanguageSupport,
	syntaxTree
} from '@codemirror/language'
import { parser as baseParser } from '@orgajs/lezer'

const data = defineLanguageFacet({})

// --- folding ---

/**
 * @param {SyntaxNode} node
 */
function getHeadlineLevel(node) {
	if (node.type.name !== 'headline') return
	const stars = node.getChild('stars')
	if (stars) {
		const level = stars.to - stars.from
		return level
	}
}

/**
 * @param {SyntaxNode} headerNode
 */
function findSectionEnd(headerNode) {
	const level = getHeadlineLevel(headerNode)
	if (level === undefined) throw new Error('Not a headline')
	let last = headerNode
	for (;;) {
		const next = last.nextSibling
		if (!next) {
			break
		}

		const l = getHeadlineLevel(next)
		if (l !== undefined && l <= level) {
			return next.from - 1 // Escape the newline. TODO: is this safe?
		}

		last = next
	}

	return last.to
}

const headerIndent = foldService.of((state, start, end) => {
	for (
		let /** @type {SyntaxNode | null} */ node = syntaxTree(state).resolveInner(
				end,
				-1
			);
		node;
		node = node.parent
	) {
		if (node.from < start) {
			break
		}

		if (!node.type.name.startsWith('headline')) {
			continue
		}

		const upto = findSectionEnd(node)
		if (upto > end) {
			return { from: end, to: upto }
		}
	}

	return null
})

const parser = baseParser.configure({
	props: [
		foldNodeProp.add((type) => {
			if (type.name !== 'headline') {
				return undefined
			}

			return (tree, state) => ({
				from: state.doc.lineAt(tree.from).to,
				to: state.doc.lineAt(tree.from).to
			})
		})
	]
})

/**
 * @param {any} parser
 */
function mkLang(parser) {
	return new Language(data, parser, [headerIndent], 'org')
}

export function org() {
	const lang = mkLang(parser)
	return new LanguageSupport(lang)
}

export { tags } from '@orgajs/lezer'


================================================
FILE: packages/codemirror-lang/package.json
================================================
{
	"name": "@orgajs/cm-lang",
	"version": "1.3.0",
	"description": "codemirror language: org",
	"type": "module",
	"files": [
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"scripts": {},
	"keywords": [
		"org",
		"org-mode",
		"orgajs",
		"orga",
		"codemirror"
	],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"repository": {
		"type": "git",
		"url": "https://github.com:orgapp/orgajs.git",
		"directory": "packages/cm-lang"
	},
	"dependencies": {
		"@codemirror/language": "^6.10.8",
		"@orgajs/lezer": "workspace:^"
	},
	"devDependencies": {
		"@codemirror/state": "^6.5.2",
		"@lezer/common": "^1.1.1"
	}
}


================================================
FILE: packages/codemirror-lang/tsconfig.json
================================================
{
	"extends": "../../tsconfig.json"
}


================================================
FILE: packages/editor/CHANGELOG.md
================================================
# @orgajs/editor

## 1.4.1

### Patch Changes

- bd2365a: fix types and linting

## 1.4.0

### Minor Changes

- a53cfea: all about the editor

  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.

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/cm-lang@1.3.0

## 1.3.1

### Patch Changes

- 60ad38f: migrate orga-build to be based on vite
  - @orgajs/cm-lang@1.2.1

## 1.3.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/cm-lang@1.2.0

## 1.2.2

### Patch Changes

- 2f7b62d: fix package.json file

## 1.2.1

### Patch Changes

- e3ef3a5: build website with orga-build
- Updated dependencies [e3ef3a5]
  - @orgajs/cm-lang@1.1.6

## 1.2.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- @orgajs/cm-lang@1.1.5

## 1.1.7

### Patch Changes

- 0f825de5: update editor dependencies
- Updated dependencies [0f825de5]
  - @orgajs/cm-lang@1.1.4

## 1.1.6

### Patch Changes

- e9564ff5: remove opinionated extensions from default editor

## 1.1.5

### Patch Changes

- 0ffa3415: cleanup theme

## 1.1.4

### Patch Changes

- dc3a9db2: cleanup editor

## 1.1.3

### Patch Changes

- 7cfff79a: headline elements (stars, todo keywords and priority) end after the whitespaces
  - @orgajs/cm-lang@1.1.3

## 1.1.2

### Patch Changes

- ea032b35: bug fix, link generating button
  - @orgajs/cm-lang@1.1.2

## 1.1.1

### Patch Changes

- ac322714: implement editor
- Updated dependencies [ac322714]
  - @orgajs/cm-lang@1.1.1

## 1.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - @orgajs/cm-lang@1.1.0


================================================
FILE: packages/editor/README.org
================================================
* TODO Quick Start

* Customization
** TODO Write a Theme
** TODO key bindings


================================================
FILE: packages/editor/index.js
================================================
/**
 * @typedef {import('./lib/editor.js').Config} EditorConfig
 */

export { tags } from '@orgajs/cm-lang'
export { makeEditor } from './lib/editor.js'
export { settings } from './lib/settings.js'
export { setup } from './lib/setup.js'


================================================
FILE: packages/editor/lib/actions/fold.js
================================================
/**
 * @file Actions to shift sections.
 *
 * @typedef {import('@codemirror/view').EditorView} EditorView
 * @typedef {import('@lezer/common').Tree} Tree
 * @typedef {import('@lezer/common').SyntaxNode} Node
 * @typedef {import('@codemirror/state').ChangeSpec} ChangeSpec
 */
import {
	foldAll,
	foldCode,
	foldState,
	unfoldAll,
	unfoldCode
} from '@codemirror/language'
import { EditorState } from '@codemirror/state'
import { selectedLines } from './utils'

/**
 * @param {EditorView} view
 */
export function toggleFold(view) {
	const { state } = view

	const lines = selectedLines(view)
	for (const line of lines) {
		const folded = findFold(state, line.from, line.to)
		if (folded) {
			unfoldCode(view)
		} else {
			foldCode(view)
		}
	}
	return true
}

/**
 * @param {EditorState} state
 * @param {number} from
 * @param {number} to
 */
function findFold(state, from, to) {
	/** @type {{from:number, to:number} | null} */ let found = null
	state.field(foldState, false)?.between(from, to, (from, to) => {
		if (!found || found.from > from) found = { from, to }
	})
	return found
}

/**
 * @param {EditorView} view
 */
export function toggleFoldAll(view) {
	const state = view.state
	const folds = state.field(foldState, false)
	if (folds?.size) {
		unfoldAll(view)
	} else {
		foldAll(view)
	}
	return true
}


================================================
FILE: packages/editor/lib/actions/shift.js
================================================
/**
 * @file Actions to shift sections.
 *
 * @typedef {import('@codemirror/view').EditorView} EditorView
 * @typedef {import('@lezer/common').Tree} Tree
 * @typedef {import('@lezer/common').SyntaxNode} Node
 * @typedef {import('@codemirror/state').ChangeSpec} ChangeSpec
 */

import { syntaxTree } from '@codemirror/language'

/**
 * Shift the headline.
 * @param {number} delta - The number of spaces to shift. Positive values shift right, negative values shift left.
 * @param {boolean} [recursive=false] - Whether to shift subsections recursively.
 */
export function shift(delta, recursive = false) {
	/**
	 * @param {EditorView} view
	 */
	return function (view) {
		const { state } = view
		const tree = syntaxTree(state)
		const pos = state.selection.main.head
		// the selection must be in a headline
		const headline = getHeadline(tree, pos)
		if (!headline) return false
		/** @type {ChangeSpec[]} */
		const changes = []
		let cancelled = false
		if (recursive === false) {
			const stars = headline.getChild('stars')
			if (!stars || stars.to - stars.from + delta < 1) {
				return true
			}
			const change = _shift(stars, delta)
			if (change) {
				changes.push(change)
			}
		} else {
			const cursor = headline.cursor()
			const change = _shift(headline, delta)
			if (change) {
				changes.push(change)
			} else {
				return true
			}
			while (cursor.nextSibling()) {
				if (cursor.type.name === 'headline') {
					const change = _shift(cursor.node, delta)
					if (change) {
						changes.push(change)
					} else {
						cancelled = true
						break
					}
				}
			}
		}

		if (!cancelled && changes.length > 0) {
			view.dispatch({ changes })
		}
		return true
	}
}

/**
 * shift the stars
 * @param {Node|null|undefined} node
 * @param {number} delta
 * @returns {ChangeSpec | undefined}
 */
function _shift(node, delta) {
	if (!node) return undefined
	if (node.type.name === 'headline')
		return _shift(node.getChild('stars'), delta)
	if (node.type.name !== 'stars') return

	if (delta > 0) {
		return {
			from: node.from,
			insert: '*'.repeat(delta)
		}
	}
	if (delta < 0 && node.to - node.from + delta >= 1) {
		return {
			from: node.from,
			to: node.from - delta,
			insert: ''
		}
	}
}

/**
 * @param {Tree} tree
 * @param {number} pos
 */
function getHeadline(tree, pos) {
	/** @type {import('@lezer/common').NodeIterator | null} */
	let iter = tree.resolveStack(pos)
	while (iter) {
		const name = iter.node.type.name
		if (name.startsWith('headline')) return iter.node
		iter = iter.next
	}
	return null
}


================================================
FILE: packages/editor/lib/actions/todo.js
================================================
/**
 * @typedef {import('@codemirror/view').EditorView} EditorView
 */

import { syntaxTree } from '@codemirror/language'
import { parseTodoKeywords } from 'orga/todo'
import { settings } from '../settings'
import { getTodo } from './utils'

/**
 * @param {EditorView} view
 */
export function toggleTodo(view) {
	const { state } = view
	const pos = state.selection.main.head
	const tree = syntaxTree(state)

	const _todo = getTodo(tree, pos)
	if (!_todo) return false
	const content = state.sliceDoc(_todo.from, _todo.to)
	const _settings = state.field(settings)
	const t = parseTodoKeywords(_settings.todo)
	const next = t.next(content)
	const change = {
		from: _todo.from,
		to: _todo.to,
		...(next !== undefined && { insert: next })
	}
	view.dispatch({ changes: change })
	console.log({ todo: _todo, content, next })
	return true
}


================================================
FILE: packages/editor/lib/actions/utils.js
================================================
/**
 * @typedef {import('@codemirror/view').EditorView} EditorView
 * @typedef {import('@lezer/common').Tree} Tree
 */

/**
 * @param {EditorView} view
 */
export function selectedLines(view) {
	/** @type {Array<import('@codemirror/view').BlockInfo>} */
	const lines = []
	for (const { head } of view.state.selection.ranges) {
		if (lines.some((l) => l.from <= head && l.to >= head)) continue
		lines.push(view.lineBlockAt(head))
	}
	return lines
}

/**
 * @param {Tree} tree
 * @param {number} pos
 */
export function getTodo(tree, pos) {
	const headline = getNode(tree, pos, 'headline')
	return headline?.getChild('todo')
}

/**
 * @param {Tree} tree
 * @param {number} pos
 * @param {string} type
 */
export function getNode(tree, pos, type) {
	/** @type {import('@lezer/common').NodeIterator | null} */
	let iter = tree.resolveStack(pos)
	while (iter) {
		const name = iter.node.type.name
		if (name === type) return iter.node
		iter = iter.next
	}
	return null
}


================================================
FILE: packages/editor/lib/editor.js
================================================
/**
 * @callback OnChange
 * @param {EditorState} state
 */

/**
 * @typedef Config
 * @property {Element} target
 * @property {string} [content='']
 * @property {import('@codemirror/state').Extension} [extensions=[]]
 * @property {boolean} [dark=false]
 * @property {OnChange} [onChange=() => {}]
 */
import { EditorState } from '@codemirror/state'
import { EditorView } from '@codemirror/view'
import { setup } from './setup.js'

/**
 * @param {Config} config
 */
export function makeEditor(config) {
	const { target, content = '', extensions = [], onChange } = config
	const state = EditorState.create({
		doc: content,
		extensions: [setup, extensions]
	})
	const editor = new EditorView({
		state,
		parent: target,
		dispatch: (tr) => {
			editor.update([tr])
			tr.docChanged && onChange && onChange(editor.state)
		}
	})

	return { editor }
}


================================================
FILE: packages/editor/lib/extensions/cleanup.js
================================================
/**
 * @typedef Range
 * @property {number} from
 * @property {number} to
 *
 * @typedef {object} Options
 * @property {boolean} hideStars
 * @property {boolean} hideLinks
 */
import { syntaxTree } from '@codemirror/language'
import { Decoration, ViewPlugin } from '@codemirror/view'
import { parseTodoKeywords } from 'orga/todo'
import { settings } from '../settings'

/**
 * @param {Range} a
 * @param {Range} b
 */
function overlap(a, b) {
	return a.from <= b.to && a.to >= b.from
}

/**
 * @param {Options} options
 */
export function cleanup(options) {
	return ViewPlugin.define(
		(view) => {
			let _data = createDecorations(view, options)
			let _selection = view.state.selection.main

			return {
				get decorations() {
					return _data.decorations
				},
				get selection() {
					return _selection
				},
				update(update) {
					_selection = update.state.selection.main
					if (update.docChanged) {
						_data = createDecorations(update.view, options)
					}
				}
			}
		},
		{
			decorations: (v) => {
				const { decorations, selection } = v
				return decorations.update({
					filter: (_from, _to, deco) => {
						const revealRange = deco.spec.revealRange
						if (revealRange) {
							return !overlap(revealRange, selection)
						}
						return true
					}
				})
			},
			eventHandlers: {
				// cmd+click to open links
				mousedown(e, view) {
					const pos = view.posAtCoords(e)
					if (!pos) return
					if (!e.metaKey) return
					this.decorations.between(pos, pos, (_from, _to, deco) => {
						const { tagName, attributes } = deco.spec
						if (tagName === 'a' && attributes) {
							e.preventDefault()
							// TODO: is it possible to make it a real link?
							// I guess that'd be difficult because it's a fucking editor
							window.open(deco.spec.attributes.href, '_blank')
							return false
						}
					})
				}
			}
		}
	)
}

// TODO: this plugin is getting big, in terms of responsibility, break it down

/**
 * @param {Range | null} reveal
 */
function hide(reveal) {
	return Decoration.replace({
		revealRange: reveal
	})
}

/**
 * @param {boolean} actionable
 */
function todo(actionable) {
	return Decoration.mark({
		attributes: {
			class: 'cm-org-todo',
			'data-actionable': actionable.toString()
		}
	})
}

/**
 * @param {import('@codemirror/view').EditorView} view
 * @param {Options} options
 */
function createDecorations(view, options) {
	const _settings = view.state.field(settings)
	const t = parseTodoKeywords(_settings.todo)
	let decorations = Decoration.none
	/** @type {Range[]} */
	const links = []

	/** @type {Range | null} */
	let headlineRange = null
	/** @type {Range | null} */
	let linkRange = null
	syntaxTree(view.state).iterate({
		enter(node) {
			if (node.name.startsWith('headline')) {
				headlineRange = { from: node.from, to: node.to }
			}

			if (node.name === 'link') {
				linkRange = { from: node.from, to: node.to }
			}

			if (node.name === 'url') {
				if (linkRange === null) return
				// get text of node
				const text = view.state.doc.sliceString(node.from, node.to)
				decorations = decorations.update({
					add: [
						Decoration.mark({
							tagName: 'a',
							attributes: { class: 'cm-link', href: text.slice(1, -1) }
						}).range(linkRange.from, linkRange.to)
					]
				})
			}

			if (options.hideLinks && (node.name === 'url' || node.name === 'mark')) {
				decorations = decorations.update({
					add: [hide(linkRange).range(node.from, node.to)]
				})
			}

			if (options.hideStars && node.name === 'stars') {
				const revealRange = { from: headlineRange?.from, to: headlineRange?.to }
				decorations = decorations.update({
					add: [
						Decoration.replace({
							revealRange
						}).range(node.from, node.to)
					]
				})
			}

			if (node.name === 'todo') {
				const content = view.state.doc.sliceString(node.from, node.to).trim()
				decorations = decorations.update({
					add: [todo(t.actionable(content)).range(node.from, node.to)]
				})
			}

			if (node.name === 'done') {
				decorations = decorations.update({
					add: [todo(false).range(node.from, node.to)]
				})
			}
		},
		leave: (node) => {
			if (node.name.startsWith('headline')) headlineRange = null
			if (node.name === 'link') linkRange = null
		}
	})
	return { decorations, links }
}


================================================
FILE: packages/editor/lib/settings.js
================================================
/**
 * @typedef {import('@codemirror/state').EditorState} EditorState
 *
 * @typedef {Object} TodoKeywordSet
 * @property {string[]} actionables - The keywords that represent actionable states (e.g. "TODO", "NEXT").
 * @property {string[]} done - The keywords that represent completed states (e.g. "DONE", "CANCELLED").
 *
 * @typedef {Object} Settings
 * @property {string} todo - The set of todo keywords used in the document.
 */

import { syntaxTree } from '@codemirror/language'
import { StateField } from '@codemirror/state'

export const settings = StateField.define({
	create(state) {
		return extractSettings(state)
	},
	update(value, tr) {
		if (tr.docChanged) {
			return extractSettings(tr.state)
		}
		return value
	}
})

/**
 * @param {EditorState} state
 * @return {Settings}
 */
function extractSettings(state) {
	const tree = syntaxTree(state)
	/** @type {Settings} */
	const settings = {
		todo: 'TODO DONE'
	}
	tree.iterate({
		enter(node) {
			if (node.name === 'keyword') {
				const content = state.doc.sliceString(node.from, node.to).trim()
				const m = content.match(/^#\+(\w+):(?:[ \t]+(.*))?$/y)
				if (!m) return true
				const [_, key, value] = m
				if (!key || !value) return true

				if (key.toLowerCase() === 'todo') {
					settings.todo = value.trim()
					return true
				}
			}
			return true
		}
	})
	return settings
}


================================================
FILE: packages/editor/lib/setup.js
================================================
import { defaultKeymap } from '@codemirror/commands'
import { bracketMatching, foldGutter } from '@codemirror/language'
import { EditorView, highlightActiveLine, keymap } from '@codemirror/view'
import { org } from '@orgajs/cm-lang'
import { toggleFold, toggleFoldAll } from './actions/fold.js'
import { shift } from './actions/shift.js'
import { toggleTodo } from './actions/todo'
import { cleanup } from './extensions/cleanup.js'
import { settings } from './settings'
import theme from './theme.js'

const keys = [
	{ key: 'Tab', run: toggleFold, shift: toggleFoldAll },
	{
		key: 'Cmd-ArrowLeft',
		run: shift(-1),
		shift: shift(-1, true),
		preventDefault: true
	},
	{
		key: 'Cmd-ArrowRight',
		run: shift(1),
		shift: shift(1, true),
		preventDefault: true
	},
	{
		key: 'Cmd-x',
		run: toggleTodo,
		preventDefault: true
	}
]

export const setup = (() => [
	org(),
	settings,
	theme,
	keymap.of([...keys, ...defaultKeymap]),
	highlightActiveLine(),
	foldGutter({
		openText: '▾',
		closedText: '▸'
	}),
	EditorView.lineWrapping,
	bracketMatching(),
	cleanup({ hideStars: false, hideLinks: true })
])()


================================================
FILE: packages/editor/lib/theme.js
================================================
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
import { EditorView } from '@codemirror/view'
import { tags as t } from '@orgajs/cm-lang'

const theme = EditorView.baseTheme({
	'&': {
		height: '100%'
	},
	'.cm-link': {
		cursor: 'pointer'
	},
	'.cm-org-todo': {
		color: 'white',
		backgroundColor: 'green',
		padding: '0 2px',
		borderRadius: '2px',
		cursor: 'pointer'
	},
	'.cm-org-todo[data-actionable="true"]': {
		backgroundColor: 'red'
	}
})

const baseStyle = HighlightStyle.define([
	{
		tag: [t.heading],
		fontWeight: 'bold',
		textDecoration: 'underline'
	},
	{ tag: [t.keyword, t.strong], fontWeight: 'bold' },
	{ tag: t.emphasis, fontStyle: 'italic' },
	{
		tag: t.monospace,
		borderRadius: '4px',
		padding: '1px 4px',
		fontFamily: "'JetBrains Mono', monospace"
	},
	{ tag: t.strikethrough, textDecoration: 'line-through' },
	{ tag: t.underline, textDecoration: 'underline' }
])

const lightColors = HighlightStyle.define(
	[
		{ tag: t.keyword, color: '#e45649' },
		{ tag: t.comment, color: '#9ca0a4' },
		{ tag: t.processingInstruction, color: '#9ca0a4' },
		{ tag: t.attributeName, color: '#9ca0a4' }
	],
	{ themeType: 'light' }
)

const darkColors = HighlightStyle.define(
	[
		{ tag: t.keyword, color: 'green' },
		{ tag: t.comment, color: 'red' },
		{ tag: t.processingInstruction, color: 'gray' },
		{ tag: t.attributeName, color: 'gray' }
	],
	{ themeType: 'dark' }
)

export default [
	theme,
	syntaxHighlighting(lightColors),
	syntaxHighlighting(darkColors),
	syntaxHighlighting(baseStyle)
]


================================================
FILE: packages/editor/package.json
================================================
{
	"name": "@orgajs/editor",
	"version": "1.4.1",
	"type": "module",
	"files": [
		"lib/",
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"description": "react org-mode editor based on prose-mirror",
	"scripts": {},
	"repository": {
		"type": "git",
		"url": "https://github.com/orgapp/orgajs.git",
		"directory": "packages/editor"
	},
	"keywords": [
		"org-mode",
		"CodeMirror",
		"editor"
	],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"dependencies": {
		"@codemirror/commands": "^6.8.0",
		"@codemirror/language": "^6.10.8",
		"@codemirror/state": "^6.5.2",
		"@codemirror/view": "^6.36.2",
		"@orgajs/cm-lang": "workspace:^"
	},
	"devDependencies": {
		"@lezer/common": "^1.2.3",
		"orga": "workspace:^",
		"vfile": "^6.0.3"
	}
}


================================================
FILE: packages/editor/tsconfig.json
================================================
{
	"extends": "../../tsconfig.json"
}


================================================
FILE: packages/esbuild/CHANGELOG.md
================================================
# @orgajs/esbuild

## 1.1.5

### Patch Changes

- bd2365a: fix types and linting
- Updated dependencies [bd2365a]
  - @orgajs/orgx@2.6.1

## 1.1.4

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/orgx@2.6.0

## 1.1.3

### Patch Changes

- @orgajs/orgx@2.5.2

## 1.1.2

### Patch Changes

- @orgajs/orgx@2.5.1

## 1.1.1

### Patch Changes

- 8451164: move orga-build to esbuild

## 1.1.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/orgx@2.5.0

## 1.0.1

### Patch Changes

- Updated dependencies [e3ef3a5]
  - @orgajs/orgx@2.4.1

## 1.0.0

### Major Changes

- 351f690: introduce @orgajs/node-loader, @orgajs/esbuild, @orgajs/build

  - @orgajs/node-loader : the nodejs loader for org-mode files
  - @orgajs/esbuild : esbuild plugin
  - @orgajs/build : static site generator, a.k.a orga-build

### Patch Changes

- Updated dependencies [351f690]
  - @orgajs/orgx@2.4.0


================================================
FILE: packages/esbuild/index.js
================================================
/**
 * @import { CompileOptions } from '@orgajs/orgx'
 * @import {
      OnLoadResult,
      PluginBuild
 * } from 'esbuild'
 */
import fs from 'node:fs/promises'
import { compile } from '@orgajs/orgx'
import { SourceMapGenerator } from 'source-map'
import { VFile } from 'vfile'

const name = '@orgajs/esbuild'

/**
 * Create Node.js hooks to handle org files.
 *
 * @param {Readonly<CompileOptions> | null | undefined} [options]
 *   Configuration (optional).
 * @returns
 *   Node.js hooks.
 */
function esbuild(options) {
	return {
		name,
		setup
	}

	/**
	 * @param {PluginBuild} build
	 *   Build.
	 * @returns {undefined}
	 *   Nothing.
	 */
	function setup(build) {
		build.onLoad({ filter: /\.org$/ }, onload)
	}

	/**
	 * @param {any} data
	 *   Data.
	 * @returns {Promise<OnLoadResult>}
	 *   Result.
	 */
	async function onload(data) {
		const document = String(
			data.pluginData &&
				data.pluginData.contents !== null &&
				data.pluginData.contents !== undefined
				? data.pluginData.contents
				: await fs.readFile(data.path)
		)

		const file = new VFile({ path: data.path, value: document })
		const code = await compile(file, { ...options, SourceMapGenerator })
		const contents =
			String(code) +
			'\n' +
			'//# sourceMappingURL=data:application/json;base64,' +
			Buffer.from(JSON.stringify(file.map)).toString('base64') +
			'\n'

		return {
			contents
		}
	}
}

export default esbuild


================================================
FILE: packages/esbuild/package.json
================================================
{
	"name": "@orgajs/esbuild",
	"version": "1.1.5",
	"description": "esbuild plugin for orgajs",
	"type": "module",
	"exports": "./index.js",
	"files": [
		"lib/",
		"index.d.ts.map",
		"index.d.ts",
		"index.js"
	],
	"scripts": {},
	"license": "MIT",
	"keywords": [
		"esbuild",
		"jsx",
		"org-mode",
		"react"
	],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"repository": {
		"type": "git",
		"url": "https://github.com/orgapp/orgajs.git",
		"directory": "packages/esbuild"
	},
	"dependencies": {
		"@orgajs/orgx": "workspace:^",
		"source-map": "^0.7.4",
		"vfile": "^6.0.3"
	},
	"devDependencies": {
		"esbuild": "^0.24.2"
	}
}


================================================
FILE: packages/lezer/CHANGELOG.md
================================================
# @orgajs/lezer

## 1.4.1

### Patch Changes

- bd2365a: fix types and linting
- Updated dependencies [bd2365a]
  - orga@4.7.1

## 1.4.0

### Minor Changes

- a53cfea: all about the editor

  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.

### Patch Changes

- Updated dependencies [a53cfea]
  - orga@4.6.0

## 1.3.1

### Patch Changes

- Updated dependencies [60ad38f]
  - orga@4.5.1

## 1.3.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - orga@4.5.0

## 1.2.1

### Patch Changes

- e3ef3a5: build website with orga-build

## 1.2.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- Updated dependencies [d8861c2]
  - orga@4.4.0

## 1.1.4

### Patch Changes

- 0f825de5: update editor dependencies

## 1.1.3

### Patch Changes

- Updated dependencies [7cfff79a]
  - orga@4.3.0

## 1.1.2

### Patch Changes

- ea032b35: bug fix, link generating button

## 1.1.1

### Patch Changes

- ac322714: implement editor
- Updated dependencies [ac322714]
  - orga@4.2.0

## 1.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - orga@4.1.0


================================================
FILE: packages/lezer/README.org
================================================
#+title: Lezer Parser for org-mode

* Tasks

** TODO properly support incremental parsing
** TODO finish nodes design
** TODO finish handlers
** TODO cleanup dependencies


================================================
FILE: packages/lezer/index.js
================================================
export { OrgParser, parser } from './lib/index.js'
export { tags } from './lib/nodes.js'


================================================
FILE: packages/lezer/lib/context.js
================================================
/**
 * @typedef {import('@lezer/common').PartialParse} PartialParse
 * @typedef {import('@lezer/common').Input} Input
 * @typedef {import('@lezer/common').TreeFragment} TreeFragment
 * @typedef {import('./fragments.js').FragmentCursor} FragmentCursor
 */

import { getSettings, makeParser } from 'orga'
import { fragmentCursor } from './fragments.js'
import { nodes } from './nodes.js'
import { toLezer } from './oast-to-lezer.js'
import { treeBuilder } from './tree.js'

/**
 * @param {import('./index.js').OrgParser} config
 * @param {Input} input
 * @param {TreeFragment[]} _fragments
 * @param {{from: number, to: number}[]} ranges
 * @returns {PartialParse}
 */
export function parseContext(config, input, _fragments, ranges) {
	const { log, nodeSet } = config
	let cursor = ranges[0].from
	const end = ranges[ranges.length - 1].to
	const rangeI = 0
	/** @type {number | null} */
	let stoppedAt = null
	const full = input.read(0, input.length)

	const builder = treeBuilder(nodeSet, nodes.document, 0, cursor, 0, 0)

	const fragments = _fragments.length
		? fragmentCursor(config, _fragments, input)
		: null

	// Read settings directly from document text
	const settings = getSettings(full)

	/** @type {import('orga').Parser | null} */
	let parser = null

	/**
	 * check if we reached the end of the input (ranges)
	 * finish the block in parser if exist
	 * check if we can reuse a fragment
	 * @returns {import('@lezer/common').Tree | null}
	 */
	function advance() {
		log('advance called', cursor, end)
		// TODO: should we set an end to the tree?
		// will take a look when this actually happens
		if (stoppedAt != null && cursor > stoppedAt) return builder.build()

		if (cursor >= end) {
			// end of the tree has to match the end of the input
			// sometimes the the chidren does not fill the whole tree
			// which causes the end of the tree to be smaller than the end of the input
			// set it to the end of the input will prevent unnecessary parsing
			return builder.build(end)
		}

		if (fragments !== null && couldReuse(fragments)) {
			const result = fragments.takeNodes(cursor, ranges, rangeI)
			if (result.taken > 0) {
				wrapUpParser()
				builder.addChildren(result.nodes, result.positions)
				cursor += result.taken
				return null
			} else {
				log('took nothing')
			}
		}

		if (!parser) {
			log('-- creating parser --', cursor, end)

			parser = makeParser(full, {
				range: { start: cursor, end },
				settings,
				flat: true
			})
		}

		// parser.advance should finish a block
		const document = parser.advance()
		if (typeof document === 'number') {
			cursor = document
			return null
		}

		wrapUpParser()
		return null
	}

	function wrapUpParser() {
		if (!parser) return
		const document = parser.finish()
		log(
			`wrap up parser: ${document.children.length}, ${document.position?.start.offset}, ${document.position?.end.offset}`
		)

		const tree = toLezer(document, nodeSet)
		log(document)
		log(tree)
		builder.takeChildren(tree, document.position?.start.offset)
		builder.takeProps(tree)
		if (document.position?.end.offset) cursor = document.position.end.offset
		log('-- destroying parser --')
		parser = null
	}

	/**
	 * check if we can reuse nodes from fragments
	 * @param {FragmentCursor} fragments
	 */
	function couldReuse(fragments) {
		const hash = builder.hash
		// TODO: pass the real lineStart
		if (!fragments.moveTo(cursor, cursor)) return false
		if (!fragments.matches(hash)) return false
		return true
	}

	return {
		get parsedPos() {
			log('parsedPos called', cursor)
			// if return undefined, the call of advance was not as intense
			return cursor
			// return parser.now
		},
		advance,
		stopAt(pos) {
			log('stopAt called', pos, stoppedAt)
			if (stoppedAt != null && stoppedAt < pos)
				throw new RangeError("Can't move stoppedAt forward")
			stoppedAt = pos
		},
		get stoppedAt() {
			return stoppedAt
		}
	}
}


================================================
FILE: packages/lezer/lib/fragments.js
================================================
/**
 * @typedef {import('@lezer/common').PartialParse} PartialParse
 * @typedef {import('@lezer/common').Input} Input
 * @typedef {import('@lezer/common').TreeFragment} TreeFragment
 * @typedef {import('@lezer/common').TreeCursor} TreeCursor
 *
 * @typedef TakeNodesResult
 * @property {Tree[]} nodes
 * @property {number[]} positions
 * @property {number} taken
 *
 * @typedef FragmentCursor
 * @property {(pos: number, lineStart: number) => boolean} moveTo
 * @property {(hash: number) => boolean} matches
 * @property {(start: number, ranges: {from: number, to: number}[], rangeI: number) => TakeNodesResult} takeNodes
 */

import { NodeProp, Tree } from '@lezer/common'
import { nodes } from './nodes.js'

/**
 * @param {import('./index.js').OrgParser} config
 * @param {TreeFragment[]} fragments
 * @param {Input} input
 * @returns {FragmentCursor}
 */
export function fragmentCursor({ log, nodeSet }, fragments, input) {
	let i = 0
	/** @type {TreeCursor | null} */
	let cursor = null
	/** @type {TreeFragment | null} */
	let fragment = fragments.length ? fragments[i++] : null
	let fragmentEnd = -1

	return {
		moveTo,
		matches,
		takeNodes
	}

	function nextFragment() {
		fragment = i < fragments.length ? fragments[i++] : null
		cursor = null
		fragmentEnd = -1
	}

	/**
	 * move the cursor to the first block after `pos`.
	 * @param {number} pos
	 * @param {number} lineStart
	 */
	function moveTo(pos, lineStart) {
		while (fragment && fragment.to < pos) nextFragment()
		if (!fragment || fragment.from > (pos ? pos - 1 : 0)) {
			return false
		}

		fragmentEnd = fragment.to

		if (fragmentEnd < 0) {
			let end = fragment.to
			while (end > 0 && input.read(end - 1, end) !== '\n') end--
			fragmentEnd = end ? end - 1 : 0
		}

		const c = cursor || fragment.tree.cursor()
		if (!cursor) {
			cursor = c
			c.firstChild()
		}
		// if (!c) {
		//   c = cursor = fragment.tree.cursor()
		//   c?.firstChild()
		// }

		const rPos = pos + fragment.offset
		while (c.to <= rPos) if (!c.parent()) return false
		for (;;) {
			if (c.from >= rPos) return fragment.from <= lineStart
			if (!c.childAfter(rPos)) return false
		}
	}

	/**
	 * @param {number} hash
	 */
	function matches(hash) {
		const tree = cursor?.tree
		const result = tree ? tree.prop(NodeProp.contextHash) === hash : false
		if (result) {
			log('✅ fragment matches, reusing', {
				hash,
				np: tree?.prop(NodeProp.contextHash)
			})
		} else {
			log('❌ fragment does not match, not reusing', {
				hash,
				np: tree?.prop(NodeProp.contextHash)
			})
		}
		return result
	}

	/**
	 * @param {number} start
	 * @param {{from: number, to: number}[]} ranges
	 * @param {number} rangeI
	 * @returns {TakeNodesResult}
	 */
	function takeNodes(start, ranges, rangeI) {
		/** @type {TakeNodesResult} */
		const result = {
			nodes: [],
			positions: [],
			taken: 0
		}

		log('takeNodes', start, ranges, rangeI)

		if (!cursor || !fragment) return result
		const cur = cursor
		const off = fragment.offset
		let end = start
		// let prevEnd = end
		let blockI = 0
		// let prevI = 0
		const fragEnd = fragmentEnd - (fragment.openEnd ? 1 : 0)
		for (;;) {
			if (cur.to - off > fragEnd) {
				if (cur.type.isAnonymous && cur.firstChild()) continue
				log(
					`stop takeNodes from ${cur.name}: fe: ${fragEnd} | ${fragmentEnd}, cur: ${cur.name}, cur.from: ${cur.from}, cur.to: ${cur.to}, off: ${off}`
				)
				break
			}

			const pos = toRelative(cur.from - off, ranges)
			if (cur.to - off <= ranges[rangeI].to) {
				// Fits in current range
				log(
					`Fits in current range, name: ${cur.name}, pos: ${pos}, cur.from: ${cur.from}, cur.to: ${cur.to}`
				)
				const tree = cur.tree

				if (tree) {
					result.nodes.push(tree)
					result.positions.push(pos)
				}
			} else {
				log('create dummy')
				const dummy = new Tree(
					nodeSet.types[nodes.paragraph],
					[],
					[],
					0
					// cx.block.hashProp
				)
				result.nodes.push(dummy)
				result.positions.push(pos)
				// reuse dummy?
			}

			if (cur.type.is('Block')) {
				log('got block:', cur.type.name)
				end = cur.to - off
				blockI = result.nodes.length
			}
			if (!cur.nextSibling()) break
		}
		log(`>> popping: ${blockI} / ${result.nodes.length}`)
		log('node:', result.nodes.map((n) => n.type.name).join(','))
		while (result.nodes.length > blockI) {
			const n = result.nodes.pop()
			log('.. pop non blocks', n?.type.name)
			result.positions.pop()
		}

		result.taken = end - start
		return result
	}
}

/**
 * Convert an input-stream-relative position to a
 * Markdown-doc-relative position by subtracting the size of all input
 * gaps before `abs`.
 * @param {number} abs
 * @param {{from: number, to: number}[]} ranges
 */
function toRelative(abs, ranges) {
	let pos = abs
	for (let i = 1; i < ranges.length; i++) {
		const gapFrom = ranges[i - 1].to,
			gapTo = ranges[i].from
		if (gapFrom < abs) pos -= gapTo - gapFrom
	}
	return pos
}


================================================
FILE: packages/lezer/lib/handlers.js
================================================
/**
 * @typedef {import('./types.js').Seed} Seed
 * @typedef {import('./types.js').Handler} Handler

 * @typedef {Record<string, Handler>} Handlers
 *   Handle nodes.

 */
import { NodeProp } from '@lezer/common'
import { nodes } from './nodes.js'

// class NodeProp extends _NodeProp {
//   static path = new _NodeProp({ perNode: true })
// }

/** @type {NodeProp<{level: number}>} */
export const headlineProp = new NodeProp({ perNode: true })

export const documentProp = new NodeProp({
	perNode: true
	// deserialize: (str) => {
	// 	console.log('deserialize', str)
	// 	return str
	// }
})

/**
 * @type {Handlers}
 */
export const handlers = {
	document: (_s, doc) => {
		if (doc.type !== 'document') {
			return false
		}
		return {
			id: nodes.document,
			props: [[documentProp, doc.properties]]
		}
	},
	headline: (_s, node) => {
		if (node.type === 'headline') {
			return {
				id: nodes.headline,
				props: [[headlineProp, { level: node.level }]]
			}
		}
		return false
	},
	stars: () => nodes.stars,
	todo: (_s, node) => {
		if (node.type !== 'todo') {
			return false
		}

		return nodes.todo
	},
	'link.path': () => nodes.url,
	// 'link.description': () => nodes.linkDescription,
	link: () => nodes.link,
	opening: () => nodes.mark,
	closing: () => nodes.mark,
	block: () => nodes.block,
	html: () => nodes.html,
	jsx: () => nodes.jsx,
	'block.begin': () => nodes.blockBegin,
	'block.end': () => nodes.blockEnd,
	tags: () => nodes.marker,
	keyword: () => nodes.keyword,
	paragraph: () => nodes.paragraph,
	list: () => nodes.list,
	'list.item.bullet': () => nodes.marker,
	text: (_, node) => {
		if (node.type !== 'text') {
			return false
		}
		switch (node.style) {
			case 'bold':
				return nodes.bold
			case 'italic':
				return nodes.italic
			case 'strikeThrough':
				return nodes.strikeThrough
			case 'code':
				return nodes.code
			case 'verbatim':
				return nodes.code
			case 'underline':
				return nodes.underline
		}
		return false
	}
}


================================================
FILE: packages/lezer/lib/index.js
================================================
/**
 * @typedef {import('@lezer/common').PartialParse} PartialParse
 * @typedef {import('@lezer/common').Input} Input
 * @typedef {import('@lezer/common').TreeFragment} TreeFragment
 */

/**
 * @typedef OrgParserConfig
 * @property {import('@lezer/common').NodePropSource[] | undefined | null} props
 */

import { NodeSet, Parser } from '@lezer/common'
import { parseContext } from './context.js'
import { nodeSet } from './nodes.js'

export { tags } from './nodes.js'

export class OrgParser extends Parser {
	/**
	 * @param {NodeSet} nodeSet
	 * @param {(...data: any[]) => void} [log]
	 */
	constructor(nodeSet, log = () => {}) {
		super()
		this.nodeSet = nodeSet
		this.log = log
	}

	/**
	 * @param {Input} input
	 * @param {TreeFragment[]} fragments
	 * @param {{from: number, to: number}[]} ranges
	 * @returns {PartialParse}
	 */
	createParse(input, fragments, ranges) {
		const r = ranges.map((r) => `${r.from}-${r.to}`).join(', ')
		const frags = fragments
			.map(
				(f) => `(${f.from}-${f.to}, offset: ${f.offset}, openEnd: ${f.openEnd})`
			)
			.join(' ')
		// TODO: add info more about fragments, how do I use ranges vs fragments?
		this.log(`createParse`, `ranges: (${r}), frags: [${frags}]`)
		const parse = parseContext(this, input, fragments, ranges)
		return parse
	}

	/**
	 * @param {OrgParserConfig} config
	 */
	configure(config) {
		let { nodeSet } = this
		const nodeTypes = nodeSet.types.slice()

		nodeSet = new NodeSet(nodeTypes)
		if (config.props && config.props.length > 0) {
			nodeSet = nodeSet.extend(...config.props)
		}
		return new OrgParser(nodeSet, this.log)
	}
}

export const parser = new OrgParser(
	nodeSet,
	console.log.bind(console, 'orga-parser')
)


================================================
FILE: packages/lezer/lib/nodes.js
================================================
import { NodeProp, NodeSet, NodeType } from '@lezer/common'
import { styleTags, Tag, tags as t } from '@lezer/highlight'

let i = 0
export const nodes = Object.freeze({
	none: i++,
	// block
	document: i++,
	headline: i++,
	paragraph: i++,
	keyword: i++,
	block: i++,
	list: i++,
	html: i++,
	jsx: i++,
	// inline
	stars: i++,
	todo: i++,
	done: i++,
	link: i++,
	marker: i++,
	bold: i++,
	italic: i++,
	code: i++,
	strikeThrough: i++,
	underline: i++,
	url: i++,
	blockBegin: i++,
	blockEnd: i++,
	// smaller
	mark: i++
})

/**
 * @type {NodeProp<{level: number}>}
 */
export const headlineProp = new NodeProp()

/** @type {NodeType[]} */
export const nodeTypes = Object.entries(nodes).map(([name, id]) =>
	NodeType.define({
		id,
		name,
		props: id >= nodes.stars ? [] : [[NodeProp.group, ['Block']]],
		top: name === 'document'
	})
)

// extra tags
const underline = Tag.define(t.content)

const orgHighlighting = styleTags({
	'headline/...': t.heading,
	keyword: t.attributeName,
	link: t.link,
	'stars mark blockBegin blockEnd': t.processingInstruction,
	italic: t.emphasis,
	bold: t.strong,
	strikeThrough: t.strikethrough,
	paragraph: t.content,
	list: t.list,
	underline: underline,
	'html jsx code block': t.monospace
})

export const tags = {
	...t,
	underline
}

export const nodeSet = new NodeSet(nodeTypes).extend(orgHighlighting)


================================================
FILE: packages/lezer/lib/oast-to-lezer.js
================================================
/**
 * @typedef {import('orga').Document} OrgTree
 * @typedef {import('@lezer/common').Tree} LezerTree
 * @typedef {import('@lezer/common').NodeSet} NodeSet
 * @typedef {import('orga').Document} OastRoot
 * @typedef {import('orga').Content} OastContent
 * @typedef {import('orga').Parent} OastParent

 * @callback Mapping
 *   Transform an oast node to prose node.
 * @param {OastNodes} node
 * @param {number} id
 * @param {Array<LezerTree> | undefined} [children]
 * @returns {LezerTree | null | undefined}

 * @typedef {import('./types.js').State} ParseState
 */
import { NodeProp, Tree } from '@lezer/common'
import { handlers } from './handlers.js'

/**
 * @param {import('vfile').VFile | null} file
 * @param {NodeSet} nodeSet
 * @returns {ParseState}
 */
function createParseState(file, nodeSet) {
	/** @type {ParseState} */
	const state = {
		file,
		ignore: ['newline', 'emptyLine'],
		nodeSet: nodeSet,
		handlers,
		one(node, parent, base = 0) {
			return one(this, node, parent, base)
		},
		all(parent, base) {
			return all(this, parent, base)
		}
	}
	return state
}

/**
 * @param {OrgTree} tree
 * @param {NodeSet} nodeSet
 * @param {import('vfile').VFile | null} [file=null]
 * @returns {import('@lezer/common').Tree}
 */
export function toLezer(tree, nodeSet, file = null) {
	// TODO: inject gaps
	const state = createParseState(file, nodeSet)
	const result = state.one(tree)
	if (!result) {
		throw new Error('no result')
	}
	const t = result.nodes[0]
	const _props = tree.properties
	return t
}

/** @type {import('./types.js').Handler} */
function defaultUnknownHandler() {
	// console.log('unknown node', n.type, n)
	return true
}

/**
 * @param {import('./types.js').OastNode} node
 * @returns {[number, number]}
 */
function getRange(node) {
	const start = node.position?.start.offset || 0
	const end = node.position?.end.offset || 0
	return [start, end - start]
}

/**
 * @param {ParseState} state
 * @param {import('./types.js').OastNode} node
 * @param {OastParent | undefined} [parent]
 * @param {number} [base=0]
 * @returns {{nodes: LezerTree[], positions: number[]} | null | undefined}}
 */
function one(state, node, parent, base = 0) {
	if (state.ignore.includes(node.type)) {
		return state.all(node, base)
	}

	const handler = state.handlers[node.type] || defaultUnknownHandler
	const seed = handler(state, node, parent)

	if (typeof seed === 'boolean') {
		if (seed) {
			return state.all(node, base)
		}
		return null
	}

	let [id, skip, props] =
		typeof seed === 'number' ? [seed, false] : [seed.id, seed.skip, seed.props]

	const [loc, len] = getRange(node)
	const pos = loc - base

	/** @type {Tree[]} */
	let nodes = []
	/** @type {number[]} */
	let positions = []
	if (!skip) {
		const result = state.all(node, loc)
		nodes = result.nodes
		positions = result.positions
	}

	if (node.data?.hash !== undefined) {
		if (!props) {
			props = []
		}
		props.push([NodeProp.contextHash, node.data.hash])
	}

	const tree = new Tree(state.nodeSet.types[id], nodes, positions, len, props)
	const result = { nodes: [tree], positions: [pos] }
	return result
}

/**
 * @param {ParseState} state
 * @param {import('./types.js').OastNode} parent
 * @param {number} base
 * @returns {{nodes: LezerTree[], positions: number[]}}}
 */
function all(state, parent, base) {
	/** @type {Array<LezerTree>} */
	const _nodes = []
	/** @type {Array<number>} */
	const _positions = []

	if ('children' in parent) {
		let index = -1
		while (++index < parent.children.length) {
			const node = parent.children[index]
			const { nodes, positions } = state.one(node, parent, base) || {
				nodes: [],
				positions: []
			}
			_nodes.push(...nodes)
			_positions.push(...positions)
		}
	}
	return {
		nodes: _nodes,
		positions: _positions
	}
}


================================================
FILE: packages/lezer/lib/tree.js
================================================
import { NodeProp, NodeType, Tree } from '@lezer/common'
import { documentProp } from './handlers.js'

// import { nodes } from './nodes.js'

/**
 * @param {number} type
 * @param {number} value
 * @param {number} [parentHash=0]
 */
function hash(type, value, parentHash = 0) {
	return (parentHash + (parentHash << 8) + type + (value << 4)) | 0
}

/**
 * @param {import('@lezer/common').NodeSet} nodeSet
 * @param {number} type
 * @param {number} value
 * @param {number} from
 * @param {number} parentHash
 * @param {number} originalEnd
 */
export function treeBuilder(
	nodeSet,
	type,
	value,
	from,
	parentHash,
	originalEnd
) {
	/** @type {Tree[]} */
	const children = []
	/** @type {number[]} */
	const positions = []

	const _hash = hash(type, value, parentHash)

	/** @type {[NodeProp<any>, any][]} */
	const props = [[NodeProp.contextHash, _hash]]

	return {
		addChild,
		addChildren,
		takeChildren,
		takeProps,
		addProps: (/** @type {[NodeProp<any>, any][]} */ p) => props.push(...p),
		build,
		hash: _hash
	}

	/**
	 * @param {Tree} child
	 * @param {number} pos
	 */
	function addChild(child, pos) {
		if (child.prop(NodeProp.contextHash) !== _hash)
			child = new Tree(
				child.type,
				child.children,
				child.positions,
				child.length,
				props
			)
		children.push(child)
		positions.push(pos)
	}

	/**
	 * @param {Tree[]} children
	 * @param {number[]} positions
	 */
	function addChildren(children, positions) {
		for (let i = 0; i < children.length; i++)
			addChild(children[i], positions[i])
	}

	/**
	 * @param {Tree} tree
	 * @param {number} [offset=0]
	 */
	function takeChildren(tree, offset = 0) {
		// addChildren(tree.children, tree.positions)
		const cursor = tree.cursor()
		if (!cursor.firstChild()) return
		do {
			const child = cursor.tree
			if (!child) continue
			// TODO: is the position correct?
			addChild(child, cursor.from + offset)
		} while (cursor.nextSibling())
	}

	/**
	 * @param {Tree} tree
	 */
	function takeProps(tree) {
		const doc = tree.prop(documentProp)
		if (doc) {
			props.push([documentProp, doc])
		}
	}

	/**
	 * @param {number} [end = originalEnd] - end of the tree
	 * @returns {Tree}
	 */
	function build(end = originalEnd) {
		const last = children.length - 1
		if (last >= 0)
			end = Math.max(end, positions[last] + children[last].length + from)

		const tree = new Tree(
			nodeSet.types[type],
			children,
			positions,
			end - from
		).balance({
			makeTree: (children, positions, length) =>
				new Tree(NodeType.none, children, positions, length, props)
		})

		return tree
	}
}


================================================
FILE: packages/lezer/lib/types.ts
================================================
import type { Tree as LezerTree, NodeSet } from '@lezer/common'
import type { Content, Document, Parent as OastParent, Token } from 'orga'
import type { Position } from 'unist'
import type { VFile } from 'vfile'

export type OastNode = Document | Content | Token

type Action = boolean

export type Seed =
	| {
			id: number
			position?: Position
			props?: any
			skip?: Action
	  }
	| Action
	| number

interface LezerChild {
	node: LezerTree
	position: number
}

export type Handler = (
	state: State,
	node: OastNode,
	parent: OastParent | undefined
) => Seed

export interface State {
	file: VFile | null
	ignore: string[]
	readonly nodeSet: NodeSet
	handlers: Record<string, Handler>
	one: (
		node: OastNode,
		parent?: OastParent | undefined,
		base?: number
	) => { nodes: LezerTree[]; positions: number[] } | null | undefined
	all: (
		node: OastNode,
		base: number
	) => { nodes: LezerTree[]; positions: number[] }
}


================================================
FILE: packages/lezer/package.json
================================================
{
	"name": "@orgajs/lezer",
	"version": "1.4.1",
	"description": "lezer parser for org-mode",
	"type": "module",
	"files": [
		"lib/",
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"scripts": {
		"test": "node --test tests/*.test.js"
	},
	"keywords": [
		"org-mode",
		"org",
		"parser",
		"lezer"
	],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"repository": {
		"url": "orgapp/orgajs",
		"directory": "packages/lezer"
	},
	"dependencies": {
		"@lezer/common": "^1.1.1",
		"@lezer/highlight": "^1.2.1",
		"orga": "workspace:^",
		"unist-util-visit": "^5.0.0"
	},
	"devDependencies": {
		"@types/unist": "^3.0.3",
		"text-kit": "workspace:^",
		"vfile": "^6.0.3"
	}
}


================================================
FILE: packages/lezer/tests/compare-tree.js
================================================
import { Tree } from '@lezer/common'

/**
 * @typedef {import('@lezer/common').Tree} Tree
 */

/**
 * @param {Tree} a
 * @param {Tree} b
 */
export function compareTree(a, b) {
	const curA = a.cursor(),
		curB = b.cursor()
	for (;;) {
		let mismatch = null,
			next = false
		if (curA.type !== curB.type)
			mismatch = `Node type mismatch (${curA.name} vs ${curB.name})`
		else if (curA.from !== curB.from)
			mismatch = `Start pos mismatch for ${curA.name}: ${curA.from} vs ${curB.from}`
		else if (curA.to !== curB.to)
			mismatch = `End pos mismatch for ${curA.name}: ${curA.to} vs ${curB.to}`
		else {
			next = curA.next()
			if (next !== curB.next()) mismatch = `Tree size mismatch`
		}
		if (mismatch) {
			const lines = [mismatch, 'a-:>', ...print(a), 'b-:>', ...print(b)]
			throw new Error(lines.join('\n'))
		}

		if (!next) break
	}
}

/**
 * @param {import('@lezer/common').TreeCursor | Tree} tree
 * @param {string} [prefix]
 */
export function print(tree, prefix = '') {
	const cur = tree instanceof Tree ? tree.cursor() : tree
	const lines = [`${prefix}${cur.name} (${cur.from}-${cur.to})`]
	if (cur.firstChild()) {
		do {
			lines.push(...print(cur, `${' '.repeat(prefix.length)}└╴`))
		} while (cur.nextSibling())
		cur.parent()
	}
	return lines
}


================================================
FILE: packages/lezer/tests/incremental.test.js
================================================
/**
 * @typedef {{from: number, to?: number, insert?: string}[]} ChangeSpec
 */

import assert from 'node:assert'
import { describe, it } from 'node:test'
import { Tree, TreeFragment } from '@lezer/common'
import { parser } from '../lib/index.js'
import { compareTree } from './compare-tree.js'

const doc = `* Header
This is a /paragraph/.
Still the same =paragraph=.

#+begin_src js
console.log('hello')
#+end_src

here is a link: [[https://example.com][link text]]
`
const docLength = doc.length

class State {
	constructor(doc, tree, fragments) {
		this.doc = doc
		this.tree = tree
		this.fragments = fragments
	}

	static start(doc) {
		const tree = parser.parse(doc)
		return new State(doc, tree, TreeFragment.addTree(tree))
	}

	/**
	 * @param {ChangeSpec[]} changes
	 * @param {boolean} reparse
	 */
	update(changes, reparse = true) {
		let changed = [],
			doc = this.doc,
			off = 0
		for (const { from, to = from, insert = '' } of changes) {
			doc = doc.slice(0, from) + insert + doc.slice(to)
			changed.push({
				fromA: from - off,
				toA: to - off,
				fromB: from,
				toB: from + insert.length
			})
			off += insert.length - (to - from)
		}
		const fragments = TreeFragment.applyChanges(this.fragments, changed, 2)
		if (!reparse) return new State(doc, Tree.empty, fragments)
		// return this
		const tree = parser.parse(doc, fragments)
		return new State(doc, tree, TreeFragment.addTree(tree, fragments))
	}
}

// const state1 = State.start(doc)

/**
 * @param {ChangeSpec} change
 * @param {boolean} [verbose=false]
 * @param {number} reuse
 */
function testChange(change, verbose = false, reuse = 10) {
	const state1 = State.start(doc)
	const state = state1.update(change)
	const updatedDoc = state.doc
	verbose && console.log('updatedDoc', updatedDoc)
	compareTree(state.tree, parser.parse(updatedDoc))

	if (reuse) {
		const diff = overlap(state.tree, state1.tree)
		assert.ok(diff > reuse, `diff: ${diff}`)
	}
}

/**
 * @param {Tree} a
 * @param {Tree} b
 */
function overlap(a, b) {
	let inA = new Set(),
		shared = 0,
		sharingTo = 0
	for (let cur = a.cursor(); cur.next(); ) if (cur.tree) inA.add(cur.tree)
	for (let cur = b.cursor(); cur.next(); )
		if (
			cur.tree &&
			inA.has(cur.tree) &&
			cur.type.is('Block') &&
			cur.from >= sharingTo
		) {
			shared += cur.to - cur.from
			sharingTo = cur.to
		}
	return Math.round((shared * 100) / b.length)
}

describe('incremential parsing', () => {
	// it.runOnly(true)
	it('can insert in the middle', () => {
		testChange([{ from: 2, to: 2, insert: 'bears' }])
	})
	it('can insert at the begining', () => {
		testChange([{ from: 0, to: 0, insert: 'bears' }])
	})
	it('can handle deletion', () => {
		testChange([{ from: 0, to: 5 }])
	})
	it('can appending at the end', () => {
		const size = doc.length
		testChange([{ from: size, to: size, insert: '* another heading' }])
	})
	it('can replace content', () => {
		testChange([{ from: 2, to: 8, insert: 'bears' }])
	})
	it('reuses nodes from the previous parse', () => {
		const state1 = State.start(doc)
		const state = state1.update([{ from: 2, to: 8, insert: 'bears' }])
		const diff = overlap(state1.tree, state.tree)
		assert.ok(diff > 90, `diff: ${diff}`)
		console.log('hello test')
	})
	it('can handle deleting a star', () => testChange([{ from: 0, to: 1 }]))
	// it('can reuse content for a change in a block context', () => {})
	// it('can handle adding to a quoted block', () => {})
	// it('can handle a change in a post-linkref paragraph', () => {})
	// it('can handle a change in a paragraph-adjacent linkrefs', () => {})

	it('can handle insertion at the eof', () =>
		testChange([{ from: docLength, to: docLength, insert: '* h' }]))
})


================================================
FILE: packages/lezer/tsconfig.json
================================================
{
	"extends": "../../tsconfig.json"
}


================================================
FILE: packages/loader/CHANGELOG.md
================================================
# Change Log

## 4.4.4

### Patch Changes

- bd2365a: fix types and linting
- Updated dependencies [bd2365a]
  - @orgajs/orgx@2.6.1

## 4.4.3

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/orgx@2.6.0

## 4.4.2

### Patch Changes

- @orgajs/orgx@2.5.2

## 4.4.1

### Patch Changes

- @orgajs/orgx@2.5.1

## 4.4.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/orgx@2.5.0

## 4.3.2

### Patch Changes

- e3ef3a5: build website with orga-build
- Updated dependencies [e3ef3a5]
  - @orgajs/orgx@2.4.1

## 4.3.1

### Patch Changes

- Updated dependencies [351f690]
  - @orgajs/orgx@2.4.0

## 4.3.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- Updated dependencies [d8861c2]
  - @orgajs/orgx@2.3.0

## 4.2.2

### Patch Changes

- @orgajs/orgx@2.2.2

## 4.2.1

### Patch Changes

- @orgajs/orgx@2.2.1

## 4.2.0

### Minor Changes

- ac322714: implement editor

### Patch Changes

- Updated dependencies [ac322714]
  - @orgajs/orgx@2.2.0

## 4.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - @orgajs/orgx@2.1.0

## 4.0.1

### Patch Changes

- Updated dependencies [1dbf674d]
  - @orgajs/orgx@2.0.1

## 4.0.0

### Major Changes

- 176a3b5d: # Migrate most of the ecosystem to ESM

  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.

  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.

  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.

  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!

### Patch Changes

- Updated dependencies [176a3b5d]
  - @orgajs/orgx@2.0.0

## 3.1.10

### Patch Changes

- Updated dependencies [eeccc870]
  - @orgajs/orgx@1.0.8

## 3.1.9

### Patch Changes

- Updated dependencies [6c1ddb9f]
  - @orgajs/orgx@1.0.7

## 3.1.8

### Patch Changes

- 4bde5155: tidy up dependencies
- Updated dependencies [4bde5155]
  - @orgajs/orgx@1.0.6

## 3.1.7

### Patch Changes

- @orgajs/orgx@1.0.5

## 3.1.6

### Patch Changes

- @orgajs/orgx@1.0.4

## 3.1.5

### Patch Changes

- Updated dependencies [cd7cac3d]
  - @orgajs/orgx@1.0.3

## 3.1.4

### Patch Changes

- Updated dependencies [c8edd571]
  - @orgajs/orgx@1.0.2

## 3.1.3

### Patch Changes

- 594bf16b: ## @orgajs/orgx

  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).

  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:

  - `@orgajs/loader`
  - `@orgajs/next`
  - `gatsby-plugin-orga`
  - `gatsby-theme-orga-docs`
  - `@orgajs/playground'`

  `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.

  - `gatsby-theme-orga-posts`
  - `gatsby-theme-orga-posts-core`

  ## theme-ui support

  `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.

- Updated dependencies [594bf16b]
  - @orgajs/orgx@1.0.1

## 3.1.2

### Patch Changes

- @orgajs/reorg@3.1.1

## 3.1.1

### Patch Changes

- 8c6f440b: - better layout support
  - rename MDXxxx to Orgaxxx

## 3.1.0

### Minor Changes

- eeea0c54: introduce new token: empty line

### Patch Changes

- Updated dependencies [eeea0c54]
  - @orgajs/reorg@3.1.0

## 3.0.1

### Patch Changes

- 6ed76057: # rename gatsby themes

  - gatsby-theme-orga -> gatsby-theme-orga-posts-core
  - gatsby-theme-blorg -> gatsby-theme-orga-posts

  # add example projects

  - gatsby-posts
  - gatsby-posts-core

- 759e6149: # Bug Fixes

  - fix lexer for parsing headline with todo keyword
  - fix properties drawer issue
  - fix orga-theme-ui-preset package
  - fix gatsby-transformer-orga & gatsby-theme-blorg

  # Improved Playground

  - add `tokens` view
  - show node type in tree views

- Updated dependencies [6ed76057]
- Updated dependencies [759e6149]
  - @orgajs/reorg@3.0.1

## 3.0.0

### Major Changes

- 8b02d10: # Features

  - more powerful and flexible lexer and parser
  - webpack support
  - `jsx` support
  - better code block rendering
  - better image processing in gatsby
  - updated examples
  - tons of bug fixes
  - brand new `gatsby-plugin-orga`

### Patch Changes

- Updated dependencies [8b02d10]
  - @orgajs/reorg@3.0.0

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [2.6.0](https://github.com/orgapp/orgajs/compare/v2.5.0...v2.6.0) (2021-08-28)

### Bug Fixes

- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))
- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))
- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))

# [2.5.0](https://github.com/orgapp/orgajs/compare/v2.4.9...v2.5.0) (2021-08-27)

### Bug Fixes

- fix examples ([bdcd265](https://github.com/orgapp/orgajs/commit/bdcd2655502a73800e8915ba09fd78452dff503f))

## [2.4.9](https://github.com/orgapp/orgajs/compare/v2.4.8...v2.4.9) (2021-07-13)

**Note:** Version bump only for package @orgajs/loader

## [2.4.8](https://github.com/orgapp/orgajs/compare/v2.4.7...v2.4.8) (2021-04-26)

**Note:** Version bump only for package @orgajs/loader

## [2.4.7](https://github.com/orgapp/orgajs/compare/v2.4.6...v2.4.7) (2021-04-26)

**Note:** Version bump only for package @orgajs/loader


================================================
FILE: packages/loader/LICENSE.org
================================================
The MIT License (MIT)

Copyright (c) 2015 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: packages/loader/index.cjs
================================================
// stolen code from @mdx-js/loader

/**
 * Webpack loader
 *
 * @todo once webpack supports ESM loaders, remove this wrapper.
 *
 * @this {LoaderContext}
 * @param {string} code
 */
module.exports = function orgLoader(code) {
	const callback = this.async()
	// Note that `import()` caches, so this should be fast enough.
	import('./lib/index.js').then((module) =>
		module.loader.call(this, code, callback)
	)
}


================================================
FILE: packages/loader/index.d.ts
================================================
import type { ProcessorOptions } from '@orgajs/orgx'
import type { LoaderContext } from 'webpack'

/**
 * A Webpack loader to compile MDX to JavaScript.
 *
 * [Reference for Loader API](https://webpack.js.org/api/loaders/)
 *
 * @this {LoaderContext<unknown>}
 * @param {string} value
 *   The original module source code.
 * @returns {void}
 */
declare function orgLoader(this: LoaderContext<unknown>, value: string): void

export default orgLoader

export type Options = ProcessorOptions


================================================
FILE: packages/loader/lib/index.js
================================================
/**
 * @typedef {import('webpack').LoaderContext<unknown>} LoaderContext
 */

import path from 'node:path'
import { createProcessor } from '@orgajs/orgx'

/**
 * @param {string} source
 * @param {LoaderContext['callback']} callback
 * @this {LoaderContext}
 */
export async function loader(source, callback) {
	const processor = createProcessor({
		development: this.mode === 'development',
		...this.getOptions()
	})

	try {
		const file = await processor.process({
			value: source,
			path: this.resourcePath
		})
		callback(undefined, file.value, file.map)
	} catch (error) {
		const fpath = path.relative(this.context, this.resourcePath)
		error.message = `${fpath}:${error.name}: ${error.message}`
		callback(error)
	}
}


================================================
FILE: packages/loader/package.json
================================================
{
	"name": "@orgajs/loader",
	"version": "4.4.4",
	"description": "Load org-mode content through orga.",
	"type": "module",
	"main": "./index.cjs",
	"types": "index.d.ts",
	"files": [
		"lib/",
		"index.cjs",
		"index.d.ts"
	],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"homepage": "https://github.com/orgapp/orgajs/tree/main/packages/loader#readme",
	"repository": {
		"type": "git",
		"url": "https://github.com/orgapp/orgajs.git",
		"directory": "packages/loader"
	},
	"scripts": {
		"test": "node --test tests/*.test.js"
	},
	"dependencies": {
		"@orgajs/orgx": "workspace:^",
		"vfile-reporter": "^8.1.1"
	},
	"devDependencies": {
		"@orgajs/react": "workspace:^",
		"@types/node": "^25.3.2",
		"babel-loader": "^9.1.3",
		"html-loader": "^4.2.0",
		"react": "^19.0.0",
		"react-dom": "^19.0.0",
		"webpack": "^5.104.1"
	}
}


================================================
FILE: packages/loader/tests/compiler.js
================================================
import { promises as fs } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { promisify } from 'node:util'
import webpack from 'webpack'

export async function compile(fixture, options = {}) {
	const base = new URL('.', import.meta.url)

	const result = await promisify(webpack)({
		// @ts-expect-error TODO: webpack types miss support for `context`.
		context: fileURLToPath(base),
		entry: `./${fixture}`,
		mode: 'none',
		output: {
			path: fileURLToPath(base),
			filename: 'bundle.js'
		},
		module: {
			rules: [
				{
					test: /\.org$/,
					use: [
						// {
						//   loader: 'babel-loader',
						//   options: {
						//     configFile: false,
						//     plugins: [
						//       '@babel/plugin-transform-runtime',
						//       '@babel/plugin-syntax-jsx',
						//       '@babel/plugin-transform-react-jsx',
						//     ],
						//   },
						// },
						{
							// loader: path.resolve(__dirname, '../dist'),
							loader: fileURLToPath(new URL('../index.cjs', import.meta.url)),
							options
						}
					]
				}
			]
		}
	})

	// cleanup
	await fs.unlink(new URL('bundle.js', base))
	return result
}


================================================
FILE: packages/loader/tests/example.md
================================================
# hello world

this is some content.


================================================
FILE: packages/loader/tests/fixture.org
================================================
#+title: hello world
* TODO headline one

#+begin_export jsx
<div style={{ color: 'red' }}>in a box</div>
#+end_export


================================================
FILE: packages/loader/tests/loader.test.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { compile } from './compiler.js'

test('basic org-mode parsing', async () => {
	const stats = await compile('fixture.org', {
		name: 'Alice'
	})

	// wait for 3 seconds
	await new Promise((resolve) => setTimeout(resolve, 3000))
	console.log('after the wait')

	const output = `${stats.toJson({ source: true }).modules[0].source}`
	assert.equal(
		output.trim(),
		`
/*@jsxRuntime automatic @jsxImportSource react*/
import {jsx as _jsx, jsxs as _jsxs} from "react/jsx-runtime";
export const title = 'hello world';
function _createOrgContent(props) {
  const _components = Object.assign({
    div: "div",
    h1: "h1"
  }, props.components);
  return _jsxs(_components.div, {
    className: "section",
    children: [_jsx(_components.h1, {
      children: "headline one"
    }), _jsx(_components.div, {
      style: {
        color: 'red'
      },
      children: "in a box"
    })]
  });
}
function OrgContent(props = {}) {
  const {wrapper: OrgLayout} = props.components || ({});
  return OrgLayout ? _jsx(OrgLayout, {
    ...props,
    children: _jsx(_createOrgContent, {
      ...props
    })
  }) : _createOrgContent(props);
}
export default OrgContent;
  `.trim()
	)
})


================================================
FILE: packages/metadata/CHANGELOG.md
================================================
# @orgajs/metadata

## 2.4.1

### Patch Changes

- bd2365a: fix types and linting

## 2.4.0

### Minor Changes

- a53cfea: all about the editor

  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.

## 2.3.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

## 2.2.0

### Minor Changes

- d8861c2: update unified ecosystem

## 2.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

## 2.0.0

### Major Changes

- 176a3b5d: # Migrate most of the ecosystem to ESM

  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.

  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.

  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.

  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!

## 1.0.2

### Patch Changes

- eeccc870: - get image links out of paragraph
  - some other minor fixes

## 1.0.1

### Patch Changes

- 594bf16b: ## @orgajs/orgx

  Introducing new compiler `@orgajs/orgx`. It's a (almost) a direct port of [xdm](https://github.com/wooorm/xdm).

  Most of the packages have already adopted `@orgajs/orgx`. The important ones are:

  - `@orgajs/loader`
  - `@orgajs/next`
  - `gatsby-plugin-orga`
  - `gatsby-theme-orga-docs`
  - `@orgajs/playground'`

  `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.

  - `gatsby-theme-orga-posts`
  - `gatsby-theme-orga-posts-core`

  ## theme-ui support

  `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.


================================================
FILE: packages/metadata/README.org
================================================
#+title: @orgajs/metadata


================================================
FILE: packages/metadata/index.js
================================================
/**
 * @typedef {import('./lib/index.js').Metadata} Metadata
 */

export { parse } from './lib/index.js'


================================================
FILE: packages/metadata/lib/index.js
================================================
/**
 * TODO: more types?
 * @typedef {string} Value
 * @typedef {Record<string, Value | Value[]>} Metadata
 */

const TO_DISCARD = [
	'caption',
	'header',
	'name',
	'plot',
	'results',
	/^attr_\w+/i, // Affiliated Keywords
	/^begin_\w+/i,
	/^end_\w+/i,
	'begin',
	'end', // blocks
	'call', // call
	'jsx' // orga's jsx support
]

/**
 * @param {string} key
 * @returns {boolean}
 */
function shouldDiscard(key) {
	return !!TO_DISCARD.find((test) => {
		if (typeof test === 'string') {
			return test === key.toLowerCase()
		}
		return test.test(key)
	})
}

/**
 * trim whitespaces and strip quotes if necessary
 * @param {string} text
 * @returns {Value}
 */
function processValue(text) {
	return text.trim().replace(/^["'](.+(?=["']$))["']$/, '$1')
}

/**
 * @param {Metadata} data
 */
function pushTo(data) {
	/**
	 * @param {string} _key
	 * @param {string} _value
	 * @returns {Metadata}
	 */
	return function (_key, _value) {
		const key = _key.toLowerCase()
		const value = processValue(_value)

		const existing = data[key]
		if (existing) {
			if (Array.isArray(existing)) {
				existing.push(value)
			} else {
				data[key] = [existing, value]
			}
		} else {
			data[key] = value
		}
		return data
	}
}

/**
 * @param {string} text
 * @returns {Metadata}
 */
export function parse(text) {
	const matches = text.matchAll(/^\s*#\+(\S+):(.*)$/gm)
	return [...matches].reduce((data, [, key, value]) => {
		if (shouldDiscard(key)) return data
		return pushTo(data)(key, value)
	}, {})
}


================================================
FILE: packages/metadata/package.json
================================================
{
	"name": "@orgajs/metadata",
	"version": "2.4.1",
	"description": "extract metadata info from org file",
	"type": "module",
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"homepage": "https://github.com/orgapp/orgajs/tree/main/packages/metadata#readme",
	"repository": {
		"type": "git",
		"url": "https://github.com/orgapp/orgajs.git",
		"directory": "packages/metadata"
	},
	"files": [
		"lib",
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"exports": "./index.js",
	"scripts": {
		"test": "node --test --no-warnings tests/test.js"
	},
	"devDependencies": {
		"@types/node": "^25.3.2",
		"tsx": "^4.19.2",
		"typescript": "^5.9.2"
	}
}


================================================
FILE: packages/metadata/tests/test.js
================================================
import * as assert from 'node:assert'
import { describe, it } from 'node:test'
import { parse } from '../index.js'

describe('metadata parser', () => {
	it('works', () => {
		assert.deepEqual(parse('#+title: hello world'), {
			title: 'hello world'
		})
	})

	it('can handle multiple entries', () => {
		assert.deepEqual(
			parse(`
#+include: file1.org
#+include: ../file2.org
`),
			{
				include: ['file1.org', '../file2.org']
			}
		)
	})

	it('can handle spaces at the front', () => {
		assert.deepEqual(
			parse(`
#+title: orga
#+keywords: parser ast
`),
			{
				title: 'orga',
				keywords: 'parser ast'
			}
		)
	})

	it('transform keys to lowercase', () => {
		assert.deepEqual(
			parse(`
#+TODO: TODO NEXT | DONE
#+todo: DRAFT | PUBLISHED
`),
			{
				todo: ['TODO NEXT | DONE', 'DRAFT | PUBLISHED']
			}
		)
	})

	it('strips quotes if necessary', () => {
		assert.deepEqual(
			parse(`
#+include: "./file1.org"
#+include: './file2.org'
#+desc: it's good
`),
			{
				include: ['./file1.org', './file2.org'],
				desc: "it's good"
			}
		)
	})
})


================================================
FILE: packages/metadata/tsconfig.json
================================================
{
	"extends": "../../tsconfig.json"
}


================================================
FILE: packages/next/README.org
================================================
* @orgajs/next

Next.js integration is now maintained in a standalone repository:

- [[https://github.com/orgapp/orga-next][orgapp/orga-next]]

Package name remains =@orgajs/next=.

For usage and setup instructions, see:

- [[https://github.com/orgapp/orga-next/blob/main/README.org][README.org]]
- [[https://orga.js.org/guides/next][Next.js guide]]


================================================
FILE: packages/node-loader/CHANGELOG.md
================================================
# @orgajs/node-loader

## 1.1.5

### Patch Changes

- bd2365a: fix types and linting
- Updated dependencies [bd2365a]
  - @orgajs/orgx@2.6.1

## 1.1.4

### Patch Changes

- Updated dependencies [a53cfea]
  - @orgajs/orgx@2.6.0

## 1.1.3

### Patch Changes

- @orgajs/orgx@2.5.2

## 1.1.2

### Patch Changes

- @orgajs/orgx@2.5.1

## 1.1.1

### Patch Changes

- b73e6b3: fix builder

## 1.1.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - @orgajs/orgx@2.5.0

## 1.0.1

### Patch Changes

- Updated dependencies [e3ef3a5]
  - @orgajs/orgx@2.4.1

## 1.0.0

### Major Changes

- 351f690: introduce @orgajs/node-loader, @orgajs/esbuild, @orgajs/build

  - @orgajs/node-loader : the nodejs loader for org-mode files
  - @orgajs/esbuild : esbuild plugin
  - @orgajs/build : static site generator, a.k.a orga-build

### Patch Changes

- Updated dependencies [351f690]
  - @orgajs/orgx@2.4.0


================================================
FILE: packages/node-loader/index.js
================================================
/**
 * @import {LoadFnOutput, LoadHook, LoadHookContext} from 'node:module'
 * @import {ProcessorOptions} from '@orgajs/orgx'
 */

/**
 * @typedef {Parameters<LoadHook>[2]} NextLoad
 *   Next.
 *
 * @typedef {ProcessorOptions} Options
 *   Configuration.
 *
 */

import fs from 'node:fs/promises'
import { createProcessor } from '@orgajs/orgx'
import { SourceMapGenerator } from 'source-map'
import { VFile } from 'vfile'
import { reporter } from 'vfile-reporter'

/**
 * Create Node.js hooks to handle org files.
 *
 * @param {Readonly<Options> | null | undefined} [loaderOptions]
 *   Configuration (optional).
 * @returns
 *   Node.js hooks.
 */
export function createLoader(loaderOptions) {
	let settings = configure(loaderOptions || {})

	return { initialize, load }

	/**
	 * @param {Readonly<Options> | null | undefined} options
	 */
	async function initialize(options) {
		settings = configure({ ...loaderOptions, ...options })
	}

	/**
	 * Load `file:` URLs to MD(X) files.
	 *
	 * @param {string} href
	 *   URL.
	 * @param {LoadHookContext} context
	 *   Context.
	 * @param {NextLoad} nextLoad
	 *   Next or default `load` function.
	 * @returns {Promise<LoadFnOutput>}
	 *   Result.
	 * @satisfies {LoadHook}
	 */
	async function load(href, context, nextLoad) {
		const url = new URL(href)
		const { compile } = settings

		if (url.protocol === 'file:' && /.org$/.test(url.pathname)) {
			const value = await fs.readFile(url)
			const file = await compile(new VFile({ value, path: url }))
			if (file.messages.length > 0) {
				console.error(reporter(file))
			}

			let source = String(file)
			source +=
				'\n//# sourceMappingURL=data:application/json;base64,' +
				Buffer.from(JSON.stringify(file.map)).toString('base64') +
				'\n'

			return {
				format: 'module',
				shortCircuit: true,
				source
			}
		}

		return nextLoad(href, context)
	}
}

/**
 * @param {Options} options
 */
function configure(options) {
	const processor = createProcessor({
		development: true,
		...options,
		SourceMapGenerator
	})

	/**
	 * @param {import('vfile').Compatible} file
	 */
	function compile(file) {
		return processor.process(file)
	}

	return { compile }
}

const defaultLoader = createLoader()

/**
 * Pass options to the loader.
 */
export const initialize = defaultLoader.initialize

/**
 * Load `file:` URLs to org files.
 */
export const load = defaultLoader.load


================================================
FILE: packages/node-loader/package.json
================================================
{
	"name": "@orgajs/node-loader",
	"version": "1.1.5",
	"description": "",
	"type": "module",
	"files": [
		"lib",
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"exports": "./index.js",
	"scripts": {},
	"keywords": [],
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"repository": {
		"type": "git",
		"url": "https://github.com/orgapp/orgajs.git",
		"directory": "packages/node-loader"
	},
	"dependencies": {
		"@orgajs/orgx": "workspace:^",
		"source-map": "^0.7.4",
		"vfile": "^6.0.3",
		"vfile-reporter": "^8.1.1"
	},
	"devDependencies": {
		"@types/node": "^25.3.2"
	}
}


================================================
FILE: packages/oast-to-hast/.projectile
================================================


================================================
FILE: packages/oast-to-hast/CHANGELOG.md
================================================
# Change Log

## 4.5.3

### Patch Changes

- 850bcf9: fix: use native anchor for external links to prevent wouter pushState SecurityError

## 4.5.2

### Patch Changes

- be20652: expose rehypePlugins in orga-build

## 4.5.1

### Patch Changes

- bd2365a: fix types and linting
- Updated dependencies [bd2365a]
  - orga@4.7.1

## 4.5.0

### Minor Changes

- 761c484: Preserve inline markup in quote and center blocks.

### Patch Changes

- Updated dependencies [761c484]
  - orga@4.7.0

## 4.4.3

### Patch Changes

- 68430c7: fix newline in paragraph

## 4.4.2

### Patch Changes

- d8da621: fix invalid html structure with image/video

## 4.4.1

### Patch Changes

- 20f5a03: fix: render video links as `<video controls>` elements

## 4.4.0

### Minor Changes

- da20dcc: bug fix: correct definition list HTML output

## 4.3.3

### Patch Changes

- Updated dependencies [a53cfea]
  - orga@4.6.0

## 4.3.2

### Patch Changes

- Updated dependencies [60ad38f]
  - orga@4.5.1

## 4.3.1

### Patch Changes

- 7c3c600: fix react resolve issue

## 4.3.0

### Minor Changes

- 188d30f: - migrate most of modules to js
  - fix types during the process
  - remove unmaintained modules

### Patch Changes

- Updated dependencies [188d30f]
  - orga@4.5.0

## 4.2.0

### Minor Changes

- d8861c2: update unified ecosystem

### Patch Changes

- Updated dependencies [d8861c2]
  - orga@4.4.0

## 4.1.3

### Patch Changes

- ab38e4b0: add ability to customize <a>'s target attribute

## 4.1.2

### Patch Changes

- Updated dependencies [7cfff79a]
  - orga@4.3.0

## 4.1.1

### Patch Changes

- Updated dependencies [ac322714]
  - orga@4.2.0

## 4.1.0

### Minor Changes

- 4d8efbb7: Add increamental parsing ability for the editor.

### Patch Changes

- Updated dependencies [4d8efbb7]
  - orga@4.1.0

## 4.0.0

### Major Changes

- 176a3b5d: # Migrate most of the ecosystem to ESM

  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.

  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.

  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.

  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!

### Patch Changes

- Updated dependencies [176a3b5d]
  - orga@4.0.0

## 3.2.1

### Patch Changes

- eeccc870: - get image links out of paragraph
  - some other minor fixes
- Updated dependencies [eeccc870]
  - orga@3.2.1

## 3.2.0

### Minor Changes

- 6c1ddb9f: add latex support

### Patch Changes

- Updated dependencies [6c1ddb9f]
  - orga@3.2.0

## 3.1.6

### Patch Changes

- Updated dependencies [4bde5155]
  - orga@3.1.5

## 3.1.5

### Patch Changes

- ae83a3b0: - affiliated keyword support for list
  - `HTML_CONTAINER_CLASS` support in properties drawer
  - remove complex regex from inline parsing
- Updated dependencies [ae83a3b0]
  - orga@3.1.4

## 3.1.4

### Patch Changes

- Updated dependencies [09a3b5c6]
  - orga@3.1.3

## 3.1.3

### Patch Changes

- Updated dependencies [594bf16b]
  - orga@3.1.2

## 3.1.2

### Patch Changes

- 19156b8a: inject props into layout
- Updated dependencies [19156b8a]
  - orga@3.1.1

## 3.1.1

### Patch Changes

- 7f209ff5: oast-to-hast: add `all` function to context

## 3.1.0

### Minor Changes

- eeea0c54: introduce new token: empty line

### Patch Changes

- Updated dependencies [eeea0c54]
  - orga@3.1.0

## 3.0.1

### Patch Changes

- 6ed76057: # rename gatsby themes

  - gatsby-theme-orga -> gatsby-theme-orga-posts-core
  - gatsby-theme-blorg -> gatsby-theme-orga-posts

  # add example projects

  - gatsby-posts
  - gatsby-posts-core

- 759e6149: # Bug Fixes

  - fix lexer for parsing headline with todo keyword
  - fix properties drawer issue
  - fix orga-theme-ui-preset package
  - fix gatsby-transformer-orga & gatsby-theme-blorg

  # Improved Playground

  - add `tokens` view
  - show node type in tree views

- Updated dependencies [6ed76057]
- Updated dependencies [759e6149]
  - orga@3.0.1

## 3.0.0

### Major Changes

- 8b02d10: # Features

  - more powerful and flexible lexer and parser
  - webpack support
  - `jsx` support
  - better code block rendering
  - better image processing in gatsby
  - updated examples
  - tons of bug fixes
  - brand new `gatsby-plugin-orga`

### Patch Changes

- Updated dependencies [8b02d10]
  - orga@3.0.0

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [2.6.0](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.5.0...v2.6.0) (2021-08-28)

### Bug Fixes

- remove prepublish step individually ([a75a6a9](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/a75a6a9606421b66b6ef69b28e3fcb03a5ee282a))
- **website:** better code block ([9d5b3a2](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/9d5b3a2d554672d22523727e89b2b5c60dc6233d))

### Features

- add jsx support ([0d22499](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/0d224990b412e064ebf6816608eea6766f93d60c))

# [2.5.0](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.9...v2.5.0) (2021-08-27)

### Features

- add jsx support ([0d22499](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/commit/0d224990b412e064ebf6816608eea6766f93d60c))

## [2.4.9](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.8...v2.4.9) (2021-07-13)

**Note:** Version bump only for package oast-to-hast

## [2.4.8](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.7...v2.4.8) (2021-04-26)

**Note:** Version bump only for package oast-to-hast

## [2.4.7](https://github.com/orgapp/orgajs/tree/master/packages/oast-to-hast/compare/v2.4.6...v2.4.7) (2021-04-26)

**Note:** Version bump only for package oast-to-hast


================================================
FILE: packages/oast-to-hast/LICENSE.org
================================================
The MIT License (MIT)

Copyright (c) 2015 gatsbyjs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.



================================================
FILE: packages/oast-to-hast/index.js
================================================
/**
 * @typedef {import('./lib/index.js').Options} Options
 */

export { handlers as defaultHandlers } from './lib/handlers/index.js'

export { toHast, toHast as default } from './lib/index.js'


================================================
FILE: packages/oast-to-hast/lib/handlers/block.js
================================================
import { parseHtml } from './html.js'

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Block} node
 * @returns {import('hast').Element|undefined}
 */
export function block(state, node) {
	const name = node.name.toLowerCase()

	/**
	 * Preserve inline markup for block types whose content is parsed into
	 * block children by orga. Fallback to the raw value for externally-provided
	 * trees that omit `children`.
	 */
	const parsedChildren = state.all(node)

	if (name === 'src') {
		const lang = node.params?.[0]
			? `language-${node.params[0]}`
			: 'language-undefined'
		return state.patch(node, {
			type: 'element',
			tagName: 'pre',
			properties: {},
			children: [
				{
					type: 'element',
					tagName: 'code',
					properties: { className: [lang] },
					children: [
						{
							type: 'text',
							value: node.value
						}
					]
				}
			]
		})
	}

	if (name === 'quote') {
		return state.patch(node, {
			type: 'element',
			tagName: 'blockquote',
			properties: {},
			children:
				parsedChildren.length > 0
					? parsedChildren
					: [
							{
								type: 'text',
								value: node.value
							}
						]
		})
	}

	if (name === 'center') {
		return state.patch(node, {
			type: 'element',
			tagName: 'center',
			properties: {},
			children:
				parsedChildren.length > 0
					? parsedChildren
					: [
							{
								type: 'text',
								value: node.value
							}
						]
		})
	}

	if (name === 'export') {
		if (node.params[0].toLowerCase() === 'html') {
			return state.patch(node, parseHtml(node.value))
		}

		return {
			// @ts-expect-error: this is a special passthrough
			type: (node.params[0] || 'raw').toLowerCase(),
			value: node.value
		}
	}

	if (name === 'comment') {
		return undefined
	}

	return state.patch(node, {
		type: 'element',
		tagName: 'pre',
		properties: { className: [name] },
		children: [
			{
				type: 'text',
				value: node.value
			}
		]
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/document.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Document} node
 * @returns {import('hast').Root}
 */
export function document(state, node) {
	return {
		type: 'root',
		data: node.properties,
		children: state.all(node)
	}
}


================================================
FILE: packages/oast-to-hast/lib/handlers/footnote.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').FootnoteReference} node
 * @returns {import('hast').Element}
 */
export function footnoteRef(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'sup',
		properties: { id: `fnref-${node.label}` },
		children: [
			{
				type: 'element',
				tagName: 'a',
				properties: { href: `#fn-${node.label}` },
				children: [{ type: 'text', value: node.label }]
			}
		]
	})
}

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Footnote} node
 * @returns {import('hast').Element}
 */
export function footnote(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'div',
		properties: {
			id: `fn-${node.label}`,
			className: ['footnote'],
			dataLabel: node.label
		},
		children: state.all(node)
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/headline.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Headline} node
 * @returns {import('hast').Element}
 */
export function headline(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: `h${node.level}`,
		properties: {},
		children: state.all(node)
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/hr.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').HorizontalRule} node
 * @returns {import('hast').Element}
 */
export function hr(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'hr',
		properties: {},
		children: []
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/html.js
================================================
import { fromHtml } from 'hast-util-from-html'

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').HTML} node
 * @returns {import('hast').Element}
 */
export function html(state, node) {
	return state.patch(node, parseHtml(node.value))
}

/**
 * @param {string} html
 * @returns {import('hast').Element}
 */
export function parseHtml(html) {
	const hast = fromHtml(html, { fragment: true })

	/** @type {import('hast').Element} */
	const result = {
		type: 'element',
		tagName: 'div',
		properties: {},
		children: []
	}

	hast.children.forEach((child) => {
		if (
			child.type === 'element' ||
			child.type === 'text' ||
			child.type === 'comment'
		) {
			result.children.push(child)
		}
	})

	return result
}


================================================
FILE: packages/oast-to-hast/lib/handlers/index.js
================================================
import { block } from './block.js'
import { document } from './document.js'
import { footnote, footnoteRef } from './footnote.js'
import { headline } from './headline.js'
import { hr } from './hr.js'
import { html } from './html.js'
import { keyword } from './keyword.js'
import { latex } from './latex.js'
import { link } from './link.js'
import { checkbox, list, item as listItem } from './list.js'
import { newline } from './newline.js'
import { paragraph } from './paragraph.js'
import { section } from './section.js'
import {
	table,
	cell as tableCell,
	hr as tableHr,
	row as tableRow
} from './table.js'
import { text } from './text.js'

/**
 * Default handlers for nodes.
 *
 * @satisfies {import('../state.js').Handlers}
 */
export const handlers = {
	document,
	keyword,
	headline,
	section,
	paragraph,
	text,
	block,
	latex,
	link,
	list,
	'list.item': listItem,
	'list.item.tag': ignore,
	'list.item.bullet': ignore,
	'list.item.checkbox': checkbox,
	'link.path': ignore,
	table,
	'table.row': tableRow,
	'table.cell': tableCell,
	'table.hr': tableHr,
	html,
	jsx: passThrough,
	drawer: ignore,
	priority: ignore,
	planning: ignore,
	footnote,
	'footnote.reference': footnoteRef,
	hr,
	newline
}

/** @type {import('../state.js').Handler} */
function ignore() {
	return undefined
}

/** @type {import('../state.js').Handler} */
function passThrough(_, node) {
	return node
}


================================================
FILE: packages/oast-to-hast/lib/handlers/keyword.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Keyword} node
 * @returns {import('hast').Element|undefined}
 */
export function keyword(state, node) {
	if (node.key.toLowerCase() === 'select_tags') {
		const tags = node.value
			.split(',')
			.map((tag) => tag.trim())
			.filter(Boolean)
		state.options.selectTags = tags
	}

	return undefined
}


================================================
FILE: packages/oast-to-hast/lib/handlers/latex.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Latex} node
 * @returns {import('hast').Element}
 */
export function latex(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'div',
		properties: { className: ['math-display'] },
		children: [
			{
				type: 'text',
				value: node.value
			}
		]
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/link.js
================================================
/**
 * @import { Element } from 'hast'
 */

import mime from 'mime'

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Link} node
 * @returns {Element}
 */
export function link(state, node) {
	const type = mime.getType(node.path.value)

	if (type?.startsWith('image')) {
		/** @type {Element} */
		const image = {
			type: 'element',
			tagName: 'img',
			properties: {
				src: node.path.value,
				target: state.options.linkTarget
			},
			children: []
		}
		/** @type {Element|null} */
		let cap = null
		const c = node.attributes.caption
		if (c) {
			cap = {
				type: 'element',
				tagName: 'figcaption',
				properties: {},
				children: [
					{
						type: 'text',
						value: `${c}`
					}
				]
			}
		} else if (node.children.length > 0) {
			cap = {
				type: 'element',
				tagName: 'figcaption',
				properties: {},
				children: state.all(node)
			}
		}
		if (cap) {
			return state.patch(node, {
				type: 'element',
				tagName: 'figure',
				properties: {},
				children: [image, cap]
			})
		}

		return state.patch(node, image)
	}

	if (type?.startsWith('video')) {
		/** @type {Element} */
		const video = {
			type: 'element',
			tagName: 'video',
			properties: {
				src: node.path.value,
				controls: true
			},
			children: []
		}
		/** @type {Element|null} */
		let cap = null
		const c = node.attributes.caption
		if (c) {
			cap = {
				type: 'element',
				tagName: 'figcaption',
				properties: {},
				children: [
					{
						type: 'text',
						value: `${c}`
					}
				]
			}
		} else if (node.children.length > 0) {
			cap = {
				type: 'element',
				tagName: 'figcaption',
				properties: {},
				children: state.all(node)
			}
		}
		if (cap) {
			return state.patch(node, {
				type: 'element',
				tagName: 'figure',
				properties: {},
				children: [video, cap]
			})
		}

		return state.patch(node, video)
	}
	return state.patch(node, {
		type: 'element',
		tagName: 'a',
		properties: {
			href: state.options.linkHref(node),
			target: state.options.linkTarget
		},
		children: state.all(node)
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/list.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').List} node
 * @returns {import('hast').Element}
 */
export function list(state, node) {
	let tagName = node.ordered ? 'ol' : 'ul'
	if (node.children.every((i) => i.type !== 'list.item' || i.tag)) {
		tagName = 'dl'
	}

	const properties = state.getAttrHtml(node)

	return state.patch(node, {
		type: 'element',
		tagName: tagName,
		properties: properties ?? {},
		children: state.all(node)
	})
}

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').ListItem} node
 * @param {import('orga').Parent | undefined} parent
 * @returns {import('hast').ElementContent | import('hast').ElementContent[]}
 */
export function item(state, node, parent) {
	if (node.tag) {
		/** @type {import('hast').Element[]} */
		const dtdd = [
			{
				type: 'element',
				tagName: 'dt',
				properties: {},
				children: [{ type: 'text', value: node.tag }]
			},
			{
				type: 'element',
				tagName: 'dd',
				properties: {},
				children: state.all(node)
			}
		]

		const allTagged = parent?.children?.every(
			(i) => i.type !== 'list.item' || i.tag
		)

		if (allTagged) {
			// Pure definition list: return [<dt>, <dd>] to be flattened into <dl>
			return dtdd
		}

		// Definition item inside a mixed list: wrap in <li><dl>…</dl></li>
		return state.patch(node, {
			type: 'element',
			tagName: 'li',
			properties: {},
			children: [
				{
					type: 'element',
					tagName: 'dl',
					properties: {},
					children: dtdd
				}
			]
		})
	}

	return state.patch(node, {
		type: 'element',
		tagName: 'li',
		properties: {},
		children: state.all(node)
	})
}

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').ListItemCheckbox} node
 * @returns {import('hast').Element}
 */
export function checkbox(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'input',
		properties: {
			type: 'checkbox',
			checked: node.checked,
			disabled: true
		},
		children: []
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/newline.js
================================================
/**
 * @param {import('../state.js').State} _state
 * @param {import('orga').Newline} _node
 * @param {import('orga').Parent | undefined} parent
 * @returns {import('hast').Text | undefined}
 */
export function newline(_state, _node, parent) {
	// In Org paragraphs, a single source newline is a soft break. For HTML
	// output, normalize it to a space so text remains readable.
	if (parent?.type === 'paragraph') {
		return { type: 'text', value: ' ' }
	}

	return undefined
}


================================================
FILE: packages/oast-to-hast/lib/handlers/paragraph.js
================================================
/**
 * Block-level HTML elements that are not allowed as descendants of <p>.
 * When a paragraph contains any of these, we must avoid wrapping in <p>.
 *
 * @see https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element
 */
const BLOCK_TAGS = new Set([
	'address',
	'article',
	'aside',
	'blockquote',
	'details',
	'dialog',
	'dd',
	'div',
	'dl',
	'dt',
	'fieldset',
	'figcaption',
	'figure',
	'footer',
	'form',
	'h1',
	'h2',
	'h3',
	'h4',
	'h5',
	'h6',
	'header',
	'hgroup',
	'hr',
	'li',
	'main',
	'nav',
	'ol',
	'p',
	'pre',
	'section',
	'summary',
	'table',
	'ul'
])

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Paragraph} node
 * @returns {import('hast').Element}
 */
export function paragraph(state, node) {
	const properties = state.getAttrHtml(node)
	const children = state.all(node)

	// If any child is a block-level element (e.g. a <figure> from a media link
	// with caption), wrapping in <p> produces invalid HTML and causes hydration
	// errors in React. Unwrap single block children; use <div> for mixed content.
	const hasBlock = children.some(
		(child) =>
			child.type === 'element' &&
			BLOCK_TAGS.has(/** @type {import('hast').Element} */ (child).tagName)
	)

	if (hasBlock) {
		if (children.length === 1) {
			return /** @type {import('hast').Element} */ (children[0])
		}
		return state.patch(node, {
			type: 'element',
			tagName: 'div',
			properties: properties ?? {},
			children
		})
	}

	return state.patch(node, {
		type: 'element',
		tagName: 'p',
		properties: properties ?? {},
		children
	})
}


================================================
FILE: packages/oast-to-hast/lib/handlers/section.js
================================================
/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Section} node
 * @returns {import('hast').Element|undefined}
 */
export function section(state, node) {
	const headline = node.children.find((n) => n.type === 'headline')

	if (headline) {
		if (shouldSkip(state.options, headline.tags || [])) {
			return undefined
		}
	}

	let className = 'section'
	const drawer = node.children.find((n) => n.type === 'drawer')
	if (drawer && drawer.name === 'PROPERTIES') {
		const lines = drawer.value.split('\n')
		lines.forEach((line) => {
			const m = line.match(/:(\w+):(.*)$/)
			if (m && m[1].toUpperCase() === 'HTML_CONTAINER_CLASS') {
				className = `${className} ${m[2].trim()}`
			}
		})
	}

	return state.patch(node, {
		type: 'element',
		tagName: 'div',
		properties: { className: className.split(/\s+/).filter(Boolean) },
		children: state.all(node)
	})
}

/**
 * @param {import('../state.js').Config} config
 * @param {string[]} tags
 * @returns {boolean}
 */
function shouldSkip({ selectTags = [], excludeTags = [] }, tags) {
	if (selectTags.length > 0) {
		return !tags.some((tag) => selectTags.includes(tag))
	}

	if (excludeTags.length > 0) {
		return tags.some((tag) => excludeTags.includes(tag))
	}

	return false
}


================================================
FILE: packages/oast-to-hast/lib/handlers/table.js
================================================
/**
 * @import {Element,ElementContent} from 'hast'
 * @import {Table,TableCell,TableRow} from 'orga'
 * @import {State} from '../state.js'
 */

/**
 * @param {State} state
 * @param {Table} node
 * @returns {Element}
 */
export function table(state, node) {
	const rows = state.all(node)
	const hrIndex = rows.findIndex(
		(row) => row.type === 'element' && row.tagName === 'hr'
	)

	/** @type {ElementContent[]} */
	const headRows = []
	/** @type {ElementContent[]} */
	const bodyRows = []
	rows.forEach((row, i) => {
		if (i < hrIndex) {
			headRows.push(row)
		} else if (i > hrIndex) {
			bodyRows.push(row)
		}
	})

	/** @type {ElementContent[]} */
	const tableContent = []

	if (headRows.length > 0) {
		tableContent.push({
			type: 'element',
			tagName: 'thead',
			properties: {},
			children: headRows
		})
	}

	if (bodyRows.length > 0) {
		tableContent.push({
			type: 'element',
			tagName: 'tbody',
			properties: {},
			children: bodyRows
		})
	}

	const caption = node.attributes.caption
	if (caption) {
		tableContent.push({
			type: 'element',
			tagName: 'caption',
			properties: {},
			children: [{ type: 'text', value: `${caption}` }]
		})
	}

	return state.patch(node, {
		type: 'element',
		tagName: 'table',
		properties: {},
		children: tableContent
	})
}

/**
 * @param {State} state
 * @param {TableRow} node
 * @returns {Element}
 */
export function row(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'tr',
		properties: {},
		children: state.all(node)
	})
}

/**
 * @param {State} state
 * @param {TableCell} node
 * @returns {Element}
 */
export function cell(state, node) {
	return state.patch(node, {
		type: 'element',
		tagName: 'td',
		properties: {},
		children: state.all(node)
	})
}

/**
 * @returns {Element}
 */
export function hr() {
	return {
		type: 'element',
		tagName: 'hr',
		properties: {},
		children: []
	}
}


================================================
FILE: packages/oast-to-hast/lib/handlers/text.js
================================================
/**
 * @import {Element,Text} from 'hast'
 *
 */

const wrapper = {
	bold: 'strong',
	italic: 'i',
	code: 'code',
	verbatim: 'code',
	underline: 'u',
	strikeThrough: 'del',
	math: 'span'
}

/**
 * @param {import('../state.js').State} state
 * @param {import('orga').Text} node
 * @returns {Element|Text}
 */
export function text(state, node) {
	/** @type {Element|Text} */
	let e = {
		type: 'text',
		value: node.value
	}
	if (node.style) {
		e = {
			type: 'element',
			tagName: wrapper[node.style],
			properties: {},
			children: [e]
		}
		if (node.style === 'math') {
			e.properties.className = ['math-inline']
		}
	}
	return state.patch(node, e)
}


================================================
FILE: packages/oast-to-hast/lib/index.js
================================================
/**
 * @typedef {import('hast').Nodes} HastNodes
 * @typedef {import('orga').Nodes} OastNodes
 * @typedef {Partial<import('./state.js').Config> | null | undefined} Options
 */

import { createState } from './state.js'

/**
 * @param {OastNodes} tree
 *   oast tree.
 * @param {Options} [options]
 *   Configuration (optional).
 * @returns {HastNodes}
 *   hast tree.
 */
export function toHast(tree, options = {}) {
	const state = createState(tree, options)

	const node = state.one(tree)
	if (Array.isArray(node)) {
		return { type: 'root', children: node }
	}
	// if (tree.type === 'document') {
	// 	return {
	// 		type: 'root',
	// 		data: tree.properties,
	// 		children: node ? [node] : [],
	// 	}
	// }
	return node || { type: 'root', children: [] }
}


================================================
FILE: packages/oast-to-hast/lib/state.js
================================================
/**
 * @typedef {import('hast').Nodes} HastNodes
	 @import {ElementContent as HastElementContent,Root as HastRoot} from 'hast'
 * @typedef {import('orga').Parent} OastParent
 * @typedef {import('orga').Nodes} OastNodes
 */

/**
 * @typedef {Object} Config
 * @property {Handlers} handlers
 * @property {string} linkTarget
 * @property {(link: import('orga').Link) => string} linkHref
 * @property {string[]} selectTags=[]
 * @property {string[]} excludeTags=['noexport']
 */

/**
 * @typedef {ReturnType<typeof createState>} State
 *
 * @callback Handler
 * @param {State} state
 * @param {any} node
 * @param {OastParent | undefined} parent
 * @returns {Array<HastElementContent> | HastElementContent | HastRoot | undefined}
 *   hast node.
 *
 * @typedef {Partial<Record<OastNodes['type'], Handler>>} Handlers
 *   Handle nodes.
 */

import { position } from 'unist-util-position'
import { handlers as defaultHandlers } from './handlers/index.js'

/**
 * @param {OastNodes} _tree
 * @param {Partial<Config> | null | undefined} [options = {}]
 */
export function createState(_tree, options = {}) {
	/** @type {Handlers} */
	let handlers = { ...defaultHandlers }
	if (options?.handlers) {
		handlers = { ...handlers, ...options.handlers }
	}

	const state = {
		one,
		all,
		handlers,
		getAttrHtml,
		patch,
		/** @type {Config} */
		options: {
			handlers,
			linkTarget: '_self',
			selectTags: [],
			excludeTags: ['noexport'],
			linkHref: defaultLinkHref,
			...options
		}
	}

	return state

	/**
	 * @param {OastNodes} parent
	 * @returns {Array<HastElementContent>}
	 */
	function all(parent) {
		/** @type {Array<HastElementContent>} */
		const values = []
		if ('children' in parent) {
			parent.children.forEach((node) => {
				const result = one(node, parent)
				if (!result) {
					return
				}
				if (Array.isArray(result)) {
					values.push(...result)
				} else {
					// @ts-expect-error: can never be Root here
					values.push(result)
				}
			})
		}
		return values
	}

	/**
	 * @param {OastNodes} node
	 * @param {OastParent | undefined} parent
	 */
	function one(node, parent = undefined) {
		const handle = handlers[node.type] || unkownHandler
		return handle(state, node, parent)
	}

	/**
	 * @param {OastNodes} node
	 * @returns {Record<string, string> | undefined}
	 */
	function getAttrHtml(node) {
		if ('properties' in node && 'attr_html' in node.properties) {
			const a = node.properties.attr_html
			if (typeof a === 'string') return
			if (Array.isArray(a)) return
			return a
		}
	}

	/**
	 * @template {HastNodes} T
	 * @param {OastNodes} from
	 * @param {T} to
	 * @returns {T}
	 */
	function patch(from, to) {
		if (from.position) {
			to.position = position(from)
		}
		return to
	}
}

/**
 * @param {import('orga').Link} link
 * @returns {string}
 */
function defaultLinkHref(link) {
	const protocol = link.path.protocol
	if (!protocol || protocol === 'internal' || protocol === 'file') {
		return link.path.value
	}
	if (protocol === 'http' || protocol === 'https') {
		return link.path.value
	}
	return `${protocol}:${link.path.value}`
}

/** @type {Handler} */
function unkownHandler(state, node) {
	if (node?.children) {
		return {
			type: 'element',
			tagName: 'div',
			properties: {},
			children: state.all(node)
		}
	} else if ('value' in node) {
		return { type: 'text', value: `${node.value}` }
	}
	return undefined
}


================================================
FILE: packages/oast-to-hast/package.json
================================================
{
	"name": "oast-to-hast",
	"version": "4.5.3",
	"description": "Transform OAST to HAST",
	"files": [
		"lib",
		"index.js",
		"index.d.ts",
		"index.d.ts.map"
	],
	"exports": "./index.js",
	"type": "module",
	"author": "Xiaoxing Hu <hi@xiaoxing.dev>",
	"license": "MIT",
	"repository": "https://github.com/orgapp/orgajs/tree/main/packages/oast-to-hast",
	"dependencies": {
		"hast-util-from-html": "^2.0.3",
		"mime": "^3.0.0",
		"orga": "workspace:^",
		"parse5": "^7.1.2",
		"unist-util-position": "^5.0.0"
	},
	"scripts": {
		"test": "node --test tests/*.js"
	},
	"devDependencies": {
		"@types/hast": "^3.0.4",
		"@types/mime": "^3.0.1",
		"@types/unist": "^3.0.3",
		"hastscript": "^9.0.0"
	}
}


================================================
FILE: packages/oast-to-hast/tests/block.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { h } from 'hastscript'
import { parse } from 'orga'
import { toHast } from '../index.js'

test('quote block preserves inline markup', () => {
	const oast = parse(`#+BEGIN_QUOTE
Be *bold*, and if you must, be /italic/.
#+END_QUOTE
`)

	const hast = removePosition(toHast(oast))

	assert.deepEqual(hast, {
		type: 'root',
		data: {},
		children: [
			h('blockquote', [
				'Be ',
				h('strong', 'bold'),
				', and if you must, be ',
				h('i', 'italic'),
				'.'
			])
		]
	})
})

function removePosition(node) {
	if (!node || typeof node !== 'object') return node
	if (Array.isArray(node)) return node.map(removePosition)
	const result = {}
	for (const [key, value] of Object.entries(node)) {
		if (key === 'position') continue
		result[key] = removePosition(value)
	}
	return result
}


================================================
FILE: packages/oast-to-hast/tests/classname.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { parse } from 'orga'
import { toHast } from '../index.js'

test('src blocks emit code.className as token array', () => {
	const oast = parse(`#+begin_src javascript
console.log('ok')
#+end_src`)
	const hast = toHast(oast)
	const code = hast.children[0]?.children?.[0]

	assert.deepEqual(code?.tagName, 'code')
	assert.deepEqual(code?.properties?.className, ['language-javascript'])
})

test('sections emit div.className as token array', () => {
	const oast = parse(`* Heading
:PROPERTIES:
:HTML_CONTAINER_CLASS: foo bar
:END:
Body`)
	const hast = toHast(oast)
	const section = hast.children[0]

	assert.deepEqual(section?.tagName, 'div')
	assert.deepEqual(section?.properties?.className, ['section', 'foo', 'bar'])
})


================================================
FILE: packages/oast-to-hast/tests/heading.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { h } from 'hastscript'
import { toHast } from '../index.js'

test('heading', async () => {
	const hast = toHast({
		type: 'headline',
		level: 3,
		children: [{ type: 'text', value: 'Hello' }]
	})

	assert.deepEqual(hast, h('h3', 'Hello'))
})


================================================
FILE: packages/oast-to-hast/tests/list.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { h } from 'hastscript'
import { toHast } from '../index.js'

test('regular unordered list', () => {
	const hast = toHast({
		type: 'list',
		ordered: false,
		indent: 0,
		children: [
			{
				type: 'list.item',
				indent: 0,
				children: [{ type: 'text', value: 'item one' }]
			},
			{
				type: 'list.item',
				indent: 0,
				children: [{ type: 'text', value: 'item two' }]
			}
		]
	})

	assert.deepEqual(hast, h('ul', [h('li', 'item one'), h('li', 'item two')]))
})

test('pure definition list produces <dl> with flat <dt>/<dd> pairs (no <div> wrapper)', () => {
	const hast = toHast({
		type: 'list',
		ordered: false,
		indent: 0,
		children: [
			{
				type: 'list.item',
				indent: 0,
				tag: 'word',
				children: [{ type: 'text', value: 'description.' }]
			},
			{
				type: 'list.item',
				indent: 0,
				tag: 'another',
				children: [{ type: 'text', value: 'definition.' }]
			}
		]
	})

	assert.deepEqual(
		hast,
		h('dl', [
			h('dt', 'word'),
			h('dd', 'description.'),
			h('dt', 'another'),
			h('dd', 'definition.')
		])
	)
})

test('pure definition list followed by a paragraph still produces <dl>', () => {
	// The parser appends a trailing newline node as a child of the list when
	// followed by a blank line + paragraph. It must not be mistaken for a
	// non-tagged item.
	const hast = toHast({
		type: 'list',
		ordered: false,
		indent: 0,
		children: [
			{
				type: 'list.item',
				indent: 0,
				tag: 'hello',
				children: [{ type: 'text', value: 'this is greeting.' }]
			},
			{
				type: 'list.item',
				indent: 0,
				tag: 'world',
				children: [{ type: 'text', value: 'this is the world.' }]
			},
			{ type: 'newline' }
		]
	})

	assert.deepEqual(
		hast,
		h('dl', [
			h('dt', 'hello'),
			h('dd', 'this is greeting.'),
			h('dt', 'world'),
			h('dd', 'this is the world.')
		])
	)
})

test('mixed list wraps definition items as <li><dl><dt>/<dd></dl></li>', () => {
	const hast = toHast({
		type: 'list',
		ordered: false,
		indent: 0,
		children: [
			{
				type: 'list.item',
				indent: 0,
				children: [{ type: 'text', value: 'item one' }]
			},
			{
				type: 'list.item',
				indent: 0,
				tag: 'word',
				children: [{ type: 'text', value: 'definition goes here.' }]
			}
		]
	})

	assert.deepEqual(
		hast,
		h('ul', [
			h('li', 'item one'),
			h('li', [h('dl', [h('dt', 'word'), h('dd', 'definition goes here.')])])
		])
	)
})


================================================
FILE: packages/oast-to-hast/tests/paragraph.js
================================================
import * as assert from 'node:assert'
import test from 'node:test'
import { h } from 'hastscript'
import { toHast } from '../index.js'

test('paragraph with text', async () => {
	const hast = toHast({
		type: 'paragraph',
		children: [{ type: 'text', value: 'Hello' }]
	})

	assert.deepEqual(hast, h('p', 'Hello'))
})

test('paragraph newline is rendered as a space', async () => {
	const hast = toHast({
		type: 'paragraph',
		children: [
			{ type: 'text', value: 'foo' },
			{ type: 'newline' },
			{ type: 'text', value: 'bar' }
		]
	})

	assert.deepEqual(hast, h('p', ['foo', ' ', 'bar']))
})

test('paragraph mailto link keeps protocol in href', async () => {
	const hast = toHast({
		type: 'paragraph',
		children: [
			{
				type: 'link',
				path: { protocol: 'mailto', val
Download .txt
gitextract_ms15wv5a/

├── .changeset/
│   ├── README.md
│   └── config.json
├── .editorconfig
├── .eslintignore
├── .github/
│   ├── FUNDING.yml
│   └── workflows/
│       ├── ci.yml
│       ├── release.yml
│       └── website.yml
├── .gitignore
├── .prettierignore
├── .prettierrc
├── CHANGELOG.md
├── CONTRIBUTING.org
├── LICENSE.org
├── README.org
├── biome.json
├── docs/
│   ├── .gitignore
│   ├── _components.tsx
│   ├── _layout.tsx
│   ├── _snippets/
│   │   └── hey.org
│   ├── advanced/
│   │   ├── _layout.tsx
│   │   ├── api.org
│   │   ├── ast.org
│   │   ├── index.org
│   │   └── latex.org
│   ├── contribute.org
│   ├── guides/
│   │   ├── _layout.tsx
│   │   ├── astro.org
│   │   ├── gatsby.org
│   │   ├── index.org
│   │   ├── next.org
│   │   ├── orga-build.org
│   │   └── webpack.org
│   ├── index.org
│   ├── playground.tsx
│   ├── style.css
│   └── tsconfig.json
├── examples/
│   ├── README.org
│   ├── build/
│   │   ├── index.org
│   │   ├── more.org
│   │   ├── package.json
│   │   └── test-content.tsx
│   ├── editor/
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── content.org
│   │   ├── index.html
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── main.ts
│   │   │   └── style.css
│   │   └── tsconfig.json
│   ├── getting-started/
│   │   ├── .gitignore
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   └── package.json
│   └── webpack/
│       ├── .babelrc
│       ├── CHANGELOG.md
│       ├── README.org
│       ├── package.json
│       ├── public/
│       │   └── index.html
│       ├── src/
│       │   ├── box.js
│       │   ├── hello.org
│       │   └── index.js
│       └── webpack.config.mjs
├── orga.config.js
├── package.json
├── packages/
│   ├── astro/
│   │   └── README.org
│   ├── codemirror-lang/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── editor/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── actions/
│   │   │   │   ├── fold.js
│   │   │   │   ├── shift.js
│   │   │   │   ├── todo.js
│   │   │   │   └── utils.js
│   │   │   ├── editor.js
│   │   │   ├── extensions/
│   │   │   │   └── cleanup.js
│   │   │   ├── settings.js
│   │   │   ├── setup.js
│   │   │   └── theme.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── esbuild/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── lezer/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── context.js
│   │   │   ├── fragments.js
│   │   │   ├── handlers.js
│   │   │   ├── index.js
│   │   │   ├── nodes.js
│   │   │   ├── oast-to-lezer.js
│   │   │   ├── tree.js
│   │   │   └── types.ts
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── compare-tree.js
│   │   │   └── incremental.test.js
│   │   └── tsconfig.json
│   ├── loader/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.cjs
│   │   ├── index.d.ts
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   └── tests/
│   │       ├── compiler.js
│   │       ├── example.md
│   │       ├── fixture.org
│   │       └── loader.test.js
│   ├── metadata/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   └── test.js
│   │   └── tsconfig.json
│   ├── next/
│   │   └── README.org
│   ├── node-loader/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── oast-to-hast/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── handlers/
│   │   │   │   ├── block.js
│   │   │   │   ├── document.js
│   │   │   │   ├── footnote.js
│   │   │   │   ├── headline.js
│   │   │   │   ├── hr.js
│   │   │   │   ├── html.js
│   │   │   │   ├── index.js
│   │   │   │   ├── keyword.js
│   │   │   │   ├── latex.js
│   │   │   │   ├── link.js
│   │   │   │   ├── list.js
│   │   │   │   ├── newline.js
│   │   │   │   ├── paragraph.js
│   │   │   │   ├── section.js
│   │   │   │   ├── table.js
│   │   │   │   └── text.js
│   │   │   ├── index.js
│   │   │   └── state.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── block.js
│   │   │   ├── classname.js
│   │   │   ├── heading.js
│   │   │   ├── list.js
│   │   │   └── paragraph.js
│   │   └── tsconfig.json
│   ├── oast-to-prose/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── handlers/
│   │   │   │   ├── block.js
│   │   │   │   ├── headline.js
│   │   │   │   ├── index.js
│   │   │   │   ├── link.js
│   │   │   │   ├── newline.js
│   │   │   │   ├── paragraph.js
│   │   │   │   ├── section.js
│   │   │   │   ├── stars.js
│   │   │   │   ├── tags.js
│   │   │   │   ├── text.js
│   │   │   │   └── todo.js
│   │   │   ├── index.js
│   │   │   ├── schema.js
│   │   │   └── state.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   └── text.js
│   │   └── tsconfig.json
│   ├── orga/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── __tests__/
│   │   │   │   ├── block/
│   │   │   │   │   ├── affiliated keyword.json
│   │   │   │   │   ├── affiliated keyword.org
│   │   │   │   │   ├── export.json
│   │   │   │   │   ├── export.org
│   │   │   │   │   ├── missing begin.json
│   │   │   │   │   ├── missing begin.org
│   │   │   │   │   ├── missing end.json
│   │   │   │   │   ├── missing end.org
│   │   │   │   │   ├── standard.json
│   │   │   │   │   └── standard.org
│   │   │   │   ├── footnote/
│   │   │   │   │   ├── multiline.json
│   │   │   │   │   ├── multiline.org
│   │   │   │   │   ├── standard.json
│   │   │   │   │   ├── standard.org
│   │   │   │   │   ├── stopped by empty lines.json
│   │   │   │   │   ├── stopped by empty lines.org
│   │   │   │   │   ├── stopped by footnote.json
│   │   │   │   │   ├── stopped by footnote.org
│   │   │   │   │   ├── stopped by headline.json
│   │   │   │   │   ├── stopped by headline.org
│   │   │   │   │   ├── with block.json
│   │   │   │   │   └── with block.org
│   │   │   │   ├── headline/
│   │   │   │   │   ├── broken drawer.json
│   │   │   │   │   ├── broken drawer.org
│   │   │   │   │   ├── drawers.json
│   │   │   │   │   ├── drawers.org
│   │   │   │   │   ├── keyword.json
│   │   │   │   │   ├── keyword.org
│   │   │   │   │   ├── nested.json
│   │   │   │   │   ├── nested.org
│   │   │   │   │   ├── planning.json
│   │   │   │   │   ├── planning.org
│   │   │   │   │   ├── with tags.json
│   │   │   │   │   └── with tags.org
│   │   │   │   ├── hr/
│   │   │   │   │   ├── standard.json
│   │   │   │   │   └── standard.org
│   │   │   │   ├── index.test.ts
│   │   │   │   ├── keyword/
│   │   │   │   │   ├── multiple todo.json
│   │   │   │   │   ├── multiple todo.org
│   │   │   │   │   ├── other.json
│   │   │   │   │   ├── other.org
│   │   │   │   │   ├── todo.json
│   │   │   │   │   └── todo.org
│   │   │   │   ├── latex/
│   │   │   │   │   ├── does not match.json
│   │   │   │   │   ├── does not match.org
│   │   │   │   │   ├── latex block.json
│   │   │   │   │   ├── latex block.org
│   │   │   │   │   ├── missing begin.json
│   │   │   │   │   ├── missing begin.org
│   │   │   │   │   ├── missing end.json
│   │   │   │   │   └── missing end.org
│   │   │   │   ├── list/
│   │   │   │   │   ├── broken by empty line.json
│   │   │   │   │   ├── broken by empty line.org
│   │   │   │   │   ├── descriptive.json
│   │   │   │   │   ├── descriptive.org
│   │   │   │   │   ├── multiline.json
│   │   │   │   │   ├── multiline.org
│   │   │   │   │   ├── nested.json
│   │   │   │   │   ├── nested.org
│   │   │   │   │   ├── ordered.json
│   │   │   │   │   ├── ordered.org
│   │   │   │   │   ├── unordered.json
│   │   │   │   │   └── unordered.org
│   │   │   │   ├── paragraph/
│   │   │   │   │   ├── anonymous footnote.json
│   │   │   │   │   ├── anonymous footnote.org
│   │   │   │   │   ├── footnote reference at the end.json
│   │   │   │   │   ├── footnote reference at the end.org
│   │   │   │   │   ├── footnote refernece in the middle.json
│   │   │   │   │   ├── footnote refernece in the middle.org
│   │   │   │   │   ├── footnote without body.json
│   │   │   │   │   ├── footnote without body.org
│   │   │   │   │   ├── inline footnote with style.json
│   │   │   │   │   ├── inline footnote with style.org
│   │   │   │   │   ├── inline footnote.json
│   │   │   │   │   ├── inline footnote.org
│   │   │   │   │   ├── inline math.json
│   │   │   │   │   ├── inline math.org
│   │   │   │   │   ├── link with style.json
│   │   │   │   │   ├── link with style.org
│   │   │   │   │   ├── link.json
│   │   │   │   │   ├── link.org
│   │   │   │   │   ├── nested footnote.json
│   │   │   │   │   ├── nested footnote.org
│   │   │   │   │   ├── styled text.json
│   │   │   │   │   └── styled text.org
│   │   │   │   └── table/
│   │   │   │       ├── standard.json
│   │   │   │       ├── standard.org
│   │   │   │       ├── with inline styles.json
│   │   │   │       └── with inline styles.org
│   │   │   ├── index.ts
│   │   │   ├── nodes.ts
│   │   │   ├── options.ts
│   │   │   ├── parse/
│   │   │   │   ├── _parseSymbols.ts
│   │   │   │   ├── _primitive.ts
│   │   │   │   ├── _utils.ts
│   │   │   │   ├── block.ts
│   │   │   │   ├── context.ts
│   │   │   │   ├── drawer.ts
│   │   │   │   ├── footnote.ts
│   │   │   │   ├── headline.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── keyword.ts
│   │   │   │   ├── latex.ts
│   │   │   │   ├── list.ts
│   │   │   │   ├── paragraph.ts
│   │   │   │   ├── phrasing.ts
│   │   │   │   ├── planning.ts
│   │   │   │   ├── section.ts
│   │   │   │   └── table.ts
│   │   │   ├── position.ts
│   │   │   ├── timestamp.test.ts
│   │   │   ├── timestamp.ts
│   │   │   ├── todo.test.ts
│   │   │   ├── todo.ts
│   │   │   ├── tokenize/
│   │   │   │   ├── __tests__/
│   │   │   │   │   ├── debug.ts
│   │   │   │   │   └── tok.ts
│   │   │   │   ├── blank.test.ts
│   │   │   │   ├── block.test.ts
│   │   │   │   ├── block.ts
│   │   │   │   ├── comment.test.ts
│   │   │   │   ├── comment.ts
│   │   │   │   ├── drawer.test.ts
│   │   │   │   ├── drawer.ts
│   │   │   │   ├── empty.ts
│   │   │   │   ├── footnote.test.ts
│   │   │   │   ├── footnote.ts
│   │   │   │   ├── headline.test.ts
│   │   │   │   ├── headline.ts
│   │   │   │   ├── hr.test.ts
│   │   │   │   ├── hr.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── inline/
│   │   │   │   │   ├── footnote.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── link.ts
│   │   │   │   │   ├── math.ts
│   │   │   │   │   └── text.ts
│   │   │   │   ├── inline.test.ts
│   │   │   │   ├── keyword.ts
│   │   │   │   ├── keywords.test.ts
│   │   │   │   ├── latex.ts
│   │   │   │   ├── list.test.ts
│   │   │   │   ├── list.ts
│   │   │   │   ├── partial.test.ts
│   │   │   │   ├── planning.test.ts
│   │   │   │   ├── planning.ts
│   │   │   │   ├── table.test.ts
│   │   │   │   └── table.ts
│   │   │   ├── types.ts
│   │   │   ├── uri.test.ts
│   │   │   ├── uri.ts
│   │   │   └── utils.ts
│   │   └── tsconfig.json
│   ├── orga-build/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── cli.js
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── __tests__/
│   │   │   │   └── build.test.js
│   │   │   ├── app.jsx
│   │   │   ├── build.js
│   │   │   ├── components.js
│   │   │   ├── config.js
│   │   │   ├── content.d.ts
│   │   │   ├── csr.jsx
│   │   │   ├── endpoint.js
│   │   │   ├── files.js
│   │   │   ├── fs.js
│   │   │   ├── index.html
│   │   │   ├── orga.js
│   │   │   ├── plugin.js
│   │   │   ├── serve.js
│   │   │   ├── ssr.jsx
│   │   │   ├── util.js
│   │   │   ├── vite.js
│   │   │   └── watch.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── orgx/
│   │   ├── CHANGELOG.md
│   │   ├── README.org
│   │   ├── index.js
│   │   ├── lib/
│   │   │   ├── compile.js
│   │   │   ├── core.js
│   │   │   ├── evaluate.js
│   │   │   ├── plugin/
│   │   │   │   ├── recma-build-jsx-transform.js
│   │   │   │   ├── recma-document.js
│   │   │   │   ├── recma-jsx-rewrite.js
│   │   │   │   └── rehype-recma.js
│   │   │   ├── run.js
│   │   │   ├── types.ts
│   │   │   └── util/
│   │   │       ├── estree-util-create.js
│   │   │       ├── estree-util-declaration-to-expression.js
│   │   │       ├── estree-util-is-declaration.js
│   │   │       ├── estree-util-specifiers-to-declarations.js
│   │   │       ├── estree-util-to-binary-addition.js
│   │   │       ├── estree-util-to-id-or-member-expression.js
│   │   │       ├── is-org-content.js
│   │   │       ├── render-error.js
│   │   │       ├── resolve-evaluate-options.js
│   │   │       └── resolve-file-and-options.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── compile.test.js
│   │   │   └── evaluate.test.js
│   │   └── tsconfig.json
│   ├── react/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── tests/
│   │   │   ├── remove-export-keywords.js
│   │   │   └── test.tsx
│   │   └── tsconfig.json
│   ├── react-cm/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   └── package.json
│   ├── react-editor/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── index.js
│   │   └── package.json
│   ├── reorg-parse/
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── README.org
│   │   ├── index.d.ts
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg-prose/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── lib/
│   │   │   └── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── reorg-rehype/
│   │   ├── .projectile
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE.org
│   │   ├── index.js
│   │   ├── package.json
│   │   └── tsconfig.json
│   ├── rollup/
│   │   ├── CHANGELOG.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── test.js
│   │   └── tsconfig.json
│   └── text-kit/
│       ├── CHANGELOG.md
│       ├── README.md
│       ├── index.js
│       ├── lib/
│       │   ├── core.js
│       │   ├── reader.js
│       │   └── utils/
│       │       ├── index.js
│       │       ├── lines.js
│       │       └── substring.js
│       ├── package.json
│       ├── tests/
│       │   ├── core.js
│       │   └── lines.js
│       └── tsconfig.json
├── pnpm-workspace.yaml
├── shell.nix
├── tsconfig.base.json
├── tsconfig.esm.json
├── tsconfig.json
└── tsconfig.packages.json
Download .txt
SYMBOL INDEX (340 symbols across 118 files)

FILE: docs/_components.tsx
  function Notice (line 13) | function Notice({
  function JSEditor (line 137) | function JSEditor({
  function OrgEditor (line 160) | function OrgEditor({ className = '', content, onChange }) {

FILE: docs/_layout.tsx
  type LayoutProps (line 24) | interface LayoutProps {
  function Layout (line 35) | function Layout({ children }: LayoutProps) {
  type Page (line 84) | type Page = {
  function findParentSlug (line 91) | function findParentSlug(slug: string, pages: Page[]): string | null {
  function renderMenu (line 101) | function renderMenu(path: string, pages: Page[]) {
  function DocumentLayout (line 122) | function DocumentLayout({ title, pages = [], children }) {
  function Content (line 134) | function Content({ children }: { children: ReactNode }) {

FILE: docs/playground.tsx
  function Playground (line 11) | function Playground() {

FILE: examples/build/test-content.tsx
  function TestContent (line 3) | function TestContent() {

FILE: packages/codemirror-lang/index.js
  function getHeadlineLevel (line 20) | function getHeadlineLevel(node) {
  function findSectionEnd (line 32) | function findSectionEnd(headerNode) {
  function mkLang (line 97) | function mkLang(parser) {
  function org (line 101) | function org() {

FILE: packages/editor/lib/actions/fold.js
  function toggleFold (line 22) | function toggleFold(view) {
  function findFold (line 42) | function findFold(state, from, to) {
  function toggleFoldAll (line 53) | function toggleFoldAll(view) {

FILE: packages/editor/lib/actions/shift.js
  function shift (line 17) | function shift(delta, recursive = false) {
  function _shift (line 74) | function _shift(node, delta) {
  function getHeadline (line 99) | function getHeadline(tree, pos) {

FILE: packages/editor/lib/actions/todo.js
  function toggleTodo (line 13) | function toggleTodo(view) {

FILE: packages/editor/lib/actions/utils.js
  function selectedLines (line 9) | function selectedLines(view) {
  function getTodo (line 23) | function getTodo(tree, pos) {
  function getNode (line 33) | function getNode(tree, pos, type) {

FILE: packages/editor/lib/editor.js
  function makeEditor (line 21) | function makeEditor(config) {

FILE: packages/editor/lib/extensions/cleanup.js
  function overlap (line 19) | function overlap(a, b) {
  function cleanup (line 26) | function cleanup(options) {
  function hide (line 87) | function hide(reveal) {
  function todo (line 96) | function todo(actionable) {
  function createDecorations (line 109) | function createDecorations(view, options) {

FILE: packages/editor/lib/settings.js
  method create (line 16) | create(state) {
  method update (line 19) | update(value, tr) {
  function extractSettings (line 31) | function extractSettings(state) {

FILE: packages/esbuild/index.js
  function esbuild (line 23) | function esbuild(options) {

FILE: packages/lezer/lib/context.js
  function parseContext (line 21) | function parseContext(config, input, _fragments, ranges) {

FILE: packages/lezer/lib/fragments.js
  function fragmentCursor (line 27) | function fragmentCursor({ log, nodeSet }, fragments, input) {
  function toRelative (line 190) | function toRelative(abs, ranges) {

FILE: packages/lezer/lib/index.js
  class OrgParser (line 18) | class OrgParser extends Parser {
    method constructor (line 23) | constructor(nodeSet, log = () => {}) {
    method createParse (line 35) | createParse(input, fragments, ranges) {
    method configure (line 51) | configure(config) {

FILE: packages/lezer/lib/oast-to-lezer.js
  function createParseState (line 26) | function createParseState(file, nodeSet) {
  function toLezer (line 49) | function toLezer(tree, nodeSet, file = null) {
  function defaultUnknownHandler (line 62) | function defaultUnknownHandler() {
  function getRange (line 71) | function getRange(node) {
  function one (line 84) | function one(state, node, parent, base = 0) {
  function all (line 133) | function all(state, parent, base) {

FILE: packages/lezer/lib/tree.js
  function hash (line 11) | function hash(type, value, parentHash = 0) {
  function treeBuilder (line 23) | function treeBuilder(

FILE: packages/lezer/lib/types.ts
  type OastNode (line 6) | type OastNode = Document | Content | Token
  type Action (line 8) | type Action = boolean
  type Seed (line 10) | type Seed =
  type LezerChild (line 20) | interface LezerChild {
  type Handler (line 25) | type Handler = (
  type State (line 31) | interface State {

FILE: packages/lezer/tests/compare-tree.js
  function compareTree (line 11) | function compareTree(a, b) {
  function print (line 40) | function print(tree, prefix = '') {

FILE: packages/lezer/tests/incremental.test.js
  class State (line 23) | class State {
    method constructor (line 24) | constructor(doc, tree, fragments) {
    method start (line 30) | static start(doc) {
    method update (line 39) | update(changes, reparse = true) {
  function testChange (line 68) | function testChange(change, verbose = false, reuse = 10) {
  function overlap (line 85) | function overlap(a, b) {

FILE: packages/loader/index.d.ts
  type Options (line 18) | type Options = ProcessorOptions

FILE: packages/loader/lib/index.js
  function loader (line 13) | async function loader(source, callback) {

FILE: packages/loader/tests/compiler.js
  function compile (line 6) | async function compile(fixture, options = {}) {

FILE: packages/metadata/lib/index.js
  constant TO_DISCARD (line 7) | const TO_DISCARD = [
  function shouldDiscard (line 26) | function shouldDiscard(key) {
  function processValue (line 40) | function processValue(text) {
  function pushTo (line 47) | function pushTo(data) {
  function parse (line 75) | function parse(text) {

FILE: packages/node-loader/index.js
  function createLoader (line 29) | function createLoader(loaderOptions) {
  function configure (line 85) | function configure(options) {

FILE: packages/oast-to-hast/lib/handlers/block.js
  function block (line 8) | function block(state, node) {

FILE: packages/oast-to-hast/lib/handlers/document.js
  function document (line 6) | function document(state, node) {

FILE: packages/oast-to-hast/lib/handlers/footnote.js
  function footnoteRef (line 6) | function footnoteRef(state, node) {
  function footnote (line 27) | function footnote(state, node) {

FILE: packages/oast-to-hast/lib/handlers/headline.js
  function headline (line 6) | function headline(state, node) {

FILE: packages/oast-to-hast/lib/handlers/hr.js
  function hr (line 6) | function hr(state, node) {

FILE: packages/oast-to-hast/lib/handlers/html.js
  function html (line 8) | function html(state, node) {
  function parseHtml (line 16) | function parseHtml(html) {

FILE: packages/oast-to-hast/lib/handlers/index.js
  function ignore (line 59) | function ignore() {
  function passThrough (line 64) | function passThrough(_, node) {

FILE: packages/oast-to-hast/lib/handlers/keyword.js
  function keyword (line 6) | function keyword(state, node) {

FILE: packages/oast-to-hast/lib/handlers/latex.js
  function latex (line 6) | function latex(state, node) {

FILE: packages/oast-to-hast/lib/handlers/link.js
  function link (line 12) | function link(state, node) {

FILE: packages/oast-to-hast/lib/handlers/list.js
  function list (line 6) | function list(state, node) {
  function item (line 28) | function item(state, node, parent) {
  function checkbox (line 84) | function checkbox(state, node) {

FILE: packages/oast-to-hast/lib/handlers/newline.js
  function newline (line 7) | function newline(_state, _node, parent) {

FILE: packages/oast-to-hast/lib/handlers/paragraph.js
  constant BLOCK_TAGS (line 7) | const BLOCK_TAGS = new Set([
  function paragraph (line 49) | function paragraph(state, node) {

FILE: packages/oast-to-hast/lib/handlers/section.js
  function section (line 6) | function section(state, node) {
  function shouldSkip (line 40) | function shouldSkip({ selectTags = [], excludeTags = [] }, tags) {

FILE: packages/oast-to-hast/lib/handlers/table.js
  function table (line 12) | function table(state, node) {
  function row (line 74) | function row(state, node) {
  function cell (line 88) | function cell(state, node) {
  function hr (line 100) | function hr() {

FILE: packages/oast-to-hast/lib/handlers/text.js
  function text (line 21) | function text(state, node) {

FILE: packages/oast-to-hast/lib/index.js
  function toHast (line 17) | function toHast(tree, options = {}) {

FILE: packages/oast-to-hast/lib/state.js
  function createState (line 38) | function createState(_tree, options = {}) {
  function defaultLinkHref (line 128) | function defaultLinkHref(link) {
  function unkownHandler (line 140) | function unkownHandler(state, node) {

FILE: packages/oast-to-hast/tests/block.js
  function removePosition (line 30) | function removePosition(node) {

FILE: packages/oast-to-prose/lib/handlers/block.js
  function block (line 10) | function block(state, node) {

FILE: packages/oast-to-prose/lib/handlers/headline.js
  function headline (line 10) | function headline(state, node) {

FILE: packages/oast-to-prose/lib/handlers/link.js
  function link (line 10) | function link(state, node) {

FILE: packages/oast-to-prose/lib/handlers/newline.js
  function newline (line 9) | function newline(state) {

FILE: packages/oast-to-prose/lib/handlers/paragraph.js
  function paragraph (line 10) | function paragraph(state, node) {

FILE: packages/oast-to-prose/lib/handlers/section.js
  function section (line 10) | function section(state, node) {

FILE: packages/oast-to-prose/lib/handlers/stars.js
  function stars (line 10) | function stars(state, node) {

FILE: packages/oast-to-prose/lib/handlers/tags.js
  function tags (line 10) | function tags(state, node) {

FILE: packages/oast-to-prose/lib/handlers/text.js
  function text (line 10) | function text(state, node) {

FILE: packages/oast-to-prose/lib/handlers/todo.js
  function todo (line 10) | function todo(state, node) {

FILE: packages/oast-to-prose/lib/index.js
  function toProse (line 37) | function toProse(tree, file, options) {

FILE: packages/oast-to-prose/lib/schema.js
  method toDOM (line 11) | toDOM() {
  method toDOM (line 29) | toDOM(node) {
  method toDOM (line 40) | toDOM(node) {
  method toDOM (line 54) | toDOM(node) {
  method toDOM (line 66) | toDOM() {
  method toDOM (line 74) | toDOM() {
  method getAttrs (line 93) | getAttrs(dom) {
  method toDOM (line 102) | toDOM(node) {
  method toDOM (line 110) | toDOM() {
  method toDOM (line 118) | toDOM() {
  method toDOM (line 128) | toDOM(node) {

FILE: packages/oast-to-prose/lib/state.js
  function createParseState (line 36) | function createParseState(file, options) {
  function defaultUnknownHandler (line 95) | function defaultUnknownHandler(state, node, file) {
  function getRawContent (line 122) | function getRawContent(node, file) {

FILE: packages/orga-build/lib/__tests__/build.test.js
  function markCodeBlocks (line 12) | function markCodeBlocks() {

FILE: packages/orga-build/lib/app.jsx
  function SmartLink (line 6) | function SmartLink({ href, ...props }) {
  function App (line 13) | function App() {

FILE: packages/orga-build/lib/build.js
  function build (line 21) | async function build(

FILE: packages/orga-build/lib/config.js
  function loadConfig (line 34) | async function loadConfig(...files) {

FILE: packages/orga-build/lib/content.d.ts
  type ContentEntry (line 2) | interface ContentEntry {

FILE: packages/orga-build/lib/endpoint.js
  function resolveEndpointResponse (line 15) | async function resolveEndpointResponse(

FILE: packages/orga-build/lib/files.js
  function getFileExtension (line 34) | function getFileExtension(filePath) {
  function getContentPath (line 44) | function getContentPath(slug) {
  function getContentId (line 71) | function getContentId(slug) {
  function setup (line 91) | function setup(dir, { outDir, exclude = [] } = {}) {
  function cache (line 281) | function cache(fn) {
  function getSlugFromContentFilePath (line 304) | function getSlugFromContentFilePath(contentFilePath) {
  function getPageSlugFromFilePath (line 328) | function getPageSlugFromFilePath(filePath) {
  function getEndpointRouteFromFilePath (line 339) | function getEndpointRouteFromFilePath(filePath) {
  function assertUniqueRoute (line 362) | function assertUniqueRoute(routeOwners, route, sourceType, filePath) {

FILE: packages/orga-build/lib/fs.js
  function resolvePath (line 9) | function resolvePath(rootPath) {
  function exists (line 27) | async function exists(path) {
  function emptyDir (line 40) | async function emptyDir(dir) {
  function ensureDir (line 57) | async function ensureDir(path) {
  function copy (line 71) | async function copy(src, dest) {

FILE: packages/orga-build/lib/orga.js
  function setupOrga (line 15) | function setupOrga({ containerClass, root, rehypePlugins = [] }) {
  function mediaAssets (line 28) | function mediaAssets() {
  function rehypeWrap (line 64) | function rehypeWrap({ className = [] }) {
  function rewriteOrgFileLinks (line 95) | function rewriteOrgFileLinks({ root }) {
  function resolveOrgHrefToContentSlug (line 127) | function resolveOrgHrefToContentSlug({ root, filePath, href }) {
  function genId (line 144) | function genId(length = 8) {

FILE: packages/orga-build/lib/plugin.js
  function orgaBuildPlugin (line 42) | function orgaBuildPlugin({
  function createOrgaBuildConfig (line 64) | function createOrgaBuildConfig({
  function hasUserIndexHtml (line 103) | async function hasUserIndexHtml(root) {
  function htmlFallbackPlugin (line 126) | function htmlFallbackPlugin(projectRoot, styles = []) {

FILE: packages/orga-build/lib/serve.js
  function serve (line 12) | async function serve(config, port = 3000, projectRoot = process.cwd()) {

FILE: packages/orga-build/lib/ssr.jsx
  function render (line 13) | function render(url) {

FILE: packages/orga-build/lib/util.js
  function buildNav (line 4) | function buildNav() {}
  function match (line 11) | function match(file, ...patterns) {
  function DefaultLayout (line 27) | function DefaultLayout({ title, children }) {
  function escapeHtml (line 49) | function escapeHtml(str) {
  function $ (line 60) | async function $(cmd) {

FILE: packages/orga-build/lib/vite.js
  function pluginFactory (line 20) | function pluginFactory({ dir, outDir, styles = [], exclude = [] }) {

FILE: packages/orga-build/lib/watch.js
  function watch (line 8) | async function watch(dir, ignore, onChange) {

FILE: packages/orga/src/__tests__/index.test.ts
  function removeUndefined (line 38) | function removeUndefined(obj: any) {

FILE: packages/orga/src/index.ts
  function makeParser (line 31) | function makeParser(text: string, options: Partial<Options> = {}) {
  function getSettings (line 43) | function getSettings(text: string): Settings {
  function getTodo (line 78) | function getTodo(settings: Settings) {

FILE: packages/orga/src/options.ts
  type LexerOptions (line 5) | interface LexerOptions {
  type ParserOptions (line 11) | interface ParserOptions {
  type Options (line 17) | interface Options {

FILE: packages/orga/src/parse/_utils.ts
  constant COMMON_IMAGE_EXTENSIONS (line 1) | const COMMON_IMAGE_EXTENSIONS = [

FILE: packages/orga/src/parse/context.ts
  function initialProperties (line 19) | function initialProperties(settings: Properties | undefined): Properties {
  type Snapshot (line 25) | interface Snapshot {
  type Context (line 32) | interface Context {
  function point (line 62) | function point(d: Point): Point {
  function createContext (line 66) | function createContext(lexer: Lexer, options: ParserOptions): Context {

FILE: packages/orga/src/parse/index.ts
  type Parse (line 16) | type Parse = (lexer: Lexer) => Parent | undefined
  type FlowControl (line 23) | type FlowControl = 'break' | 'next' | 'finish'
  type Action (line 25) | type Action = (
  type Predicate (line 30) | type Predicate = string | 'EOF' | RegExp | ((token: Node) => boolean)
  function test (line 32) | function test(node: Node, predicate: Predicate) {
  function not (line 36) | function not(test: Predicate): Predicate {
  function toFunc (line 40) | function toFunc(test: Predicate): (token: Node) => boolean {
  type Rule (line 55) | type Rule = { test: Predicate | Predicate[]; action: Action | Handler }
  type Handler (line 57) | interface Handler {
  type Parser (line 102) | interface Parser {
  function parser (line 109) | function parser(lexer: Lexer, options: ParserOptions): Parser {

FILE: packages/orga/src/parse/keyword.ts
  constant AFFILIATED_KEYWORDS (line 6) | const AFFILIATED_KEYWORDS = ['caption', 'header', 'name', 'plot', 'resul...

FILE: packages/orga/src/todo.ts
  type TodoKeywordSet (line 1) | interface TodoKeywordSet {
  type TodoManager (line 10) | interface TodoManager extends TodoKeywordSet {
  function parseTodoKeywords (line 25) | function parseTodoKeywords(value: string): TodoKeywordSet {
  function todoManager (line 70) | function todoManager(...keywords: string[]): TodoManager {

FILE: packages/orga/src/tokenize/index.ts
  constant PLANNING_KEYWORDS (line 20) | const PLANNING_KEYWORDS = ['DEADLINE', 'SCHEDULED', 'CLOSED']
  type Lexer (line 22) | interface Lexer {
  type Tokenizer (line 39) | type Tokenizer = (reader: Reader) => Token[] | Token | undefined
  function tok (line 69) | function tok(): Token[] {
  method eatAll (line 121) | eatAll(type: string): number {
  method match (line 128) | match(cond, _offset = 0) {
  method all (line 137) | all(_max: number | undefined = undefined): Token[] {
  method restore (line 149) | restore(point) {
  method now (line 155) | get now() {
  method todo (line 161) | get todo() {

FILE: packages/orga/src/tokenize/inline/index.ts
  constant ALL (line 9) | const ALL: Tokenizer[] = [

FILE: packages/orga/src/tokenize/inline/text.ts
  constant MARKERS (line 5) | const MARKERS: { [key: string]: Style } = {

FILE: packages/orga/src/types.ts
  type Literal (line 7) | interface Literal extends UnistLiteral {
  type Parent (line 11) | interface Parent extends UnistParent {
  type Primitive (line 15) | type Primitive = string | number | boolean
  type Attributes (line 17) | interface Attributes {
  type Attributed (line 21) | interface Attributed {
  type Timestamp (line 25) | interface Timestamp {
  type Properties (line 30) | type Properties = Record<string, PropertyValue>
  type Settings (line 31) | type Settings = Record<string, PropertyValue>
  type PropertyValue (line 33) | type PropertyValue = string | string[] | Record<string, string>
  type Nodes (line 35) | type Nodes = Document | Content | Token
  type Document (line 38) | interface Document extends Parent {
  type Section (line 44) | interface Section extends Parent {
  type BlockContent (line 52) | type BlockContent =
  type TopLevelContent (line 66) | type TopLevelContent = BlockContent | Keyword | Footnote
  type Content (line 68) | type Content =
  type Footnote (line 76) | interface Footnote extends Parent {
  type Block (line 81) | interface Block extends Literal, Attributed {
  type Latex (line 88) | interface Latex extends Literal {
  type Drawer (line 93) | interface Drawer extends Literal {
  type Planning (line 98) | interface Planning extends Node {
  type ListContent (line 104) | type ListContent = ListItem | List
  type List (line 106) | interface List extends Parent, Attributed {
  type TableContent (line 113) | type TableContent = TableRow | TableRule
  type Table (line 115) | interface Table extends Parent, Attributed {
  type TableRow (line 120) | interface TableRow extends Parent {
  type TableCell (line 125) | interface TableCell extends Parent {
  type ListItem (line 130) | interface ListItem extends Parent {
  type Headline (line 137) | interface Headline extends Parent {
  type Paragraph (line 147) | interface Paragraph extends Parent, Attributed {
  type HTML (line 152) | interface HTML extends Literal {
  type JSX (line 156) | interface JSX extends Literal {
  type Token (line 161) | type Token =
  type PhrasingContent (line 190) | type PhrasingContent =
  type HorizontalRule (line 199) | interface HorizontalRule extends Node {
  type Newline (line 203) | interface Newline extends Node {
  type EmptyLine (line 207) | interface EmptyLine extends Node {
  type Style (line 211) | type Style =
  type Text (line 220) | interface Text extends Literal {
  type Link (line 225) | interface Link extends Parent, Attributed {
  type LinkPath (line 231) | interface LinkPath extends Literal {
  type Enclosed (line 237) | type Enclosed = Style | 'link' | 'footnote.reference'
  type Opening (line 239) | interface Opening extends Node {
  type Closing (line 244) | interface Closing extends Node {
  type FootnoteReference (line 268) | interface FootnoteReference extends Parent {
  type Stars (line 275) | interface Stars extends Node {
  type Todo (line 280) | interface Todo extends Node {
  type Priority (line 286) | interface Priority extends Literal {
  type Tags (line 290) | interface Tags extends Node {
  type BlockBegin (line 296) | interface BlockBegin extends Node {
  type BlockEnd (line 302) | interface BlockEnd extends Node {
  type DrawerBegin (line 308) | interface DrawerBegin extends Node {
  type DrawerEnd (line 313) | interface DrawerEnd extends Node {
  type LatexBegin (line 317) | interface LatexBegin extends Node {
  type LatexEnd (line 322) | interface LatexEnd extends Node {
  type Comment (line 327) | interface Comment extends Literal {
  type Keyword (line 331) | interface Keyword extends Node {
  type FootnoteLabel (line 337) | interface FootnoteLabel extends Node {
  type PlanningKeyword (line 342) | interface PlanningKeyword extends Literal {
  type PlanningTimestamp (line 346) | interface PlanningTimestamp extends UnistLiteral {
  type ListItemTag (line 351) | interface ListItemTag extends Literal {
  type ListItemCheckbox (line 355) | interface ListItemCheckbox extends Node {
  type ListItemBullet (line 360) | interface ListItemBullet extends Node {
  type TableRule (line 366) | interface TableRule extends Node {
  type TableColumnSeparator (line 370) | interface TableColumnSeparator extends Node {
  function isSection (line 374) | function isSection(node: Node): node is Section {
  function isParagraph (line 378) | function isParagraph(node: Node): node is Paragraph {
  function isLink (line 382) | function isLink(node: Node): node is Link {
  function isFootnoteReference (line 386) | function isFootnoteReference(node: Node): node is FootnoteReference {
  function isText (line 390) | function isText(node: Node): node is Text {
  type Data (line 395) | interface Data {

FILE: packages/orga/src/uri.ts
  constant URL_PATTERN (line 1) | const URL_PATTERN = /(?:([a-z][a-z0-9+.-]*):)?(.*)/i
  type LinkInfo (line 3) | interface LinkInfo {

FILE: packages/orgx/lib/compile.js
  function compile (line 35) | function compile(vfileCompatible, compileOptions) {
  function compileSync (line 54) | function compileSync(vfileCompatible, compileOptions) {

FILE: packages/orgx/lib/core.js
  function createProcessor (line 58) | function createProcessor(options) {

FILE: packages/orgx/lib/evaluate.js
  function evaluate (line 22) | async function evaluate(vfileCompatible, evaluateOptions) {
  function evaluateSync (line 38) | function evaluateSync(vfileCompatible, evaluateOptions) {

FILE: packages/orgx/lib/plugin/recma-build-jsx-transform.js
  function recmaBuildJsxTransform (line 24) | function recmaBuildJsxTransform(options) {

FILE: packages/orgx/lib/plugin/recma-document.js
  function recmaDocument (line 64) | function recmaDocument(options) {

FILE: packages/orgx/lib/plugin/recma-jsx-rewrite.js
  function recmaJsxRewrite (line 66) | function recmaJsxRewrite(options) {
  function createImportProvider (line 562) | function createImportProvider(providerImportSource, outputFormat) {
  function isNamedFunction (line 593) | function isNamedFunction(node, name) {
  function inScope (line 602) | function inScope(scope, id) {

FILE: packages/orgx/lib/plugin/rehype-recma.js
  function rehypeRecma (line 20) | function rehypeRecma(options) {
  function isProgram (line 67) | function isProgram(node) {
  function parse (line 74) | function parse(code) {
  function removeQuotes (line 122) | function removeQuotes(text) {
  function createExport (line 131) | function createExport(k, v) {

FILE: packages/orgx/lib/run.js
  function run (line 14) | async function run(file, options) {
  function runSync (line 28) | function runSync(file, options) {

FILE: packages/orgx/lib/types.ts
  type FunctionComponent (line 1) | type FunctionComponent<Props> = (props: Props) => React.JSX.Element | null
  type ClassComponent (line 2) | type ClassComponent<Props> = new (props: Props) => React.JSX.ElementClass
  type Component (line 3) | type Component<Props> =
  type NestedOrgComponents (line 8) | interface NestedOrgComponents {
  type OrgComponents (line 12) | type OrgComponents = NestedOrgComponents & {
  type OrgProps (line 23) | interface OrgProps {
  type OrgContent (line 36) | type OrgContent = (props: OrgProps) => React.JSX.Element
  type OrgModule (line 38) | interface OrgModule {

FILE: packages/orgx/lib/util/estree-util-create.js
  function create (line 13) | function create(from, to) {

FILE: packages/orgx/lib/util/estree-util-declaration-to-expression.js
  function declarationToExpression (line 18) | function declarationToExpression(declaration) {

FILE: packages/orgx/lib/util/estree-util-is-declaration.js
  function isDeclaration (line 14) | function isDeclaration(node) {

FILE: packages/orgx/lib/util/estree-util-specifiers-to-declarations.js
  function specifiersToDeclarations (line 19) | function specifiersToDeclarations(specifiers, init) {

FILE: packages/orgx/lib/util/estree-util-to-binary-addition.js
  function toBinaryAddition (line 8) | function toBinaryAddition(expressions) {

FILE: packages/orgx/lib/util/estree-util-to-id-or-member-expression.js
  function toIdOrMemberExpressionFactory (line 37) | function toIdOrMemberExpressionFactory(idType, memberType, isIdentifier) {
  function isJsxIdentifierName (line 90) | function isJsxIdentifierName(name) {
  function jsxCont (line 108) | function jsxCont(code) {

FILE: packages/orgx/lib/util/is-org-content.js
  function isOrgContent (line 6) | function isOrgContent(node) {

FILE: packages/orgx/lib/util/resolve-evaluate-options.js
  function resolveEvaluateOptions (line 30) | function resolveEvaluateOptions(options) {

FILE: packages/orgx/lib/util/resolve-file-and-options.js
  function resolveFileAndOptions (line 17) | function resolveFileAndOptions(vfileCompatible, options) {
  function looksLikeAVFile (line 33) | function looksLikeAVFile(value) {

FILE: packages/react-cm/index.js
  function ReactCodeMirror (line 16) | function ReactCodeMirror({

FILE: packages/react-editor/index.js
  function Editor (line 15) | function Editor({ content = '', className, onChange, extensions = [] }) {

FILE: packages/react/index.js
  function useOrgComponents (line 36) | function useOrgComponents(components) {
  function OrgProvider (line 59) | function OrgProvider({ components, children, disableParentContext }) {

FILE: packages/react/tests/remove-export-keywords.js
  method ExportNamedDeclaration (line 4) | ExportNamedDeclaration(path) {

FILE: packages/reorg-parse/index.js
  function reorgParse (line 22) | function reorgParse(options) {

FILE: packages/reorg-prose/lib/index.js
  function reorgProse (line 17) | function reorgProse(options) {

FILE: packages/reorg-rehype/index.js
  function reorg2rehype (line 26) | function reorg2rehype(options = {}) {

FILE: packages/rollup/index.js
  function rollup (line 65) | function rollup(options) {

FILE: packages/text-kit/index.js
  function read (line 17) | function read(text, range = {}) {

FILE: packages/text-kit/lib/core.js
  function clamp (line 21) | function clamp(num, min, max) {
  function core (line 29) | function core(text) {

FILE: packages/text-kit/lib/reader.js
  constant PAIRS (line 16) | const PAIRS = [
  function reader (line 33) | function reader(_core, range = {}) {

FILE: packages/text-kit/lib/utils/index.js
  function enhance (line 11) | function enhance(core) {

FILE: packages/text-kit/lib/utils/lines.js
  function linePosition (line 31) | function linePosition(start, end) {
  function endOfLine (line 58) | function endOfLine(ln) {

FILE: packages/text-kit/lib/utils/substring.js
  function addSubstring (line 18) | function addSubstring(core) {
Condensed preview — 439 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (959K chars).
[
  {
    "path": ".changeset/README.md",
    "chars": 510,
    "preview": "# Changesets\n\nHello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that wo"
  },
  {
    "path": ".changeset/config.json",
    "chars": 256,
    "preview": "{\n  \"$schema\": \"https://unpkg.com/@changesets/config@1.6.0/schema.json\",\n  \"changelog\": \"@changesets/cli/changelog\",\n  \""
  },
  {
    "path": ".editorconfig",
    "chars": 497,
    "preview": "root = true\n\n[*]\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\nindent_sty"
  },
  {
    "path": ".eslintignore",
    "chars": 47,
    "preview": "node_modules\n**/dist/**\n**/__tests__/**/*.json\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 70,
    "preview": "# These are supported funding model platforms\n\ngithub: ['xiaoxinghu']\n"
  },
  {
    "path": ".github/workflows/ci.yml",
    "chars": 682,
    "preview": "name: CI\n\non:\n  push:\n    branches:\n      - main\n    paths-ignore:\n      - 'docs/**'\n      - '**/README.org'\n      - '**"
  },
  {
    "path": ".github/workflows/release.yml",
    "chars": 1227,
    "preview": "name: Release\n\non:\n  push:\n    branches:\n      - main\n\nenv:\n  CI: true\n\npermissions: {}\n\njobs:\n  release:\n    name: Rele"
  },
  {
    "path": ".github/workflows/website.yml",
    "chars": 1549,
    "preview": "name: Deploy to GitHub Pages\n\non:\n  # Trigger the workflow every time you push to the `main` branch\n  # Using a differen"
  },
  {
    "path": ".gitignore",
    "chars": 1599,
    "preview": "# 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 "
  },
  {
    "path": ".prettierignore",
    "chars": 88,
    "preview": ".archive\n.cache\nnode_modules\n.next\npublic\nlib\n**/dist/**\n.yarn/*\n**/__tests__/**/*.json\n"
  },
  {
    "path": ".prettierrc",
    "chars": 110,
    "preview": "{\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",
    "chars": 4548,
    "preview": "# Change Log\n\nAll notable changes to this project will be documented in this file.\nSee [Conventional Commits](https://co"
  },
  {
    "path": "CONTRIBUTING.org",
    "chars": 1667,
    "preview": "#+title: How to contribute to orgajs\n\nHi 👋 🦄.\n\n* Getting Started\nMake sure you have latest yarn installed locally.\nTo ge"
  },
  {
    "path": "LICENSE.org",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "README.org",
    "chars": 3396,
    "preview": "#+title: Orga\n#+subtitle: org-mode < JavaScript\n\n* What Is It\n\n=Orga= is a flexible org-mode syntax parser. It parses or"
  },
  {
    "path": "biome.json",
    "chars": 509,
    "preview": "{\n\t\"$schema\": \"https://biomejs.dev/schemas/2.4.4/schema.json\",\n\t\"files\": {\n\t\t\"includes\": [\"packages/**\", \"!packages/**/_"
  },
  {
    "path": "docs/.gitignore",
    "chars": 4,
    "preview": "out\n"
  },
  {
    "path": "docs/_components.tsx",
    "chars": 4130,
    "preview": "import { Editor } from '@orgajs/react-editor'\nimport { ReactCodeMirror } from '@orgajs/react-cm'\nimport { tags as t } fr"
  },
  {
    "path": "docs/_layout.tsx",
    "chars": 4259,
    "preview": "import { ReactNode } from 'react'\nimport { Link } from 'orga-build/components'\n\nimport type { SVGProps } from 'react'\nco"
  },
  {
    "path": "docs/_snippets/hey.org",
    "chars": 144,
    "preview": "* Hey, there\n\nThe /beauty/ of org *must* be shared.\n[[https://upload.wikimedia.org/wikipedia/commons/a/a6/Org-mode-unico"
  },
  {
    "path": "docs/advanced/_layout.tsx",
    "chars": 78,
    "preview": "import { DocumentLayout } from '../_layout.tsx'\nexport default DocumentLayout\n"
  },
  {
    "path": "docs/advanced/api.org",
    "chars": 127,
    "preview": "#+title: API\n#+published: true\n#+position: 201\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\nDescribe th"
  },
  {
    "path": "docs/advanced/ast.org",
    "chars": 136,
    "preview": "#+title: AST\n#+published: true\n#+position: 202\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\nOrga Abstra"
  },
  {
    "path": "docs/advanced/index.org",
    "chars": 113,
    "preview": "#+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",
    "chars": 807,
    "preview": "#+title: Latex Support\n#+published: true\n#+position: 203\n#+type: document\n\n\n** Inline Math\nOrgajs supports inline math w"
  },
  {
    "path": "docs/contribute.org",
    "chars": 416,
    "preview": "#+title: Contribute\n#+published: true\n#+position: 300\n#+type: document\n\n#+jsx: <Notice>This page is a WIP</Notice>\n\n* Ne"
  },
  {
    "path": "docs/guides/_layout.tsx",
    "chars": 78,
    "preview": "import { DocumentLayout } from '../_layout.tsx'\nexport default DocumentLayout\n"
  },
  {
    "path": "docs/guides/astro.org",
    "chars": 1744,
    "preview": "#+title: Astro\n#+published: true\n#+type: document\n#+position: 5\n\nUse =@orgajs/astro= to write Astro pages in Org Mode (="
  },
  {
    "path": "docs/guides/gatsby.org",
    "chars": 1106,
    "preview": "#+title: Gatsby\n#+published: true\n#+type: document\n#+position: 102\n\n#+jsx: <Notice title=\"DEPRECATED\">I'm no longer acti"
  },
  {
    "path": "docs/guides/index.org",
    "chars": 1177,
    "preview": "#+title: Getting Started\n#+published: true\n#+type: document\n#+position: 100\n\n** Basic Setup\nOrga is built on the [[https"
  },
  {
    "path": "docs/guides/next.org",
    "chars": 1584,
    "preview": "#+title: Next.js\n#+published: true\n#+type: document\n#+position: 4\n\nUse =@orgajs/next= to write Next.js pages in Org Mode"
  },
  {
    "path": "docs/guides/orga-build.org",
    "chars": 2864,
    "preview": "#+title: Build a blog with orga-build\n#+position: 2\n#+type: document\n\n\n=orga-build= is a powerful static site generator "
  },
  {
    "path": "docs/guides/webpack.org",
    "chars": 1538,
    "preview": "#+title: Webpack\n#+published: true\n#+type: document\n#+position: 3\n\n=@orgajs/loader= is a webpack loader taht can be used"
  },
  {
    "path": "docs/index.org",
    "chars": 636,
    "preview": "#+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"
  },
  {
    "path": "docs/playground.tsx",
    "chars": 3933,
    "preview": "import { ReactNode, useEffect, useMemo, useState } from 'react'\nimport { VFile } from 'vfile'\nimport { evaluate } from '"
  },
  {
    "path": "docs/style.css",
    "chars": 1203,
    "preview": "@import 'tailwindcss';\n@plugin \"@tailwindcss/typography\";\n@plugin \"daisyui\" {\n\tthemes: nord --default, dark --prefersdar"
  },
  {
    "path": "docs/tsconfig.json",
    "chars": 327,
    "preview": "{\n\t\"compilerOptions\": {\n\t\t\"jsx\": \"react-jsx\",\n\t\t\"lib\": [\"esnext\", \"DOM\"],\n\t\t\"moduleResolution\": \"node\",\n\t\t\"allowJs\": tru"
  },
  {
    "path": "examples/README.org",
    "chars": 4287,
    "preview": "#+TITLE: Examples\n\n* Setup\n\nBefore using any of the examples, you have to build the monorepo.\n\n#+begin_src shell\ngit clo"
  },
  {
    "path": "examples/build/index.org",
    "chars": 164,
    "preview": "#+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 p"
  },
  {
    "path": "examples/build/more.org",
    "chars": 45,
    "preview": "#+title: Another Page\n\nThis is another page.\n"
  },
  {
    "path": "examples/build/package.json",
    "chars": 199,
    "preview": "{\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\"bui"
  },
  {
    "path": "examples/build/test-content.tsx",
    "chars": 1164,
    "preview": "import { getPages, getPage } from 'orga-build:content'\n\nexport default function TestContent() {\n  // Test 1: Get all pag"
  },
  {
    "path": "examples/editor/.gitignore",
    "chars": 253,
    "preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
  },
  {
    "path": "examples/editor/CHANGELOG.md",
    "chars": 1819,
    "preview": "# @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 edit"
  },
  {
    "path": "examples/editor/content.org",
    "chars": 379,
    "preview": "#+title:  Example Org File\n#+date:   2023-11-24\n#+todo: TODO NEXT | DONE\n\nOrg uses single characters to markup *bold* /i"
  },
  {
    "path": "examples/editor/index.html",
    "chars": 423,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n  <head>\n    <meta charset=\"UTF-8\" />\n    <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
  },
  {
    "path": "examples/editor/package.json",
    "chars": 403,
    "preview": "{\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\": \"v"
  },
  {
    "path": "examples/editor/src/main.ts",
    "chars": 274,
    "preview": "import { makeEditor } from '@orgajs/editor'\nimport content from '../content.org?raw'\nimport './style.css'\n\nconst target "
  },
  {
    "path": "examples/editor/src/style.css",
    "chars": 148,
    "preview": "body {\n\tbackground-color: #e7e6e5;\n}\n\n#editor {\n\twidth: 720px;\n\theight: 800px;\n\toverflow: auto;\n\tborder: 1px solid #ccc;"
  },
  {
    "path": "examples/editor/tsconfig.json",
    "chars": 527,
    "preview": "{\n  \"compilerOptions\": {\n    \"target\": \"ES2020\",\n    \"useDefineForClassFields\": true,\n    \"module\": \"ESNext\",\n    \"lib\":"
  },
  {
    "path": "examples/getting-started/.gitignore",
    "chars": 913,
    "preview": "# 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# Directo"
  },
  {
    "path": "examples/getting-started/CHANGELOG.md",
    "chars": 5434,
    "preview": "# 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"
  },
  {
    "path": "examples/getting-started/README.org",
    "chars": 158,
    "preview": "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_SR"
  },
  {
    "path": "examples/getting-started/index.js",
    "chars": 265,
    "preview": "import { reorg } from '@orgajs/reorg'\nimport { stream } from 'unified-stream'\nimport mutate from '@orgajs/reorg-rehype'\n"
  },
  {
    "path": "examples/getting-started/package.json",
    "chars": 452,
    "preview": "{\n  \"private\": true,\n  \"name\": \"@orgajs/getting-started\",\n  \"version\": \"4.2.12\",\n  \"description\": \"\",\n  \"main\": \"index.j"
  },
  {
    "path": "examples/webpack/.babelrc",
    "chars": 62,
    "preview": "{\n  \"presets\": [\"@babel/preset-env\", \"@babel/preset-react\"]\n}\n"
  },
  {
    "path": "examples/webpack/CHANGELOG.md",
    "chars": 1614,
    "preview": "# 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 "
  },
  {
    "path": "examples/webpack/README.org",
    "chars": 246,
    "preview": "#+title: Webpack + Orga\n\nThis is a minimal webpack website that recognizes org-mode files as pages.\n\n-----\n\n* Running lo"
  },
  {
    "path": "examples/webpack/package.json",
    "chars": 536,
    "preview": "{\n\t\"name\": \"@orgajs/example-webpack\",\n\t\"private\": true,\n\t\"version\": \"3.2.0\",\n\t\"author\": \"Xiaoxing Hu <hi@xiaoxing.dev>\","
  },
  {
    "path": "examples/webpack/public/index.html",
    "chars": 95,
    "preview": "<!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",
    "chars": 193,
    "preview": "import React from 'react'\n\nexport default ({ children }) => (\n  <div\n    style={{\n      padding: 20,\n      backgroundCol"
  },
  {
    "path": "examples/webpack/src/hello.org",
    "chars": 315,
    "preview": "#+jsx: import Box from './box'\n\n* Hello\n\n#+begin_export jsx\nexport default ({ children }) =>\n  <div style={{ padding: 20"
  },
  {
    "path": "examples/webpack/src/index.js",
    "chars": 185,
    "preview": "import React from 'react'\nimport { createRoot } from 'react-dom/client'\nimport Hello from './hello.org'\n\nconst root = cr"
  },
  {
    "path": "examples/webpack/webpack.config.mjs",
    "chars": 255,
    "preview": "export default {\n  mode: 'development',\n  module: {\n    rules: [\n      {\n        test: /\\.js$/,\n        use: 'babel-load"
  },
  {
    "path": "orga.config.js",
    "chars": 363,
    "preview": "import tailwindcss from '@tailwindcss/vite'\nimport rehypePrettyCode from 'rehype-pretty-code'\n\nexport const containerCla"
  },
  {
    "path": "package.json",
    "chars": 1501,
    "preview": "{\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\"@change"
  },
  {
    "path": "packages/astro/README.org",
    "chars": 231,
    "preview": "* @orgajs/astro (Moved)\n\nThe Astro integration package has moved to a dedicated repository:\n\n[[https://github.com/orgapp"
  },
  {
    "path": "packages/codemirror-lang/CHANGELOG.md",
    "chars": 1421,
    "preview": "# @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"
  },
  {
    "path": "packages/codemirror-lang/index.js",
    "chars": 1933,
    "preview": "/** @typedef {import('@lezer/common').SyntaxNode} SyntaxNode */\n\nimport {\n\tdefineLanguageFacet,\n\tfoldNodeProp,\n\tfoldServ"
  },
  {
    "path": "packages/codemirror-lang/package.json",
    "chars": 639,
    "preview": "{\n\t\"name\": \"@orgajs/cm-lang\",\n\t\"version\": \"1.3.0\",\n\t\"description\": \"codemirror language: org\",\n\t\"type\": \"module\",\n\t\"file"
  },
  {
    "path": "packages/codemirror-lang/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/editor/CHANGELOG.md",
    "chars": 1948,
    "preview": "# @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:"
  },
  {
    "path": "packages/editor/README.org",
    "chars": 79,
    "preview": "* TODO Quick Start\n\n* Customization\n** TODO Write a Theme\n** TODO key bindings\n"
  },
  {
    "path": "packages/editor/index.js",
    "chars": 237,
    "preview": "/**\n * @typedef {import('./lib/editor.js').Config} EditorConfig\n */\n\nexport { tags } from '@orgajs/cm-lang'\nexport { mak"
  },
  {
    "path": "packages/editor/lib/actions/fold.js",
    "chars": 1318,
    "preview": "/**\n * @file Actions to shift sections.\n *\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {i"
  },
  {
    "path": "packages/editor/lib/actions/shift.js",
    "chars": 2545,
    "preview": "/**\n * @file Actions to shift sections.\n *\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {i"
  },
  {
    "path": "packages/editor/lib/actions/todo.js",
    "chars": 838,
    "preview": "/**\n * @typedef {import('@codemirror/view').EditorView} EditorView\n */\n\nimport { syntaxTree } from '@codemirror/language"
  },
  {
    "path": "packages/editor/lib/actions/utils.js",
    "chars": 968,
    "preview": "/**\n * @typedef {import('@codemirror/view').EditorView} EditorView\n * @typedef {import('@lezer/common').Tree} Tree\n */\n\n"
  },
  {
    "path": "packages/editor/lib/editor.js",
    "chars": 851,
    "preview": "/**\n * @callback OnChange\n * @param {EditorState} state\n */\n\n/**\n * @typedef Config\n * @property {Element} target\n * @pr"
  },
  {
    "path": "packages/editor/lib/extensions/cleanup.js",
    "chars": 4291,
    "preview": "/**\n * @typedef Range\n * @property {number} from\n * @property {number} to\n *\n * @typedef {object} Options\n * @property {"
  },
  {
    "path": "packages/editor/lib/settings.js",
    "chars": 1358,
    "preview": "/**\n * @typedef {import('@codemirror/state').EditorState} EditorState\n *\n * @typedef {Object} TodoKeywordSet\n * @propert"
  },
  {
    "path": "packages/editor/lib/setup.js",
    "chars": 1110,
    "preview": "import { defaultKeymap } from '@codemirror/commands'\nimport { bracketMatching, foldGutter } from '@codemirror/language'\n"
  },
  {
    "path": "packages/editor/lib/theme.js",
    "chars": 1547,
    "preview": "import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'\nimport { EditorView } from '@codemirror/view'\n"
  },
  {
    "path": "packages/editor/package.json",
    "chars": 764,
    "preview": "{\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\","
  },
  {
    "path": "packages/editor/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/esbuild/CHANGELOG.md",
    "chars": 1033,
    "preview": "# @orgajs/esbuild\n\n## 1.1.5\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @o"
  },
  {
    "path": "packages/esbuild/index.js",
    "chars": 1420,
    "preview": "/**\n * @import { CompileOptions } from '@orgajs/orgx'\n * @import {\n      OnLoadResult,\n      PluginBuild\n * } from 'esbu"
  },
  {
    "path": "packages/esbuild/package.json",
    "chars": 633,
    "preview": "{\n\t\"name\": \"@orgajs/esbuild\",\n\t\"version\": \"1.1.5\",\n\t\"description\": \"esbuild plugin for orgajs\",\n\t\"type\": \"module\",\n\t\"exp"
  },
  {
    "path": "packages/lezer/CHANGELOG.md",
    "chars": 1465,
    "preview": "# @orgajs/lezer\n\n## 1.4.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - orga"
  },
  {
    "path": "packages/lezer/README.org",
    "chars": 171,
    "preview": "#+title: Lezer Parser for org-mode\n\n* Tasks\n\n** TODO properly support incremental parsing\n** TODO finish nodes design\n**"
  },
  {
    "path": "packages/lezer/index.js",
    "chars": 89,
    "preview": "export { OrgParser, parser } from './lib/index.js'\nexport { tags } from './lib/nodes.js'\n"
  },
  {
    "path": "packages/lezer/lib/context.js",
    "chars": 3898,
    "preview": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n *"
  },
  {
    "path": "packages/lezer/lib/fragments.js",
    "chars": 4915,
    "preview": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n *"
  },
  {
    "path": "packages/lezer/lib/handlers.js",
    "chars": 1974,
    "preview": "/**\n * @typedef {import('./types.js').Seed} Seed\n * @typedef {import('./types.js').Handler} Handler\n\n * @typedef {Record"
  },
  {
    "path": "packages/lezer/lib/index.js",
    "chars": 1699,
    "preview": "/**\n * @typedef {import('@lezer/common').PartialParse} PartialParse\n * @typedef {import('@lezer/common').Input} Input\n *"
  },
  {
    "path": "packages/lezer/lib/nodes.js",
    "chars": 1345,
    "preview": "import { NodeProp, NodeSet, NodeType } from '@lezer/common'\nimport { styleTags, Tag, tags as t } from '@lezer/highlight'"
  },
  {
    "path": "packages/lezer/lib/oast-to-lezer.js",
    "chars": 3758,
    "preview": "/**\n * @typedef {import('orga').Document} OrgTree\n * @typedef {import('@lezer/common').Tree} LezerTree\n * @typedef {impo"
  },
  {
    "path": "packages/lezer/lib/tree.js",
    "chars": 2569,
    "preview": "import { NodeProp, NodeType, Tree } from '@lezer/common'\nimport { documentProp } from './handlers.js'\n\n// import { nodes"
  },
  {
    "path": "packages/lezer/lib/types.ts",
    "chars": 930,
    "preview": "import type { Tree as LezerTree, NodeSet } from '@lezer/common'\nimport type { Content, Document, Parent as OastParent, T"
  },
  {
    "path": "packages/lezer/package.json",
    "chars": 696,
    "preview": "{\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"
  },
  {
    "path": "packages/lezer/tests/compare-tree.js",
    "chars": 1266,
    "preview": "import { Tree } from '@lezer/common'\n\n/**\n * @typedef {import('@lezer/common').Tree} Tree\n */\n\n/**\n * @param {Tree} a\n *"
  },
  {
    "path": "packages/lezer/tests/incremental.test.js",
    "chars": 3682,
    "preview": "/**\n * @typedef {{from: number, to?: number, insert?: string}[]} ChangeSpec\n */\n\nimport assert from 'node:assert'\nimport"
  },
  {
    "path": "packages/lezer/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/loader/CHANGELOG.md",
    "chars": 7031,
    "preview": "# Change Log\n\n## 4.4.4\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - @orgajs"
  },
  {
    "path": "packages/loader/LICENSE.org",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "packages/loader/index.cjs",
    "chars": 412,
    "preview": "// stolen code from @mdx-js/loader\n\n/**\n * Webpack loader\n *\n * @todo once webpack supports ESM loaders, remove this wra"
  },
  {
    "path": "packages/loader/index.d.ts",
    "chars": 490,
    "preview": "import type { ProcessorOptions } from '@orgajs/orgx'\nimport type { LoaderContext } from 'webpack'\n\n/**\n * A Webpack load"
  },
  {
    "path": "packages/loader/lib/index.js",
    "chars": 727,
    "preview": "/**\n * @typedef {import('webpack').LoaderContext<unknown>} LoaderContext\n */\n\nimport path from 'node:path'\nimport { crea"
  },
  {
    "path": "packages/loader/package.json",
    "chars": 852,
    "preview": "{\n\t\"name\": \"@orgajs/loader\",\n\t\"version\": \"4.4.4\",\n\t\"description\": \"Load org-mode content through orga.\",\n\t\"type\": \"modul"
  },
  {
    "path": "packages/loader/tests/compiler.js",
    "chars": 1141,
    "preview": "import { promises as fs } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { promisify } from 'node:util'\n"
  },
  {
    "path": "packages/loader/tests/example.md",
    "chars": 37,
    "preview": "# hello world\n\nthis is some content.\n"
  },
  {
    "path": "packages/loader/tests/fixture.org",
    "chars": 119,
    "preview": "#+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",
    "chars": 1248,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { compile } from './compiler.js'\n\ntest('basic "
  },
  {
    "path": "packages/metadata/CHANGELOG.md",
    "chars": 3198,
    "preview": "# @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- a53cfe"
  },
  {
    "path": "packages/metadata/README.org",
    "chars": 26,
    "preview": "#+title: @orgajs/metadata\n"
  },
  {
    "path": "packages/metadata/index.js",
    "chars": 105,
    "preview": "/**\n * @typedef {import('./lib/index.js').Metadata} Metadata\n */\n\nexport { parse } from './lib/index.js'\n"
  },
  {
    "path": "packages/metadata/lib/index.js",
    "chars": 1494,
    "preview": "/**\n * TODO: more types?\n * @typedef {string} Value\n * @typedef {Record<string, Value | Value[]>} Metadata\n */\n\nconst TO"
  },
  {
    "path": "packages/metadata/package.json",
    "chars": 665,
    "preview": "{\n\t\"name\": \"@orgajs/metadata\",\n\t\"version\": \"2.4.1\",\n\t\"description\": \"extract metadata info from org file\",\n\t\"type\": \"mod"
  },
  {
    "path": "packages/metadata/tests/test.js",
    "chars": 1060,
    "preview": "import * as assert from 'node:assert'\nimport { describe, it } from 'node:test'\nimport { parse } from '../index.js'\n\ndesc"
  },
  {
    "path": "packages/metadata/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/next/README.org",
    "chars": 350,
    "preview": "* @orgajs/next\n\nNext.js integration is now maintained in a standalone repository:\n\n- [[https://github.com/orgapp/orga-ne"
  },
  {
    "path": "packages/node-loader/CHANGELOG.md",
    "chars": 1022,
    "preview": "# @orgajs/node-loader\n\n## 1.1.5\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  "
  },
  {
    "path": "packages/node-loader/index.js",
    "chars": 2387,
    "preview": "/**\n * @import {LoadFnOutput, LoadHook, LoadHookContext} from 'node:module'\n * @import {ProcessorOptions} from '@orgajs/"
  },
  {
    "path": "packages/node-loader/package.json",
    "chars": 601,
    "preview": "{\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\"in"
  },
  {
    "path": "packages/oast-to-hast/.projectile",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/oast-to-hast/CHANGELOG.md",
    "chars": 6917,
    "preview": "# Change Log\n\n## 4.5.3\n\n### Patch Changes\n\n- 850bcf9: fix: use native anchor for external links to prevent wouter pushSt"
  },
  {
    "path": "packages/oast-to-hast/LICENSE.org",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "packages/oast-to-hast/index.js",
    "chars": 194,
    "preview": "/**\n * @typedef {import('./lib/index.js').Options} Options\n */\n\nexport { handlers as defaultHandlers } from './lib/handl"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/block.js",
    "chars": 1950,
    "preview": "import { parseHtml } from './html.js'\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Block"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/document.js",
    "chars": 253,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Document} node\n * @returns {import('hast').R"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/footnote.js",
    "chars": 839,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').FootnoteReference} node\n * @returns {import("
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/headline.js",
    "chars": 300,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Headline} node\n * @returns {import('hast').E"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/hr.js",
    "chars": 275,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').HorizontalRule} node\n * @returns {import('ha"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/html.js",
    "chars": 741,
    "preview": "import { fromHtml } from 'hast-util-from-html'\n\n/**\n * @param {import('../state.js').State} state\n * @param {import('org"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/index.js",
    "chars": 1389,
    "preview": "import { block } from './block.js'\nimport { document } from './document.js'\nimport { footnote, footnoteRef } from './foo"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/keyword.js",
    "chars": 377,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Keyword} node\n * @returns {import('hast').El"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/latex.js",
    "chars": 352,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Latex} node\n * @returns {import('hast').Elem"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/link.js",
    "chars": 2075,
    "preview": "/**\n * @import { Element } from 'hast'\n */\n\nimport mime from 'mime'\n\n/**\n * @param {import('../state.js').State} state\n "
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/list.js",
    "chars": 2002,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').List} node\n * @returns {import('hast').Eleme"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/newline.js",
    "chars": 478,
    "preview": "/**\n * @param {import('../state.js').State} _state\n * @param {import('orga').Newline} _node\n * @param {import('orga').Pa"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/paragraph.js",
    "chars": 1580,
    "preview": "/**\n * Block-level HTML elements that are not allowed as descendants of <p>.\n * When a paragraph contains any of these, "
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/section.js",
    "chars": 1251,
    "preview": "/**\n * @param {import('../state.js').State} state\n * @param {import('orga').Section} node\n * @returns {import('hast').El"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/table.js",
    "chars": 1886,
    "preview": "/**\n * @import {Element,ElementContent} from 'hast'\n * @import {Table,TableCell,TableRow} from 'orga'\n * @import {State}"
  },
  {
    "path": "packages/oast-to-hast/lib/handlers/text.js",
    "chars": 656,
    "preview": "/**\n * @import {Element,Text} from 'hast'\n *\n */\n\nconst wrapper = {\n\tbold: 'strong',\n\titalic: 'i',\n\tcode: 'code',\n\tverba"
  },
  {
    "path": "packages/oast-to-hast/lib/index.js",
    "chars": 759,
    "preview": "/**\n * @typedef {import('hast').Nodes} HastNodes\n * @typedef {import('orga').Nodes} OastNodes\n * @typedef {Partial<impor"
  },
  {
    "path": "packages/oast-to-hast/lib/state.js",
    "chars": 3375,
    "preview": "/**\n * @typedef {import('hast').Nodes} HastNodes\n\t @import {ElementContent as HastElementContent,Root as HastRoot} from "
  },
  {
    "path": "packages/oast-to-hast/package.json",
    "chars": 701,
    "preview": "{\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."
  },
  {
    "path": "packages/oast-to-hast/tests/block.js",
    "chars": 862,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { parse } from "
  },
  {
    "path": "packages/oast-to-hast/tests/classname.js",
    "chars": 793,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { parse } from 'orga'\nimport { toHast } from '"
  },
  {
    "path": "packages/oast-to-hast/tests/heading.js",
    "chars": 318,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from"
  },
  {
    "path": "packages/oast-to-hast/tests/list.js",
    "chars": 2467,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from"
  },
  {
    "path": "packages/oast-to-hast/tests/paragraph.js",
    "chars": 2170,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { h } from 'hastscript'\nimport { toHast } from"
  },
  {
    "path": "packages/oast-to-hast/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/oast-to-prose/CHANGELOG.md",
    "chars": 374,
    "preview": "# 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: "
  },
  {
    "path": "packages/oast-to-prose/index.js",
    "chars": 113,
    "preview": "/**\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",
    "chars": 449,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/headline.js",
    "chars": 417,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/index.js",
    "chars": 574,
    "preview": "import { block } from './block.js'\nimport { headline } from './headline.js'\nimport { link } from './link.js'\nimport { ne"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/link.js",
    "chars": 436,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/newline.js",
    "chars": 254,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/paragraph.js",
    "chars": 395,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/section.js",
    "chars": 336,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/stars.js",
    "chars": 320,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/tags.js",
    "chars": 351,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/text.js",
    "chars": 295,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/handlers/todo.js",
    "chars": 352,
    "preview": "/**\n * @typedef {import('prosemirror-model').Node} ProseNode\n */\n\n/**\n * @param {import('../state.js').State} state\n * @"
  },
  {
    "path": "packages/oast-to-prose/lib/index.js",
    "chars": 1227,
    "preview": "/**\n * @typedef {import('orga').Document} OastRoot\n * @typedef {import('orga').Content} OastContent\n * @typedef {import("
  },
  {
    "path": "packages/oast-to-prose/lib/schema.js",
    "chars": 2403,
    "preview": "import { Schema } from 'prosemirror-model'\n\nexport const defaultSchema = new Schema({\n\tnodes: {\n\t\tdoc: {\n\t\t\tcontent: 'bl"
  },
  {
    "path": "packages/oast-to-prose/lib/state.js",
    "chars": 3413,
    "preview": "/**\n * @typedef {import('orga').Document} OastRoot\n * @typedef {import('orga').Content} OastContent\n * @typedef {import("
  },
  {
    "path": "packages/oast-to-prose/package.json",
    "chars": 640,
    "preview": "{\n\t\"name\": \"oast-to-prose\",\n\t\"version\": \"1.3.1\",\n\t\"description\": \"Transform OAST to ProseMirror Document\",\n\t\"author\": \"X"
  },
  {
    "path": "packages/oast-to-prose/tests/text.js",
    "chars": 555,
    "preview": "import * as assert from 'node:assert'\nimport test from 'node:test'\nimport { toProse } from '../lib/index.js'\n\ntest('test"
  },
  {
    "path": "packages/oast-to-prose/tsconfig.json",
    "chars": 38,
    "preview": "{\n\t\"extends\": \"../../tsconfig.json\"\n}\n"
  },
  {
    "path": "packages/orga/.projectile",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "packages/orga/CHANGELOG.md",
    "chars": 7986,
    "preview": "# Change Log\n\n## 4.7.1\n\n### Patch Changes\n\n- bd2365a: fix types and linting\n- Updated dependencies [bd2365a]\n  - text-ki"
  },
  {
    "path": "packages/orga/LICENSE.org",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2015 gatsbyjs\n\nPermission is hereby granted, free of charge, to any person obtainin"
  },
  {
    "path": "packages/orga/README.org",
    "chars": 2128,
    "preview": "* 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#+BE"
  },
  {
    "path": "packages/orga/package.json",
    "chars": 780,
    "preview": "{\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"
  },
  {
    "path": "packages/orga/src/__tests__/block/affiliated keyword.json",
    "chars": 4937,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {\n    \"nop\": \"code_block\"\n  },\n  \"children\": [\n    {\n      \"type\": \"keyword\",\n  "
  },
  {
    "path": "packages/orga/src/__tests__/block/affiliated keyword.org",
    "chars": 236,
    "preview": "#+NAME: code_block\n#+BEGIN_SRC javascript\nconsole.log('named code block')\n#+END_SRC\n\n#+NAME: code_block\n\n#+BEGIN_SRC jav"
  },
  {
    "path": "packages/orga/src/__tests__/block/export.json",
    "chars": 2028,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"html\",\n      \"value\": \"<h1>Hello</h1>\","
  },
  {
    "path": "packages/orga/src/__tests__/block/export.org",
    "chars": 72,
    "preview": "#+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",
    "chars": 2165,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n       "
  },
  {
    "path": "packages/orga/src/__tests__/block/missing begin.org",
    "chars": 52,
    "preview": "console.log('hello')\nconsole.log('world')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/missing end.json",
    "chars": 2957,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n       "
  },
  {
    "path": "packages/orga/src/__tests__/block/missing end.org",
    "chars": 65,
    "preview": "#+BEGIN_SRC javascript\nconsole.log('hello')\nconsole.log('world')\n"
  },
  {
    "path": "packages/orga/src/__tests__/block/standard.json",
    "chars": 1544,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"block\",\n      \"name\": \"SRC\",\n      \"par"
  },
  {
    "path": "packages/orga/src/__tests__/block/standard.org",
    "chars": 75,
    "preview": "#+BEGIN_SRC javascript\nconsole.log('hello')\nconsole.log('world')\n#+END_SRC\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/multiline.json",
    "chars": 7716,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n       "
  },
  {
    "path": "packages/orga/src/__tests__/footnote/multiline.org",
    "chars": 87,
    "preview": "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",
    "chars": 5802,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n       "
  },
  {
    "path": "packages/orga/src/__tests__/footnote/standard.org",
    "chars": 59,
    "preview": "reference footnote [fn:1]\n\n[fn:1] Content of the footnote.\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by empty lines.json",
    "chars": 7014,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"c"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by empty lines.org",
    "chars": 96,
    "preview": "[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",
    "chars": 5432,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"c"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by footnote.org",
    "chars": 83,
    "preview": "[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",
    "chars": 5088,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"footnote\",\n      \"label\": \"1\",\n      \"c"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/stopped by headline.org",
    "chars": 71,
    "preview": "[fn:1] Content of the footnote.\nAnd here is another line.\n* A Headline\n"
  },
  {
    "path": "packages/orga/src/__tests__/footnote/with block.json",
    "chars": 6895,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"paragraph\",\n      \"children\": [\n       "
  },
  {
    "path": "packages/orga/src/__tests__/footnote/with block.org",
    "chars": 132,
    "preview": "reference footnote [fn:1]\n\n[fn:1] Content of the footnote.\n#+BEGIN_SRC javascript\nconsole.log('footnote with code block'"
  },
  {
    "path": "packages/orga/src/__tests__/headline/broken drawer.json",
    "chars": 7048,
    "preview": "{\n  \"type\": \"document\",\n  \"properties\": {},\n  \"children\": [\n    {\n      \"type\": \"section\",\n      \"level\": 1,\n      \"prop"
  }
]

// ... and 239 more files (download for full content)

About this extraction

This page contains the full source code of the xiaoxinghu/orgajs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 439 files (820.0 KB), approximately 236.4k tokens, and a symbol index with 340 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!