codoc 0.1.0

Unified documentation parser for Ruby and TypeScript codebases
Documentation
# Codoc Unified Documentation Schema

A unified JSON schema for documenting Ruby (Yardoc) and TypeScript (TypeDoc) codebases.

## Design Principles

1. **Simplicity over completeness** - Captures what's needed for rendering documentation, not every AST detail
2. **Language-neutral where possible** - Common abstractions for similar concepts
3. **Language-specific where necessary** - Ruby concerns, TypeScript interfaces, etc.
4. **Flat references** - Uses `ref` IDs for cross-linking instead of deep nesting
5. **Human-readable** - Clear property names, sensible defaults
6. **Linkable** - Symbol table and external link mappings enable documentation generators to create hyperlinks

## Core Entity Types

| Kind | Description | Ruby | TypeScript |
|------|-------------|------|------------|
| `module` | Namespace/container | Module | Namespace, Module |
| `class` | Class definition | Class | Class |
| `interface` | Type contract | - | Interface |
| `type` | Type alias | - | Type alias |
| `enum` | Enumeration | - | Enum |
| `method` | Instance method | Method | Method |
| `function` | Standalone function | Module function | Function |
| `property` | Instance property | `attr_*` | Property |
| `constant` | Constant value | Constant | Const |

## Type References

Types are represented uniformly with a `kind` discriminator:

```json
// Simple type
{ "name": "String", "kind": "simple" }

// Generic type: Array<String>
{ "name": "Array", "kind": "generic", "args": [{ "name": "String", "kind": "simple" }] }

// Union type: String | null
{ "name": "", "kind": "union", "members": [
  { "name": "String", "kind": "simple" },
  { "name": "null", "kind": "simple" }
]}

// Nullable shorthand
{ "name": "String", "kind": "simple", "nullable": true }
```

## Documentation Fields

Every entity can have a `docs` object:

```json
{
  "docs": {
    "summary": "Brief one-liner",
    "description": "Full description with markdown",
    "examples": [{ "code": "...", "language": "ruby" }],
    "see": [{ "text": "Related", "ref": "SomeClass" }],
    "notes": ["Important note"],
    "deprecated": { "message": "Use X instead", "replacement": "X" },
    "tags": { "custom_tag": "value" }
  }
}
```

## Ruby-Specific Features

### Concerns and Mixins

```json
{
  "kind": "module",
  "isConcern": true,
  "instanceMethods": [...],
  "classMethods": [...]
}
```

### Module Inclusion

```json
{
  "kind": "class",
  "includes": [{ "name": "Enumerable", "kind": "simple" }],
  "prepends": [{ "name": "SomePrepend", "kind": "simple" }]
}
```

### Hash Options (`@option` tags)

```json
{
  "name": "options",
  "type": { "name": "Hash", "kind": "simple" },
  "options": [
    { "name": "format", "type": { "name": "Symbol", "kind": "simple" }, "description": "..." },
    { "name": "prefix", "type": { "name": "String", "kind": "simple" }, "required": false }
  ]
}
```

### Yield Blocks

```json
{
  "yields": {
    "description": "Yields for configuration",
    "params": [{ "name": "config", "type": { "name": "Config", "kind": "simple" } }],
    "returns": { "name": "void", "kind": "simple" }
  }
}
```

## TypeScript-Specific Features

### Generic Type Parameters

```json
{
  "typeParams": [
    {
      "name": "T",
      "constraint": { "name": "Element", "kind": "simple" },
      "default": { "name": "HTMLElement", "kind": "simple" }
    }
  ]
}
```

### Interfaces with Index Signatures

```json
{
  "kind": "interface",
  "indexSignatures": [{
    "keyType": { "name": "string", "kind": "simple" },
    "valueType": { "name": "unknown", "kind": "simple" }
  }]
}
```

### Method Overloads

```json
{
  "kind": "method",
  "overloads": [
    { "params": [...], "returns": {...} },
    { "params": [...], "returns": {...} }
  ]
}
```

## ID Convention

Entity IDs follow a consistent pattern:

- `ModuleName` - Top-level module
- `ModuleName::ClassName` - Nested class (Ruby style, works for both)
- `ClassName#methodName` - Instance method
- `ClassName.methodName` - Static/class method
- `ClassName.propertyName` - Property

## Linking System

The schema provides a comprehensive linking system for documentation generators.

### Symbol Table

The `symbols` array provides a flat lookup table of all documented entities:

```json
{
  "symbols": [
    {
      "id": "EventBus",
      "name": "EventBus",
      "qualifiedName": "EventBus",
      "kind": "class",
      "parent": null,
      "file": "src/EventBus.ts",
      "line": 25,
      "signature": "EventBus<TSource = unknown>"
    },
    {
      "id": "EventBus#on",
      "name": "on",
      "qualifiedName": "EventBus#on",
      "kind": "method",
      "parent": "EventBus",
      "file": "src/EventBus.ts",
      "line": 45,
      "signature": "on(eventNames, callback, signal?)"
    }
  ]
}
```

### ID Prefix

When combining documentation from multiple sources (e.g., a project with both Ruby and TypeScript), use `idPrefix`:

```json
{
  "metadata": {
    "name": "my-project",
    "language": "typescript",
    "idPrefix": "ts:"
  }
}
```

All entity IDs will be prefixed: `ts:EventBus`, `ts:EventBus#on`, etc.

### Internal References

Use `ref` in `TypeReference` to link to documented entities:

```json
{
  "type": {
    "name": "EventBus",
    "kind": "simple",
    "ref": "EventBus"
  }
}
```

### External Symbol Link Mappings

Configure external documentation links via `externalLinks` in metadata:

```json
{
  "metadata": {
    "externalLinks": {
      "typescript": {
        "baseUrl": "https://developer.mozilla.org/en-US/docs/Web/API",
        "urlTemplate": "{baseUrl}/{name}",
        "symbols": {
          "EventTarget": "https://developer.mozilla.org/en-US/docs/Web/API/EventTarget",
          "Element": "https://developer.mozilla.org/en-US/docs/Web/API/Element"
        }
      },
      "ruby": {
        "baseUrl": "https://ruby-doc.org/core-3.3.0",
        "urlTemplate": "{baseUrl}/{qualifiedName}.html",
        "transform": {
          "nameSeparator": "/",
          "methodPrefix": "#method-i-",
          "classMethodPrefix": "#method-c-"
        }
      },
      "rails": {
        "baseUrl": "https://api.rubyonrails.org/classes",
        "urlTemplate": "{baseUrl}/{qualifiedName}.html",
        "transform": { "nameSeparator": "/" },
        "symbols": {
          "ActiveRecord::Base": "https://api.rubyonrails.org/classes/ActiveRecord/Base.html"
        }
      }
    }
  }
}
```

Reference external types with `package` and `qualifiedName`:

```json
{
  "type": {
    "name": "EventTarget",
    "kind": "simple",
    "package": "typescript",
    "qualifiedName": "EventTarget"
  }
}
```

### Unresolved References

The `unresolvedReferences` array lists symbols that couldn't be resolved:

```json
{
  "unresolvedReferences": [
    {
      "name": "JQuery",
      "qualifiedName": "JQuery",
      "package": "jquery",
      "referencedFrom": ["HybridElement"]
    }
  ]
}
```

This helps documentation generators identify missing external link mappings.

### Link Resolution Algorithm

For a documentation generator to resolve a type reference:

1. If `ref` is set → look up in `symbols` array (internal link)
2. If `package` is set → look up in `externalLinks[package]`:
   - Check `symbols[qualifiedName]` for explicit URL
   - Otherwise, apply `urlTemplate` with `transform` rules
3. If neither → unlinked type name

## Comparison with TypeDoc JSON

| Aspect | TypeDoc | Codoc |
|--------|---------|-------|
| Type representation | Complex nested structure with `kindString` | Simple `kind` discriminator |
| References | Numeric IDs with separate symbol table | String IDs inline |
| Documentation | Split across `comment.summary`, `comment.blockTags` | Unified `docs` object |
| Visibility | `flags.isPrivate`, `flags.isProtected` | Single `visibility` field |
| Source location | Nested `sources[0].fileName` | Flat `location.file` |

## Root Structure

```json
{
  "schema": "codoc/v1",
  "metadata": {
    "name": "project-name",
    "version": "1.0.0",
    "language": "typescript",
    "generatedAt": "2025-12-16T10:00:00Z",
    "sourceRoot": "src",
    "idPrefix": "ts:",
    "files": ["..."],
    "externalLinks": { "..." }
  },
  "entities": [ "..." ],
  "symbols": [ "..." ],
  "unresolvedReferences": [ "..." ]
}
```

## Files

- `schema.json` - JSON Schema definition
- `examples/typescript-example.json` - TypeScript example with external link mappings
- `examples/ruby-example.json` - Ruby example with external link mappings