| import { Spec, Line, BlockMarkers, Markers } from '../../primitives.js'; |
| import { Tokenizer } from './index.js'; |
| |
| /** |
| * Walks over provided lines joining description token into a single string. |
| * */ |
| export type Joiner = (lines: Line[], markers?: BlockMarkers) => string; |
| |
| /** |
| * Shortcut for standard Joiners |
| * compact - strip surrounding whitespace and concat lines using a single string |
| * preserve - preserves original whitespace and line breaks as is |
| */ |
| export type Spacing = 'compact' | 'preserve' | Joiner; |
| |
| /** |
| * Makes no changes to `spec.lines[].tokens` but joins them into `spec.description` |
| * following given spacing srtategy |
| * @param {Spacing} spacing tells how to handle the whitespace |
| * @param {BlockMarkers} markers tells how to handle comment block delimitation |
| */ |
| export default function descriptionTokenizer( |
| spacing: Spacing = 'compact', |
| markers = Markers |
| ): Tokenizer { |
| const join = getJoiner(spacing); |
| return (spec: Spec): Spec => { |
| spec.description = join(spec.source, markers); |
| return spec; |
| }; |
| } |
| |
| export function getJoiner(spacing: Spacing): Joiner { |
| if (spacing === 'compact') return compactJoiner; |
| if (spacing === 'preserve') return preserveJoiner; |
| |
| return spacing; |
| } |
| |
| function compactJoiner(lines: Line[], markers = Markers): string { |
| return lines |
| .map(({ tokens: { description } }: Line) => description.trim()) |
| .filter((description) => description !== '') |
| .join(' '); |
| } |
| |
| const lineNo = (num: number, { tokens }: Line, i: number) => |
| tokens.type === '' ? num : i; |
| |
| const getDescription = ({ tokens }: Line) => |
| (tokens.delimiter === '' ? tokens.start : tokens.postDelimiter.slice(1)) + |
| tokens.description; |
| |
| function preserveJoiner(lines: Line[], markers = Markers): string { |
| if (lines.length === 0) return ''; |
| |
| // skip the opening line with no description |
| if ( |
| lines[0].tokens.description === '' && |
| lines[0].tokens.delimiter === markers.start |
| ) |
| lines = lines.slice(1); |
| |
| // skip the closing line with no description |
| const lastLine = lines[lines.length - 1]; |
| |
| if ( |
| lastLine !== undefined && |
| lastLine.tokens.description === '' && |
| lastLine.tokens.end.endsWith(markers.end) |
| ) |
| lines = lines.slice(0, -1); |
| |
| // description starts at the last line of type definition |
| lines = lines.slice(lines.reduce(lineNo, 0)); |
| |
| return lines.map(getDescription).join('\n'); |
| } |