# core/producers/tool.revive.producer.ts

> 54 lines of code and 15 definitions.

Tree: GovLab Quality
Language: typescript
Layer: application
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-producers-tool-revive-producer-ts
Source text: https://banes-lab.com/source/quality/core/producers/tool.revive.producer.ts.txt

Listed in [core/producers](https://banes-lab.com/api/source/quality/core/producers.md), after [core/producers/tool.pylint.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.pylint.producer.ts.md) and before [core/producers/tool.rubocop.producer.ts](https://banes-lab.com/source/quality/core/producers/tool.rubocop.producer.ts.md).

## Definitions

- `TOOL` (lexical_declaration, line 6)
- `VERSION` (lexical_declaration, line 7)
- `SOURCE` (lexical_declaration, line 8)
- `DOCS` (lexical_declaration, line 9)
- `HEADER_PREFIX` (lexical_declaration, line 10)
- `ALPHA` (lexical_declaration, line 11)
- `Section` (interface_declaration, line 13)
- `sectionsOf` (lexical_declaration, line 18)
- `sections` (lexical_declaration, line 19)
- `last` (lexical_declaration, line 21)
- `line` (lexical_declaration, line 22)
- `ruleOf` (lexical_declaration, line 34)
- `{ description, header }` (lexical_declaration, line 35)
- `produce` (lexical_declaration, line 53)
- `rules` (lexical_declaration, line 54)

## Contained in

- [core/producers](https://banes-lab.com/anatomy/quality/folder-quality-core-producers.md)

## Source

```typescript
import type { CatalogProduct, CatalogRule } from "#types/catalog.types";
import { byRuleId } from "#core/comparators/rule.comparator";
import { defineProducer } from "#core/registries/producer.registry";
import { remoteText } from "#core/adapters/remote.adapter";

const TOOL = "revive";
const VERSION = "master";
const SOURCE = "https://raw.githubusercontent.com/mgechev/revive/master/RULES_DESCRIPTIONS.md";
const DOCS = "https://revive.run/r#";
const HEADER_PREFIX = "## ";
const ALPHA: ReadonlySet<string> = new Set("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");

interface Section {
    description: string | null;
    header: string;
}

const sectionsOf = function sectionsOf(lines: readonly string[]): Section[] {
    const sections: Section[] = [];
    for (const raw of lines) {
        const last = sections.at(-1);
        const line = raw.trim();
        if (raw.startsWith(HEADER_PREFIX)) {
            sections.push({ description: null, header: raw.slice(HEADER_PREFIX.length).trim() });
            continue;
        }
        if (last?.description === null && line !== "" && ALPHA.has(line[0] ?? "")) {
            last.description = line;
        }
    }
    return sections;
};

const ruleOf = function ruleOf(section: Section): CatalogRule[] {
    const { description, header } = section;
    return header === "" || header.includes(" ")
        ? []
        : [
              {
                  canonical: null,
                  category: "rule",
                  description,
                  ecosystem: "go",
                  name: header,
                  ruleId: header,
                  tool: TOOL,
                  toolVersion: VERSION,
                  url: `${DOCS}${header}`,
              },
          ];
};

const produce = async function produce(): Promise<CatalogProduct[]> {
    const rules = sectionsOf(((await remoteText(SOURCE)) ?? "").split("\n"))
        .flatMap(ruleOf)
        .toSorted(byRuleId);
    return [{ rules, source: TOOL, summary: { tool: TOOL, toolVersion: VERSION, total: rules.length } }];
};

defineProducer({ name: TOOL, produce, refresh: "manual" });
```
