UNPKG

graphql-language-service-server

Version:
72 lines (64 loc) 1.9 kB
import { Position, Range } from 'graphql-language-service'; import { RangeMapper, SourceParser } from './types'; import { babelParser } from './babel'; import { parse } from '@astrojs/compiler'; type ParseAstroResult = | { type: 'error'; errors: string[] } | { type: 'ok'; scriptOffset: number; scriptAst: any[]; }; async function parseAstro(source: string): Promise<ParseAstroResult> { const { ast, diagnostics } = await parse(source, { position: false, // defaults to `true` }); if (diagnostics.some(d => d.severity === /* Error */ 1)) { return { type: 'error', errors: diagnostics.map(d => JSON.stringify(d)), }; } for (const node of ast.children) { if (node.type === 'frontmatter') { try { return { type: 'ok', scriptOffset: (node.position?.start.line ?? 1) - 1, scriptAst: [babelParser(node.value, ['typescript'])], }; } catch (error) { return { type: 'error', errors: [String(error)], }; } } } return { type: 'error', errors: ['Could not find frontmatter block'] }; } export const astroParser: SourceParser = async (text, uri, logger) => { const parseAstroResult = await parseAstro(text); if (parseAstroResult.type === 'error') { logger.info( `Could not parse the astro file at ${uri} to extract the graphql tags:`, ); for (const error of parseAstroResult.errors) { logger.info(error); } return null; } const rangeMapper: RangeMapper = range => { return new Range( new Position( range.start.line + parseAstroResult.scriptOffset, range.start.character, ), new Position( range.end.line + parseAstroResult.scriptOffset, range.end.character, ), ); }; return { asts: parseAstroResult.scriptAst, rangeMapper }; };