# @enesis/lezer-comark

Lezer extensions for Comark block and inline component syntax.

## Status

Active development. The grammar is functional but not yet wired into the editor's decoration pipeline.

## What it does

Adds four syntaxes to `@lezer/markdown`:

| Syntax | Lezer node | Example |
|---|---|---|
| Block component | `BlockComponent` | `::query{type="TODO"}...::` |
| Inline component | `InlineComponent` | `:priority{value="high"}` |
| Inline component (with body) | `InlineComponent` | `:badge[Active]{color="green"}` |
| Span attributes | `Span` | `[text]{.class #id key="val"}` |

## Usage

```typescript
import { parser } from "@lezer/markdown"
import { GFM } from "@lezer/markdown"
import { createComarkExtensions } from "@enesis/lezer-comark"

const fullParser = parser.configure([
  GFM,
  ...createComarkExtensions(),
])
```

## Package structure

```
src/
  index.ts              createComarkExtensions() — barrel export
  types.ts              Attrs, InlineComponentData, BlockComponentData
  attributes.ts         parseAttrs() — parses {key="val" .class #id}
  block-component.ts    LeafBlockParser for ::name{...}...::
  inline-component.ts   InlineParser for :name{...} and :name[...]{...}
  span-attr.ts          InlineParser for [text]{.class #id}
```

## Syntax reference

### Block component

```
::component-name{key="val"}
Content lines
::
```

Children: `ComponentName`, `ComponentAttrs`, `ComponentBody`

### Inline component (props only)

```
:priority{value="high"}
```

### Inline component (content + props)

```
:badge[Active]{color="green"}
```

### Span attributes

```
[highlighted text]{.highlight .yellow #ref-1}
```

Nested markdown is supported inside spans:

```
[**Bold** and *italic* text]{.emphasized}
```

### Attribute syntax

| Syntax | Result |
|---|---|
| `{key="value"}` | `{ key: "value" }` |
| `{boolflag}` | `{ boolflag: true }` |
| `{.class-one .class-two}` | `{ class: "class-one class-two" }` |
| `{#my-id}` | `{ id: "my-id" }` |

## What's implemented vs deferred

### ✅ Implemented

| Feature | Nodes |
|---|---|
| `::component{attrs}...::` blocks | `BlockComponent`, `ComponentName`, `ComponentAttrs`, `ComponentBody` |
| `:component{attrs}` inline | `InlineComponent`, `ComponentName`, `ComponentAttrs` |
| `:component[body]{attrs}` inline | `InlineComponent`, `ComponentName`, `ComponentBody`, `ComponentAttrs` |
| `[text]{.class #id}` spans | `Span`, `SpanBody`, `SpanAttrs` |
| `{key="val" .class #id bool}` attrs | `parseAttrs()` utility |

### ❌ Not yet implemented (future)

| Feature | Priority | Notes |
|---|---|---|
| `:emoji:` | Low | Simple pattern extension when needed |
| `<!-- comments -->` | Low | Simple when needed |
| Frontmatter `---\nkey: val\n---` | Medium | Useful for property schemas in documents |
| Block `{attrs}` on `# h1`, `- list` | Low | Trailing `{...}` on standard elements |
| Code block `{filename}` `{highlights}` | Low | Comark code block metadata |
| Component `#slot` | Low | Named slots for complex components |
| YAML block props inside components | Medium | `\`\`\`yaml [props]\nkey: val\n\`\`\`` inside components |
| Nested components `:::outer\n:::inner\n:::\n::` | Low | Component nesting |
| Property `<`/`>`/`==` queries | Medium | Type-aware comparison ops in query attrs |

## What the editor already handles (GFM + custom)

The editor's `@lezer/markdown` parser is configured with `GFM` (tables, task lists, strikethrough, autolinks) plus custom extensions for page refs, block refs, tags, highlights, inline math, and task states. Comark extensions add on top of these — they don't replace them.

## Roadmap

### Phase 1 — Grammar (this package)
- [x] Block component parser
- [x] Inline component parser
- [x] Span attribute parser
- [x] Attrs utility
- [x] TypeScript types

### Phase 2 — Editor integration (in @enesis/editor)
- [ ] Wire `createComarkExtensions()` into `markdown-extensions.ts`
- [ ] Create `createBlockComponentRule()` and `createInlineComponentRule()` in the rule engine
- [ ] Build component registry (`comark-registry.ts`)
- [ ] Build `::note`/`::tip`/`::warning`/`::caution` callout renderers
- [ ] Build `::query` renderer with GraphService
- [ ] Add `:` trigger to pattern plugin for property autocomplete

### Phase 3 — Typed properties
- [ ] Add `type` column to properties table
- [ ] Index typed properties from `:priority{type="enum" value="high"}`
- [ ] Property schema definitions (`::schema` block or frontmatter)
- [ ] Property autocomplete with type-aware values

### Phase 4 — Advanced comark features
- [ ] Block `{attrs}` on headings, lists, paragraphs, blockquotes
- [ ] Element `{attrs}` on bold, italic, links, images, inline code
- [ ] Span vs. block attribute disambiguation (`[span]{attrs}` vs `[text] {attrs}`)
- [ ] Frontmatter parsing
- [ ] YAML block props
- [ ] Named slots (`#slot-name` inside block components)
- [ ] Nested components (`:::outer\n:::inner:::`)
- [ ] Emoji (`:smile:`)
- [ ] Comments (`<!-- -->`)
- [ ] Data binding (`:` prefixed attrs — semantic, not parsing)
