Skip to content

transistorsoft/docforge

Repository files navigation

Transistor Software

Docforge — harvest once, apply everywhere

DocForge is a toolchain for maintaining a single source of truth for Background Geolocation SDK documentation across all platforms:

  1. Harvest JSDoc from the TypeScript API into a portable YAML docs database (docs-db/*.yaml)
  2. Translate code examples from TypeScript to Swift and Kotlin using Claude skills
  3. Verify translated examples compile against native SDKs
  4. Apply documentation to native source files (Swift, Kotlin)

Requirements

  • Python 3.13+ and uv
  • Git (for the TypeScript source submodule)

Setup

# Clone with all submodules (TS types + native SDKs)
git clone --recurse-submodules <this-repo>

# Or if already cloned, initialize submodules
git submodule update --init --recursive

# Install Python dependencies
uv sync

# Install Claude skills
./install-skills.sh

Submodules

Path Repo Purpose
background-geolocation-types/ TypeScript API types Source of JSDoc for harvesting
native/location-manager-ios/ iOS SDK Target for Swift doc application + verification
native/location-manager-android/ Android SDK Target for Kotlin doc application + verification

The docs database

harvest.py emits one YAML file per symbol, named after the doc id:

  • Foo.yaml
  • Foo.bar.yaml

Each YAML entry looks like:

id: BackgroundGeolocation.onLocation
source_file: background-geolocation-types/src/core/api/BackgroundGeolocation.ts
signature: 'onLocation(cb: ...): Subscription;'
description: |-
  Subscribe to location events.

  @example example-1
examples:
  example-1:
    title: Example 1
    code:
      ts: |-
        // ...
      objc: |-
        // ...

Important conventions:

  • description is markdown-ish and may contain example placeholders like @example example-1.
  • examples.<key>.code is a map of language → snippet (ts, objc, kotlin, …).
  • When applying, Docforge inserts the chosen language snippet at the placeholder location.

Harvesting docs (TypeScript → YAML)

1) Seed a docs database

# Harvest from the default TypeScript root (background-geolocation-types/src)
uv run forge harvest --seed --out-dir docs-db

# Or harvest from a custom TypeScript root
uv run forge harvest --seed --source /path/to/your/types/src --out-dir docs-db

Useful options:

  • --source PATH — TypeScript source root to harvest (default: background-geolocation-types/src).
  • --limit N — stop after writing N YAML files (debugging).
  • --prune — delete YAML files in --out-dir that were not generated in this run (keeps the db tidy).

2) Insert doc-id markers into TypeScript (optional, but recommended)

To make it easy to reference symbols later, you can insert/update a doc-id marker at the top of each harvestable JSDoc block:

# Insert into the default TS root
uv run forge harvest --insert-doc-ids

# Or target a custom TS root
uv run forge harvest --insert-doc-ids --source /path/to/your/types/src

This produces JSDoc blocks like:

/**
 * <!-- doc-id: ActivityType -->
 * iOS Activity Type used with {@link GeoConfig.activityType}.
 */
export const ActivityType = {
  // ...
}

Notes:

  • --insert-doc-ids skips blocks marked @internal or @hidden.
  • Some internal/hidden mixin-style interfaces may still have public member docs; Docforge can alias containers when harvesting (see code comments in harvest.py).

3) Diagnostic helpers

# Dump normalized doc blocks from a file (paths are relative to --source)
uv run forge harvest --dump core/api/BackgroundGeolocation.ts --max-blocks 3

# Or with an explicit source root
uv run forge harvest --dump --source /path/to/your/types/src core/api/BackgroundGeolocation.ts --max-blocks 3

# Dump extracted description/examples summary
uv run forge harvest --dump-extracted core/api/BackgroundGeolocation.ts --max-blocks 3

Applying docs (YAML → Objective‑C headers)

apply-docs.py walks a source tree, finds Objective‑C docblocks containing:

<!-- doc-id: Module.member -->

…and replaces the surrounding /** ... */ block with the harvested description + examples.

Basic usage

Dry-run (no writes):

uv run forge apply --docs-db docs-db --root ../ios-sdk --ext .h --lang objc --dry-run

Write changes:

uv run forge apply --docs-db docs-db --root ../ios-sdk --ext .h --lang objc --write

Modes

Exactly one of these behaviors is used:

  • --dry-run — compute changes and print a summary (no writes). (Default if no mode is specified.)
  • --check — like --dry-run, but exits 1 if any changes would be made (useful for CI).
  • --write — apply changes to disk.

Key switches

  • --docs-db PATH (required): directory containing *.yaml docs.
  • --root PATH (required): root of the source tree to scan.
  • --ext .h (default: .h): comma-separated list of extensions to scan.
  • --exclude-dirs a,b,c (optional): directory names to skip (defaults include Pods, DerivedData, node_modules, etc.).
  • --lang <key> (required): single example language to apply (eg. objc).
  • --verbose: print per-file/per-id updates and full diffs.
  • --strict: fail if a referenced doc-id is missing from the docs-db.

What happens to examples

The YAML description can contain placeholders like:

@example example-1

When applying:

  • The placeholder is replaced in-place with a rendered block:
    • @example <Title>
    • a fenced code block in your selected --lang

If an example is referenced but missing:

// MISSING example example-1
// Filename: BackgroundGeolocation.onLocation.yaml

If the example exists, but not for the requested language:

// WARNING:  No example block found for lang "objc" for example-1
// Filename: /absolute/path/to/docs-db/BackgroundGeolocation.onLocation.yaml

Output formatting

apply-docs.py normalizes Objective‑C docblocks to the canonical style:

/**
 * <!-- doc-id: BackgroundGeolocation.onLocation -->
 * Subscribe to location events.
 *
 * @example Example 1
 * ```objc
 * // ...
 * ```
 */

This ensures consistent alignment and clean diffs, even if the original header used a compact /**\n* ... style.

End-to-end workflow

Step 1: Harvest (TypeScript → YAML)

uv run forge harvest --seed --out-dir docs-db --prune

This extracts JSDoc from the TypeScript types submodule into docs-db/*.yaml with ts: code examples.

Step 2: Translate examples (TypeScript → Swift / Kotlin)

Using Claude skills (install with ./install-skills.sh):

/translate-docs-swift docs-db/*.yaml       # adds swift: blocks
/translate-docs-kotlin docs-db/*.yaml      # adds kotlin: blocks

After this step, each YAML file has ts:, swift:, and kotlin: code blocks.

Step 3: Verify examples compile

/verify-docs-swift          # compiles Swift examples against iOS SDK
/verify-docs-kotlin         # compiles Kotlin examples against Android SDK

These skills generate test files and run the compiler, iteratively fixing any errors.

Step 4: Apply docs to native source

/apply-docs-swift docs-db/*.yaml       # writes Swift doc comments to iOS source
/apply-docs-kotlin docs-db/*.yaml      # writes KDoc comments to Android source

These skills read the YAML, find the matching symbol in native source code by name, and insert/replace doc comments.

Step 5: Generate platform docs

Run standard doc generators in each native repo:

  • iOS: DocC / Xcode documentation
  • Android: Dokka

Claude Skills

All skills live in skills/ and are symlinked to ~/.claude/skills/ via install-skills.sh.

Skill Purpose
/translate-docs-swift Translate TS examples to Swift in YAML
/translate-docs-kotlin Translate TS examples to Kotlin in YAML
/verify-docs-swift Compile-check Swift examples against iOS SDK
/verify-docs-kotlin Compile-check Kotlin examples against Android SDK
/apply-docs-swift Apply YAML docs as /// comments in iOS Swift source
/apply-docs-kotlin Apply YAML docs as /** */ KDoc in Android Kotlin source

Tips

  • Keep docs-db/ in version control — it’s the canonical single source of truth for all platforms.
  • Run ./install-skills.sh after cloning to set up Claude skills.
  • The YAML database accumulates all language examples in one place — no need to copy between repos.

License

MIT License

Copyright (c) 2026 Transistor Software

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.

About

Python scripts to harvest Typescript docs from Typescript API into a database (expressed as YAML files) and apply those docs to a source-tree of a different language. The database model allows for examples to be written in multiple languages (eg: ts, dart, Swift, Kotlin etc)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors