todo-backend: add support for configuring the default parser
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -42,6 +42,7 @@ JavaScript
|
||||
Kaewkasi
|
||||
Knex
|
||||
Kumar
|
||||
Leasot
|
||||
Lerna
|
||||
Lundberg
|
||||
Luxon
|
||||
|
||||
@@ -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[];
|
||||
|
||||
Reference in New Issue
Block a user