todo-backend: add support for configuring the default parser

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2021-03-11 21:23:17 +01:00
parent ebeb76822a
commit fd45472213
6 changed files with 84 additions and 24 deletions
+1
View File
@@ -42,6 +42,7 @@ JavaScript
Kaewkasi
Knex
Kumar
Leasot
Lerna
Lundberg
Luxon
+21
View File
@@ -35,3 +35,24 @@ export default async function createPlugin({
return await createRouter({ todoService });
}
```
## Parser Configuration
The `TodoScmReader` accepts a `TodoParser` option, which can be used to configure your own parser. The default one is based on [Leasot](https://github.com/pgilad/leasot) and supports a wide range of languages. You can change the list of supported tags by configuring your own version of the built-in parser, for example:
```ts
import {
TodoScmReader,
createTodoParser,
} from '@backstage/plugin-todo-backend';
// ...
const todoReader = TodoScmReader.fromConfig(config, {
logger,
reader,
parser: createTodoParser({
tags: ['TODO', 'FIXME', 'NOTE', 'XXX'],
}),
});
```
@@ -14,23 +14,19 @@
* limitations under the License.
*/
import { extname } from 'path';
import { UrlReader } from '@backstage/backend-common';
import { ScmIntegrations } from '@backstage/integration';
import { Logger } from 'winston';
import { parse } from 'leasot';
import {
ReadTodosOptions,
ReadTodosResult,
TodoItem,
TodoParser,
TodoReader,
} from './types';
import { Config } from '@backstage/config';
type TodoParser = (ctx: {
content: string;
path: string;
}) => { text: string; author?: string; lineNumber: number }[];
import { createTodoParser } from './createTodoParser';
type Options = {
logger: Logger;
@@ -43,22 +39,6 @@ type CacheItem = {
result: ReadTodosResult;
};
const defaultTodoParser: TodoParser = ({ content, path }) => {
try {
const comments = parse(content, {
extension: extname(path),
});
return comments.map(comment => ({
text: comment.text,
author: comment.ref,
lineNumber: comment.line,
}));
} catch /* ignore unsupported extensions */ {
return [];
}
};
export class TodoScmReader implements TodoReader {
private readonly logger: Logger;
private readonly reader: UrlReader;
@@ -74,7 +54,7 @@ export class TodoScmReader implements TodoReader {
private constructor(options: Options, integrations: ScmIntegrations) {
this.logger = options.logger;
this.reader = options.reader;
this.parser = options.parser ?? defaultTodoParser;
this.parser = options.parser ?? createTodoParser();
this.integrations = integrations;
}
@@ -0,0 +1,44 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { extname } from 'path';
import { parse } from 'leasot';
import { TodoParser } from './types';
export type TodoParserOptions = {
tags?: string[];
};
export function createTodoParser(options: TodoParserOptions = {}): TodoParser {
const { tags = ['TODO', 'FIXME'] } = options;
return ({ content, path }) => {
try {
const comments = parse(content, {
customTags: tags,
extension: extname(path),
});
return comments.map(comment => ({
text: comment.text,
author: comment.ref,
lineNumber: comment.line,
}));
} catch /* ignore unsupported extensions */ {
return [];
}
};
}
@@ -15,6 +15,7 @@
*/
export { TodoScmReader } from './TodoScmReader';
export { createTodoParser } from './createTodoParser';
export type {
TodoItem,
TodoReader,
@@ -51,3 +51,16 @@ export interface TodoReader {
*/
readTodos(options: ReadTodosOptions): Promise<ReadTodosResult>;
}
type TodoParserContext = {
content: string;
path: string;
};
type TodoParserResult = {
text: string;
author?: string;
lineNumber: number;
};
export type TodoParser = (ctx: TodoParserContext) => TodoParserResult[];