diff --git a/.changeset/config.json b/.changeset/config.json index 76c5a08ba..8292fbe07 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -1,8 +1,8 @@ { - "$schema": "https://unpkg.com/@changesets/config@1.6.0/schema.json", + "$schema": "https://unpkg.com/@changesets/config@1.7.0/schema.json", "changelog": ["@changesets/changelog-github", { "repo": "withastro/astro" }], "commit": false, - "linked": [["astro", "@astrojs/parser"]], + "linked": [], "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", diff --git a/.changeset/pre.json b/.changeset/pre.json index 389e6f780..c6c33d08f 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -31,7 +31,6 @@ "@example/with-tailwindcss": "0.0.1", "@example/with-vite-plugin-pwa": "0.0.1", "astro": "0.24.3", - "@astrojs/parser": "0.22.2", "@astrojs/prism": "0.4.0", "@test/custom-element-renderer": "0.1.0", "@test/static-build-pkg": "0.0.0", diff --git a/LICENSE b/LICENSE index 53be9db53..96b135cf7 100644 --- a/LICENSE +++ b/LICENSE @@ -21,21 +21,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -""" -This license applies to parts of the `packages/astro-parser` subdirectory originating from the -https://github.com/sveltejs/svelte repository: - - -Copyright (c) 2016-21 [these people](https://github.com/sveltejs/svelte/graphs/contributors) - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -""" - - """ This license applies to parts of the `packages/create-astro` and `packages/astro` subdirectories originating from the https://github.com/sveltejs/kit repository: diff --git a/packages/astro-parser/CHANGELOG.md b/packages/astro-parser/CHANGELOG.md deleted file mode 100644 index 971f1be76..000000000 --- a/packages/astro-parser/CHANGELOG.md +++ /dev/null @@ -1,121 +0,0 @@ -# @astrojs/parser - -## 0.22.2 - -## 0.22.1 - -## 0.22.0 - -### Minor Changes - -- [#2202](https://github.com/withastro/astro/pull/2202) [`45cea6ae`](https://github.com/withastro/astro/commit/45cea6aec5a310fed4cb8da0d96670d6b99a2539) Thanks [@jonathantneal](https://github.com/jonathantneal)! - Officially drop support for Node v12. The minimum supported version is now Node v14.15+, - -## 0.20.3 - -## 0.20.2 - -### Patch Changes - -- 5d2ea578: fixed an issue using namespaced attributes in astro files - -## 0.18.6 - -## 0.18.5 - -### Patch Changes - -- cd2b5df4: Prevents locking up checking for --- inside of the HTML portion - -## 0.18.0 - -### Patch Changes - -- a7e6666: compile javascript to target Node v12.x -- 294a656: Adds support for global style blocks via `', true); - const end = parser.index; - - return { - type: 'Style', - start, - end, - attributes, - content: { - start: content_start, - end: content_end, - styles, - }, - }; -} - -function is_ref_selector(a: any, b: any) { - // TODO add CSS node types - if (!b) return false; - - return a.type === 'TypeSelector' && a.name === 'ref' && b.type === 'PseudoClassSelector'; -} diff --git a/packages/astro-parser/src/parse/state/codefence.ts b/packages/astro-parser/src/parse/state/codefence.ts deleted file mode 100644 index b8e96b262..000000000 --- a/packages/astro-parser/src/parse/state/codefence.ts +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-nocheck -import { Parser } from '../index.js'; - -export default function codefence(parser: Parser) { - const start = parser.index; - const open = parser.match_regex(/[`~]{3,}/); - parser.index += open!.length; - - let raw = open + ''; - - while (parser.index < parser.template.length && !parser.match(open)) { - raw += parser.template[parser.index++]; - } - - parser.eat(open, true); - raw += open; - const trailingWhitespace = parser.read_until(/\S/); - const { metadata, data } = extractCodeFence(raw); - - const node = { - start, - end: parser.index, - type: 'CodeFence', - raw: `${raw}` + trailingWhitespace, - metadata, - data, - }; - - parser.current().children.push(node); -} - -/** Extract attributes on first line */ -function extractCodeFence(str: string) { - const [_, leadingLine] = str.match(/(^[^\n]*\r?\n)/m) ?? ['', '']; - const metadata = leadingLine.trim(); - const data = str.slice(leadingLine.length); - return { metadata, data }; -} diff --git a/packages/astro-parser/src/parse/state/codespan.ts b/packages/astro-parser/src/parse/state/codespan.ts deleted file mode 100644 index 42d0ae932..000000000 --- a/packages/astro-parser/src/parse/state/codespan.ts +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-nocheck -import { Parser } from '../index.js'; - -export default function codespan(parser: Parser) { - const start = parser.index; - const open = parser.match_regex(/(? block.type === 'IfBlock') - ? `Expected to close ${to_string(block)} before seeing {:else if ...} block` - : 'Cannot have an {:else if ...} block outside an {#if ...} block', - }); - } - - parser.require_whitespace(); - - const expression = read_expression(parser); - - parser.allow_whitespace(); - parser.eat('}', true); - - block.else = { - start: parser.index, - end: null, - type: 'ElseBlock', - children: [ - { - start: parser.index, - end: null, - type: 'IfBlock', - elseif: true, - expression, - children: [], - }, - ], - }; - - parser.stack.push(block.else.children[0]); - } else { - // :else - const block = parser.current(); - if (block.type !== 'IfBlock' && block.type !== 'EachBlock') { - parser.error({ - code: 'invalid-else-placement', - message: parser.stack.some((block) => block.type === 'IfBlock' || block.type === 'EachBlock') - ? `Expected to close ${to_string(block)} before seeing {:else} block` - : 'Cannot have an {:else} block outside an {#if ...} or {#each ...} block', - }); - } - - parser.allow_whitespace(); - parser.eat('}', true); - - block.else = { - start: parser.index, - end: null, - type: 'ElseBlock', - children: [], - }; - - parser.stack.push(block.else); - } - } else if (parser.match(':then') || parser.match(':catch')) { - const block = parser.current(); - const is_then = parser.eat(':then') || !parser.eat(':catch'); - - if (is_then) { - if (block.type !== 'PendingBlock') { - parser.error({ - code: 'invalid-then-placement', - message: parser.stack.some((block) => block.type === 'PendingBlock') - ? `Expected to close ${to_string(block)} before seeing {:then} block` - : 'Cannot have an {:then} block outside an {#await ...} block', - }); - } - } else { - if (block.type !== 'ThenBlock' && block.type !== 'PendingBlock') { - parser.error({ - code: 'invalid-catch-placement', - message: parser.stack.some((block) => block.type === 'ThenBlock' || block.type === 'PendingBlock') - ? `Expected to close ${to_string(block)} before seeing {:catch} block` - : 'Cannot have an {:catch} block outside an {#await ...} block', - }); - } - } - - block.end = start; - parser.stack.pop(); - const await_block = parser.current(); - - if (!parser.eat('}')) { - parser.require_whitespace(); - await_block[is_then ? 'value' : 'error'] = read_context(parser); - parser.allow_whitespace(); - parser.eat('}', true); - } - - const new_block: TemplateNode = { - start, - // @ts-ignore - end: null, - type: is_then ? 'ThenBlock' : 'CatchBlock', - children: [], - skip: false, - }; - - await_block[is_then ? 'then' : 'catch'] = new_block; - parser.stack.push(new_block); - } else if (parser.eat('#')) { - // {#if foo}, {#each foo} or {#await foo} - let type; - - if (parser.eat('if')) { - type = 'IfBlock'; - } else if (parser.eat('each')) { - type = 'EachBlock'; - } else if (parser.eat('await')) { - type = 'AwaitBlock'; - } else if (parser.eat('key')) { - type = 'KeyBlock'; - } else { - parser.error({ - code: 'expected-block-type', - message: 'Expected if, each, await or key', - }); - } - - parser.require_whitespace(); - - const expression = read_expression(parser); - - // @ts-ignore - const block: TemplateNode = - type === 'AwaitBlock' - ? { - start, - end: null, - type, - expression, - value: null, - error: null, - pending: { - start: null, - end: null, - type: 'PendingBlock', - children: [], - skip: true, - }, - then: { - start: null, - end: null, - type: 'ThenBlock', - children: [], - skip: true, - }, - catch: { - start: null, - end: null, - type: 'CatchBlock', - children: [], - skip: true, - }, - } - : { - start, - end: null, - type, - expression, - children: [], - }; - - parser.allow_whitespace(); - - // {#each} blocks must declare a context – {#each list as item} - if (type === 'EachBlock') { - parser.eat('as', true); - parser.require_whitespace(); - - block.context = read_context(parser); - - parser.allow_whitespace(); - - if (parser.eat(',')) { - parser.allow_whitespace(); - block.index = parser.read_identifier(); - if (!block.index) { - parser.error({ - code: 'expected-name', - message: 'Expected name', - }); - } - - parser.allow_whitespace(); - } - - if (parser.eat('(')) { - parser.allow_whitespace(); - - block.key = read_expression(parser); - parser.allow_whitespace(); - parser.eat(')', true); - parser.allow_whitespace(); - } - } - - const await_block_shorthand = type === 'AwaitBlock' && parser.eat('then'); - if (await_block_shorthand) { - parser.require_whitespace(); - block.value = read_context(parser); - parser.allow_whitespace(); - } - - const await_block_catch_shorthand = !await_block_shorthand && type === 'AwaitBlock' && parser.eat('catch'); - if (await_block_catch_shorthand) { - parser.require_whitespace(); - block.error = read_context(parser); - parser.allow_whitespace(); - } - - parser.eat('}', true); - - // @ts-ignore - parser.current().children.push(block); - parser.stack.push(block); - - if (type === 'AwaitBlock') { - let child_block; - if (await_block_shorthand) { - block.then.skip = false; - child_block = block.then; - } else if (await_block_catch_shorthand) { - block.catch.skip = false; - child_block = block.catch; - } else { - block.pending.skip = false; - child_block = block.pending; - } - - child_block.start = parser.index; - parser.stack.push(child_block); - } - } else if (parser.eat('@html')) { - // {@html content} tag - parser.require_whitespace(); - - const expression = read_expression(parser); - - parser.allow_whitespace(); - parser.eat('}', true); - - // @ts-ignore - parser.current().children.push({ - start, - end: parser.index, - type: 'RawMustacheTag', - expression, - }); - } else if (parser.eat('@debug')) { - // let identifiers; - - // // Implies {@debug} which indicates "debug all" - // if (parser.read(/\s*}/)) { - // identifiers = []; - // } else { - // const expression = read_expression(parser); - - // identifiers = expression.type === 'SequenceExpression' - // ? expression.expressions - // : [expression]; - - // identifiers.forEach(node => { - // if (node.type !== 'Identifier') { - // parser.error({ - // code: 'invalid-debug-args', - // message: '{@debug ...} arguments must be identifiers, not arbitrary expressions' - // }, node.start); - // } - // }); - - // parser.allow_whitespace(); - // parser.eat('}', true); - // } - - // parser.current().children.push({ - // start, - // end: parser.index, - // type: 'DebugTag', - // identifiers - // }); - throw new Error('@debug not yet supported'); - } else { - const expression = read_expression(parser); - - parser.allow_whitespace(); - parser.eat('}', true); - - // @ts-ignore - parser.current().children.push({ - start, - end: parser.index, - type: 'MustacheTag', - expression, - }); - } -} diff --git a/packages/astro-parser/src/parse/state/setup.ts b/packages/astro-parser/src/parse/state/setup.ts deleted file mode 100644 index cb23860ad..000000000 --- a/packages/astro-parser/src/parse/state/setup.ts +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-nocheck - -import { Parser } from '../index.js'; - -export default function setup(parser: Parser): void { - // TODO: Error if not at top of file? currently, we ignore / just treat as text. - // if (parser.html.children.length > 0) { - // parser.error({ - // code: 'unexpected-token', - // message: 'Frontmatter scripts only supported at the top of file.', - // }); - // } - - const start = parser.index; - parser.index += 3; - const content_start = parser.index; - const setupScriptContent = parser.read_until(/^---/m); - const content_end = parser.index; - parser.eat('---', true); - const end = parser.index; - parser.js.push({ - type: 'Script', - context: 'setup', - start, - end, - content: setupScriptContent, - // attributes, - // content: { - // start: content_start, - // end: content_end, - // styles, - // }, - }); - return; -} diff --git a/packages/astro-parser/src/parse/state/tag.ts b/packages/astro-parser/src/parse/state/tag.ts deleted file mode 100644 index 8f940cbc3..000000000 --- a/packages/astro-parser/src/parse/state/tag.ts +++ /dev/null @@ -1,499 +0,0 @@ -// @ts-nocheck - -import read_expression from '../read/expression.js'; -import read_style from '../read/style.js'; -import { decode_character_references, closing_tag_omitted } from '../utils/html.js'; -import { is_void } from '../../utils/names.js'; -import { Parser } from '../index.js'; -import { TemplateNode, Text } from '../../interfaces.js'; -import fuzzymatch from '../../utils/fuzzymatch.js'; -import list from '../../utils/list.js'; -import { FEATURE_CUSTOM_ELEMENT } from '../utils/features.js'; - -const valid_tag_name = /^\!?[a-zA-Z]{1,}:?[a-zA-Z0-9\-]*/; - -const meta_tags = new Map([ - ['astro:head', 'Head'], - ['', 'SlotTemplate'], - // ['astro:options', 'Options'], - // ['astro:window', 'Window'], - // ['astro:body', 'Body'], -]); - -const valid_meta_tags = Array.from(meta_tags.keys()); //.concat('astro:self', 'astro:component', 'astro:fragment'); - -const specials = new Map([ - // Now handled as "setup" in setup.ts - // [ - // 'script', - // { - // read: read_script, - // property: 'js', - // }, - // ], - [ - 'style', - { - read: read_style, - property: 'css', - }, - ], -]); - -const SELF = /^astro:self(?=[\s/>])/; -const COMPONENT = /^astro:component(?=[\s/>])/; -const SLOT = /^astro:fragment(?=[\s/>])/; -const HEAD = /^head(?=[\s/>])/; -const CUSTOM_ELEMENT = /-/; - -function parent_is_head(stack) { - let i = stack.length; - while (i--) { - const { type } = stack[i]; - if (type === 'Head') return true; - if (type === 'Element' || type === 'InlineComponent') return false; - } - return false; -} - -export default function tag(parser: Parser) { - const start = parser.index++; - - let parent = parser.current(); - - if (parser.eat('!--')) { - const data = parser.read_until(/-->/); - parser.eat('-->', true, 'comment was left open, expected -->'); - - parser.current().children.push({ - start, - end: parser.index, - type: 'Comment', - data, - }); - - return; - } - - const is_closing_tag = parser.eat('/'); - - const name = read_tag_name(parser); - - if (CUSTOM_ELEMENT.test(name)) { - parser.feature_flags |= FEATURE_CUSTOM_ELEMENT; - } - - if (meta_tags.has(name)) { - const slug = meta_tags.get(name).toLowerCase(); - if (is_closing_tag) { - if ((name === 'astro:window' || name === 'astro:body') && parser.current().children.length) { - parser.error( - { - code: `invalid-${slug}-content`, - message: `<${name}> cannot have children`, - }, - parser.current().children[0].start - ); - } - } else { - if (name in parser.meta_tags) { - parser.error( - { - code: `duplicate-${slug}`, - message: `A component can only have one <${name}> tag`, - }, - start - ); - } - - if (parser.stack.length > 1) { - parser.error( - { - code: `invalid-${slug}-placement`, - message: `<${name}> tags cannot be inside elements or blocks`, - }, - start - ); - } - - parser.meta_tags[name] = true; - } - } - - const type = meta_tags.has(name) - ? meta_tags.get(name) - : /[A-Z]/.test(name[0]) || name === 'astro:self' || name === 'astro:component' - ? 'InlineComponent' - : name === '' - ? 'SlotTemplate' - : name === 'title' && parent_is_head(parser.stack) - ? 'Title' - : name === 'slot' && !parser.customElement - ? 'Slot' - : 'Element'; - - const element: TemplateNode = { - start, - end: null, // filled in later - type, - name, - attributes: [], - children: [], - }; - - parser.allow_whitespace(); - - if (is_closing_tag) { - if (is_void(name)) { - parser.error( - { - code: 'invalid-void-content', - message: `<${name}> is a void element and cannot have children, or a closing tag`, - }, - start - ); - } - - parser.eat('>', true); - - // close any elements that don't have their own closing tags, e.g.