summaryrefslogtreecommitdiff
path: root/packages/astro-parser/src/parse/index.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/astro-parser/src/parse/index.ts')
-rw-r--r--packages/astro-parser/src/parse/index.ts262
1 files changed, 0 insertions, 262 deletions
diff --git a/packages/astro-parser/src/parse/index.ts b/packages/astro-parser/src/parse/index.ts
deleted file mode 100644
index 0ce259dfb..000000000
--- a/packages/astro-parser/src/parse/index.ts
+++ /dev/null
@@ -1,262 +0,0 @@
-// @ts-nocheck
-
-import { isIdentifierStart, isIdentifierChar } from 'acorn';
-import fragment from './state/fragment.js';
-import { whitespace } from '../utils/patterns.js';
-import { reserved } from '../utils/names.js';
-import full_char_code_at from '../utils/full_char_code_at.js';
-import { TemplateNode, Ast, ParserOptions, Fragment, Style, Script } from '../interfaces.js';
-import error from '../utils/error.js';
-
-type ParserState = (parser: Parser) => ParserState | void;
-
-interface LastAutoClosedTag {
- tag: string;
- reason: string;
- depth: number;
-}
-
-export class Parser {
- readonly template: string;
- readonly filename?: string;
- readonly customElement: boolean;
-
- index = 0;
- stack: TemplateNode[] = [];
-
- html: Fragment;
- css: Style[] = [];
- js: Script[] = [];
- meta_tags = {};
- last_auto_closed_tag?: LastAutoClosedTag;
- feature_flags = 0;
-
- constructor(template: string, options: ParserOptions) {
- if (typeof template !== 'string') {
- throw new TypeError('Template must be a string');
- }
-
- this.template = template.replace(/\s+$/, '');
- this.filename = options.filename;
- this.customElement = options.customElement;
-
- this.html = {
- start: null,
- end: null,
- type: 'Fragment',
- children: [],
- };
-
- this.stack.push(this.html);
-
- let state: ParserState = fragment;
-
- while (this.index < this.template.length) {
- state = state(this) || fragment;
- }
-
- if (this.stack.length > 1) {
- const current = this.current();
-
- const type = current.type === 'Element' ? `<${current.name}>` : 'Block';
- const slug = current.type === 'Element' ? 'element' : 'block';
-
- this.error(
- {
- code: `unclosed-${slug}`,
- message: `${type} was left open`,
- },
- current.start
- );
- }
-
- if (state !== fragment) {
- this.error({
- code: 'unexpected-eof',
- message: 'Unexpected end of input',
- });
- }
-
- if (this.html.children.length) {
- let start = this.html.children[0].start;
- while (whitespace.test(template[start])) start += 1;
-
- let end = this.html.children[this.html.children.length - 1].end;
- while (whitespace.test(template[end - 1])) end -= 1;
-
- this.html.start = start;
- this.html.end = end;
- } else {
- this.html.start = this.html.end = null;
- }
- }
-
- current() {
- return this.stack[this.stack.length - 1];
- }
-
- acorn_error(err: any) {
- this.error(
- {
- code: 'parse-error',
- message: err.message.replace(/ \(\d+:\d+\)$/, ''),
- },
- err.pos
- );
- }
-
- error({ code, message }: { code: string; message: string }, index = this.index) {
- error(this.template, message, {
- name: 'ParseError',
- code,
- source: this.template,
- start: index,
- filename: this.filename,
- });
- }
-
- eat(str: string, required?: boolean, message?: string) {
- if (this.match(str)) {
- this.index += str.length;
- return true;
- }
-
- if (required) {
- this.error({
- code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`,
- message: message || `Expected ${str}`,
- });
- }
-
- return false;
- }
-
- match(str: string) {
- return this.template.slice(this.index, this.index + str.length) === str;
- }
-
- match_regex(pattern: RegExp) {
- const match = pattern.exec(this.template.slice(this.index));
- if (!match || match.index !== 0) return null;
-
- return match[0];
- }
-
- allow_whitespace() {
- while (this.index < this.template.length && whitespace.test(this.template[this.index])) {
- this.index++;
- }
- }
-
- read(pattern: RegExp) {
- const result = this.match_regex(pattern);
- if (result) this.index += result.length;
- return result;
- }
-
- read_identifier(allow_reserved = false) {
- const start = this.index;
-
- let i = this.index;
-
- const code = full_char_code_at(this.template, i);
- if (!isIdentifierStart(code, true)) return null;
-
- i += code <= 0xffff ? 1 : 2;
-
- while (i < this.template.length) {
- const code = full_char_code_at(this.template, i);
-
- if (!isIdentifierChar(code, true)) break;
- i += code <= 0xffff ? 1 : 2;
- }
-
- const identifier = this.template.slice(this.index, (this.index = i));
-
- if (!allow_reserved && reserved.has(identifier)) {
- this.error(
- {
- code: 'unexpected-reserved-word',
- message: `'${identifier}' is a reserved word in JavaScript and cannot be used here`,
- },
- start
- );
- }
-
- return identifier;
- }
-
- read_until(pattern: RegExp) {
- if (this.index >= this.template.length) {
- this.error({
- code: 'unexpected-eof',
- message: 'Unexpected end of input',
- });
- }
-
- const start = this.index;
- const match = pattern.exec(this.template.slice(start));
-
- if (match) {
- this.index = start + match.index;
- return this.template.slice(start, this.index);
- }
-
- this.index = this.template.length;
- return this.template.slice(start);
- }
-
- require_whitespace() {
- if (!whitespace.test(this.template[this.index])) {
- this.error({
- code: 'missing-whitespace',
- message: 'Expected whitespace',
- });
- }
-
- this.allow_whitespace();
- }
-}
-
-/**
- * Parse
- * Step 1/3 in Astro SSR.
- * This is the first pass over .astro files and the step at which we convert a string to an AST for us to crawl.
- */
-export default function parse(template: string, options: ParserOptions = {}): Ast {
- const parser = new Parser(template, options);
-
- // const instance_scripts = parser.js.filter((script) => script.context === 'default');
- // const module_scripts = parser.js.filter((script) => script.context === 'module');
- const astro_scripts = parser.js.filter((script) => script.context === 'setup');
-
- if (astro_scripts.length > 1) {
- parser.error(
- {
- code: 'invalid-script',
- message: 'A component can only have one frontmatter (---) script',
- },
- astro_scripts[1].start
- );
- }
-
- // if (module_scripts.length > 1) {
- // parser.error(
- // {
- // code: 'invalid-script',
- // message: 'A component can only have one <script context="module"> element',
- // },
- // module_scripts[1].start
- // );
- // }
-
- return {
- html: parser.html,
- css: parser.css,
- // instance: instance_scripts[0],
- module: astro_scripts[0],
- meta: {
- features: parser.feature_flags,
- },
- };
-}