Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

supplement(parser): reason for looping and searching for tags in the function isEnd is #231

Merged
merged 5 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions book/online-book/src/10-minimum-example/070-more-complex-parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,27 @@ function startsWithEndTagOpen(source: string, tag: string): boolean {

続いて parseElement と parseText について実装していきます。

::: tip isEnd のループについて
isEnd では ancestors の配列のそれぞれの要素に対して startsWithEndTagOpen で s がその要素の閉じタグで始まっている文字列かどうかをループでチェックするような処理になっています。
```typescript
function isEnd(context: ParserContext, ancestors: ElementNode[]): boolean {
const s = context.source

// s が '</' で始まり、かつその後にancestorsのタグ名が続くことを判定し、閉じタグがあるか(parseChildrenが終了するべきか)を判定します。
if (startsWith(s, '</')) {
for (let i = ancestors.length - 1; i >= 0; --i) {
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
return true
}
}
}

return !s
}
```
しかし、s が閉じタグで始まっている文字列かどうかをチェックするのであれば、ancestors の最後の要素に対してのみチェックすれば良いはずです。parser のリライトによってこのコードは無くなってしまいましたが、リライト前の Vue 3.3 のコードで ancestors の最後の要素に対してのみチェックするようにコードを書き換えても正常系のテストは全て PASS します。
:::

## parseText

まずはシンプルな parseText の方から.一部、parseText 以外でも使うユーティリティも実装しているので少しだけ長いです。
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,27 @@ function startsWithEndTagOpen(source: string, tag: string): boolean {

Next, let's implement parseElement and parseText.

::: tip About the isEnd Loop
In isEnd, there is a loop process that checks whether 's' starts with the closing tag of each element in the ancestors array using startsWithEndTagOpen.
```typescript
function isEnd(context: ParserContext, ancestors: ElementNode[]): boolean {
const s = context.source

// If s starts with </ and the tag name of ancestors follows, it determines whether there is a closing tag (whether parseChildren should end).
if (startsWith(s, '</')) {
for (let i = ancestors.length - 1; i >= 0; --i) {
if (startsWithEndTagOpen(s, ancestors[i].tag)) {
return true
}
}
}

return !s
}
```
However, if you need to check whether 's' starts with a closing tag, it should be sufficient to check only the last element in ancestors. Although this section of code was eliminated in a recent rewrite of the parser, modifying the Vue 3.3 code to only check the last element in ancestors still results in all the positive tests passing successfully.
:::

## parseText

First, let's start with the simple parseText. It is a bit long because it also implements some utilities that are used not only in parseText but also in other functions.
Expand Down