# core/parsers/specifier.parser.ts

> 30 lines of code and 9 definitions.

Tree: GovLab Quality
Language: typescript
Layer: processing
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-parsers-specifier-parser-ts
Source text: https://banes-lab.com/source/quality/core/parsers/specifier.parser.ts.txt

Listed in [core/parsers](https://banes-lab.com/api/source/quality/core/parsers.md), after [core/parsers/report.parser.ts](https://banes-lab.com/source/quality/core/parsers/report.parser.ts.md) and before [core/parsers/tool.actionlint.parser.ts](https://banes-lab.com/source/quality/core/parsers/tool.actionlint.parser.ts.md).

## Definitions

- `specifiersIn` (lexical_declaration, line 18, exported)
- `quotedAfter` (lexical_declaration, line 5)
- `i` (lexical_declaration, line 6)
- `quote` (lexical_declaration, line 10)
- `close` (lexical_declaration, line 14)
- `found` (lexical_declaration, line 19, exported)
- `at` (lexical_declaration, line 21, exported)
- `before` (lexical_declaration, line 23, exported)
- `quoted` (lexical_declaration, line 24, exported)

## Contained in

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

## Used by

- [core/loaders/coverage.loader.ts](https://banes-lab.com/source/quality/core/loaders/coverage.loader.ts.md)

## Linked from

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

## Source

```typescript
import { QUOTES, SPECIFIER_KEYWORDS } from "#configuration/constants/specifier.constants";
import { isWhitespace } from "@govlab/constants";
import { isWordBoundary } from "#core/matchers/word.matcher";

const quotedAfter = function quotedAfter(text: string, at: number): string | null {
    let i = at;
    while (i < text.length && (isWhitespace(text.charAt(i)) || text.charAt(i) === "(")) {
        i += 1;
    }
    const quote = text.charAt(i);
    if (!QUOTES.has(quote)) {
        return null;
    }
    const close = text.indexOf(quote, i + 1);
    return close === -1 ? null : text.slice(i + 1, close);
};

export const specifiersIn = function specifiersIn(text: string): string[] {
    const found: string[] = [];
    for (const keyword of SPECIFIER_KEYWORDS) {
        let at = text.indexOf(keyword);
        while (at !== -1) {
            const before = at === 0 ? "" : text.charAt(at - 1);
            const quoted = isWordBoundary(before) ? quotedAfter(text, at + keyword.length) : null;
            if (quoted !== null && quoted.length > 0) {
                found.push(quoted);
            }
            at = text.indexOf(keyword, at + 1);
        }
    }
    return found;
};
```
