@markuplint/erb-parser 4.6.21 → 4.6.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.ja.md +88 -0
- package/ARCHITECTURE.md +88 -0
- package/CHANGELOG.md +5 -1
- package/SKILL.md +80 -0
- package/docs/maintenance.ja.md +78 -0
- package/docs/maintenance.md +78 -0
- package/lib/index.d.ts +6 -0
- package/lib/index.js +6 -0
- package/lib/parser.d.ts +13 -0
- package/lib/parser.js +13 -0
- package/package.json +4 -4
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @markuplint/erb-parser
|
|
2
|
+
|
|
3
|
+
## 概要
|
|
4
|
+
|
|
5
|
+
`@markuplint/erb-parser` は、ERB(Embedded Ruby)テンプレート式を含む HTML をリントするために `HtmlParser` を拡張したテンプレートエンジンパーサーです。`ignoreTags` メカニズムを使用して ERB タグ(`<%= %>`、`<%# %>`、`<% %>`)を不透明なブロックとして扱い、Ruby コードを解釈せずに周囲の HTML 構造を検証できるようにします。
|
|
6
|
+
|
|
7
|
+
## 動作の仕組み
|
|
8
|
+
|
|
9
|
+
このパーサーは `HtmlParser`(`@markuplint/html-parser`)を継承し、親のコンストラクタに `ignoreTags` 設定を渡します。これにより、HTML パーサーが ERB タグパターンを認識し、HTML としてパースを試みる代わりに AST 内のプレースホルダーノード(`#ps:*`)に置換します。ERB 式はソースマッピングのためにノードの生コンテンツとしてそのまま保持されます。
|
|
10
|
+
|
|
11
|
+
`ignoreTags` パターンは順番にマッチングされるため、より具体的なパターン(例: 式用の `<%=`)が汎用的な `<%`(Ruby コードブロック用)よりも先にチェックされます。`erb-ruby-code` パターンの否定先読み `(?!%)` により、`<%%`(エスケープされた ERB デリミタ)がマッチしないようになっています。
|
|
12
|
+
|
|
13
|
+
## ignoreTags 設定
|
|
14
|
+
|
|
15
|
+
| タイプ | 開始パターン | 終了パターン | AST ノード名 | 説明 |
|
|
16
|
+
| --------------------- | ------------ | ------------ | ------------------------- | ----------------------- |
|
|
17
|
+
| `erb-ruby-expression` | `<%=` | `%>` | `#ps:erb-ruby-expression` | Ruby 式の出力 |
|
|
18
|
+
| `erb-comment` | `<%#` | `%>` | `#ps:erb-comment` | ERB コメント |
|
|
19
|
+
| `erb-ruby-code` | `/<%(?!%)/` | `%>` | `#ps:erb-ruby-code` | Ruby コード実行ブロック |
|
|
20
|
+
|
|
21
|
+
**注意:** trim_mode(`%` プレフィックス行)は現在サポートされていません。将来の実装のためにコメントアウトされたエントリがあります。
|
|
22
|
+
|
|
23
|
+
## サポートされない構文
|
|
24
|
+
|
|
25
|
+
**引用符なしの属性値**内のテンプレート式はサポートされていません。これはすべてのテンプレートエンジンパーサーに共通する既知の制限です([#240](https://github.com/markuplint/markuplint/issues/240))。[ウェブサイトのドキュメント](https://markuplint.dev/docs/guides/besides-html)も参照してください。
|
|
26
|
+
|
|
27
|
+
使用可能:
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div attr="<%= value %>"></div>
|
|
31
|
+
<div attr="<%= value %>"></div>
|
|
32
|
+
<div attr="<%= value %>-<%= value2 %>-<%= value3 %>"></div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
使用不可(引用符なし):
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<div attr=<%= value %>></div>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## ディレクトリ構成
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
src/
|
|
45
|
+
├── index.ts — parser インスタンスを再エクスポート
|
|
46
|
+
├── parser.ts — HtmlParser を継承する ERubyParser クラス
|
|
47
|
+
└── index.spec.ts — ERB タグパースのテスト
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 主要ソースファイル
|
|
51
|
+
|
|
52
|
+
| ファイル | 用途 |
|
|
53
|
+
| --------------- | --------------------------------------------------------------------------- |
|
|
54
|
+
| `parser.ts` | `ERubyParser` クラスを定義; `ignoreTags` を設定しシングルトンをエクスポート |
|
|
55
|
+
| `index.ts` | モジュールエントリポイント; `parser` を再エクスポート |
|
|
56
|
+
| `index.spec.ts` | すべての ERB タグタイプと HTML/ERB 混在コンテンツのテスト |
|
|
57
|
+
|
|
58
|
+
## 統合ポイント
|
|
59
|
+
|
|
60
|
+
```mermaid
|
|
61
|
+
flowchart TD
|
|
62
|
+
subgraph upstream ["上流"]
|
|
63
|
+
htmlParser["@markuplint/html-parser\n(HtmlParser クラス)"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subgraph pkg ["@markuplint/erb-parser"]
|
|
67
|
+
erbParser["ERubyParser\nextends HtmlParser\n(ignoreTags 設定のみ)"]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
subgraph consumer ["コンシューマー"]
|
|
71
|
+
mlCore["@markuplint/ml-core\n(リントエンジン)"]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
htmlParser -->|"継承"| erbParser
|
|
75
|
+
erbParser -->|"MLASTDocument を生成"| mlCore
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 上流
|
|
79
|
+
|
|
80
|
+
- **`@markuplint/html-parser`** -- すべての HTML パースロジックと `ignoreTags` メカニズムを提供する `HtmlParser` 基底クラス
|
|
81
|
+
|
|
82
|
+
### 下流
|
|
83
|
+
|
|
84
|
+
このパッケージには下流のパーサー依存はありません。markuplint エンジンから直接使用されるリーフパーサーです。
|
|
85
|
+
|
|
86
|
+
## ドキュメントマップ
|
|
87
|
+
|
|
88
|
+
- [メンテナンスガイド](docs/maintenance.ja.md) -- コマンド、レシピ、トラブルシューティング
|
package/ARCHITECTURE.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @markuplint/erb-parser
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`@markuplint/erb-parser` is a template engine parser for markuplint that extends `HtmlParser` to lint HTML containing ERB (Embedded Ruby) template expressions. It uses the `ignoreTags` mechanism to treat ERB tags (`<%= %>`, `<%# %>`, `<% %>`) as opaque blocks, allowing markuplint to validate the surrounding HTML structure without interpreting the Ruby code.
|
|
6
|
+
|
|
7
|
+
## How It Works
|
|
8
|
+
|
|
9
|
+
The parser extends `HtmlParser` (from `@markuplint/html-parser`) and passes an `ignoreTags` configuration to the parent constructor. This tells the HTML parser to recognize ERB tag patterns and replace them with placeholder nodes (`#ps:*`) in the AST instead of attempting to parse them as HTML. The ERB expressions are preserved as-is in the node's raw content for source mapping purposes.
|
|
10
|
+
|
|
11
|
+
The `ignoreTags` patterns are matched in order, so more specific patterns (e.g., `<%=` for expressions) are checked before the general `<%` pattern for Ruby code blocks. The negative lookahead `(?!%)` in the `erb-ruby-code` pattern prevents `<%%` (escaped ERB delimiters) from being matched.
|
|
12
|
+
|
|
13
|
+
## ignoreTags Configuration
|
|
14
|
+
|
|
15
|
+
| Type | Start Pattern | End Pattern | AST Node Name | Description |
|
|
16
|
+
| --------------------- | ------------- | ----------- | ------------------------- | -------------------------- |
|
|
17
|
+
| `erb-ruby-expression` | `<%=` | `%>` | `#ps:erb-ruby-expression` | Ruby expression output |
|
|
18
|
+
| `erb-comment` | `<%#` | `%>` | `#ps:erb-comment` | ERB comments |
|
|
19
|
+
| `erb-ruby-code` | `/<%(?!%)/` | `%>` | `#ps:erb-ruby-code` | Ruby code execution blocks |
|
|
20
|
+
|
|
21
|
+
**Note:** trim_mode (`%`-prefixed lines) is not currently supported. There is a commented-out entry for future implementation.
|
|
22
|
+
|
|
23
|
+
## Unsupported Syntaxes
|
|
24
|
+
|
|
25
|
+
Template expressions inside **unquoted attribute values** are not supported. This is a known limitation shared by all template engine parsers ([#240](https://github.com/markuplint/markuplint/issues/240)). See also the [website documentation](https://markuplint.dev/docs/guides/besides-html).
|
|
26
|
+
|
|
27
|
+
Available:
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div attr="<%= value %>"></div>
|
|
31
|
+
<div attr="<%= value %>"></div>
|
|
32
|
+
<div attr="<%= value %>-<%= value2 %>-<%= value3 %>"></div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Unavailable (unquoted):
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<div attr=<%= value %>></div>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Directory Structure
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
src/
|
|
45
|
+
├── index.ts — Re-exports parser instance
|
|
46
|
+
├── parser.ts — ERubyParser class extending HtmlParser
|
|
47
|
+
└── index.spec.ts — Tests for ERB tag parsing
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Key Source Files
|
|
51
|
+
|
|
52
|
+
| File | Purpose |
|
|
53
|
+
| --------------- | -------------------------------------------------------------------------- |
|
|
54
|
+
| `parser.ts` | Defines `ERubyParser` class; configures `ignoreTags` and exports singleton |
|
|
55
|
+
| `index.ts` | Module entry point; re-exports `parser` |
|
|
56
|
+
| `index.spec.ts` | Tests covering all ERB tag types and mixed HTML/ERB content |
|
|
57
|
+
|
|
58
|
+
## Integration Points
|
|
59
|
+
|
|
60
|
+
```mermaid
|
|
61
|
+
flowchart TD
|
|
62
|
+
subgraph upstream ["Upstream"]
|
|
63
|
+
htmlParser["@markuplint/html-parser\n(HtmlParser class)"]
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
subgraph pkg ["@markuplint/erb-parser"]
|
|
67
|
+
erbParser["ERubyParser\nextends HtmlParser\n(ignoreTags config only)"]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
subgraph consumer ["Consumer"]
|
|
71
|
+
mlCore["@markuplint/ml-core\n(Lint engine)"]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
htmlParser -->|"extends"| erbParser
|
|
75
|
+
erbParser -->|"produces MLASTDocument"| mlCore
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Upstream
|
|
79
|
+
|
|
80
|
+
- **`@markuplint/html-parser`** -- Provides the `HtmlParser` base class that handles all HTML parsing logic and the `ignoreTags` mechanism
|
|
81
|
+
|
|
82
|
+
### Downstream
|
|
83
|
+
|
|
84
|
+
This package has no downstream parser dependencies. It is a leaf parser consumed directly by the markuplint engine.
|
|
85
|
+
|
|
86
|
+
## Documentation Map
|
|
87
|
+
|
|
88
|
+
- [Maintenance Guide](docs/maintenance.md) -- Commands, recipes, and troubleshooting
|
package/CHANGELOG.md
CHANGED
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [4.6.
|
|
6
|
+
## [4.6.23](https://github.com/markuplint/markuplint/compare/@markuplint/erb-parser@4.6.22...@markuplint/erb-parser@4.6.23) (2026-02-10)
|
|
7
7
|
|
|
8
8
|
**Note:** Version bump only for package @markuplint/erb-parser
|
|
9
9
|
|
|
10
|
+
## [4.6.22](https://github.com/markuplint/markuplint/compare/@markuplint/erb-parser@4.6.21...@markuplint/erb-parser@4.6.22) (2025-11-05)
|
|
10
11
|
|
|
12
|
+
**Note:** Version bump only for package @markuplint/erb-parser
|
|
11
13
|
|
|
14
|
+
## [4.6.21](https://github.com/markuplint/markuplint/compare/@markuplint/erb-parser@4.6.20...@markuplint/erb-parser@4.6.21) (2025-08-24)
|
|
12
15
|
|
|
16
|
+
**Note:** Version bump only for package @markuplint/erb-parser
|
|
13
17
|
|
|
14
18
|
## [4.6.20](https://github.com/markuplint/markuplint/compare/@markuplint/erb-parser@4.6.19...@markuplint/erb-parser@4.6.20) (2025-08-13)
|
|
15
19
|
|
package/SKILL.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Perform maintenance tasks for @markuplint/erb-parser
|
|
3
|
+
globs:
|
|
4
|
+
- packages/@markuplint/erb-parser/src/**
|
|
5
|
+
alwaysApply: false
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# erb-parser-maintenance
|
|
9
|
+
|
|
10
|
+
Perform maintenance tasks for `@markuplint/erb-parser`: add or modify ERB ignoreTags patterns.
|
|
11
|
+
|
|
12
|
+
## Input
|
|
13
|
+
|
|
14
|
+
`$ARGUMENTS` specifies the task. Supported tasks:
|
|
15
|
+
|
|
16
|
+
| Task | Description |
|
|
17
|
+
| ------------------- | --------------------------------------- |
|
|
18
|
+
| `add-ignore-tag` | Add a new ERB tag pattern to ignoreTags |
|
|
19
|
+
| `modify-ignore-tag` | Modify an existing ignoreTags pattern |
|
|
20
|
+
|
|
21
|
+
If omitted, defaults to `add-ignore-tag`.
|
|
22
|
+
|
|
23
|
+
## Reference
|
|
24
|
+
|
|
25
|
+
Before executing any task, read `docs/maintenance.md` (or `docs/maintenance.ja.md`)
|
|
26
|
+
for the full guide. The recipes there are the source of truth for procedures.
|
|
27
|
+
|
|
28
|
+
Also read:
|
|
29
|
+
|
|
30
|
+
- `ARCHITECTURE.md` -- Package overview, ignoreTags configuration, and integration points
|
|
31
|
+
- `src/parser.ts` -- ERubyParser class (source of truth for ignoreTags configuration)
|
|
32
|
+
|
|
33
|
+
## Task: add-ignore-tag
|
|
34
|
+
|
|
35
|
+
Add a new ERB tag pattern to the ignoreTags array. Follow recipe #1 in `docs/maintenance.md`.
|
|
36
|
+
|
|
37
|
+
### Step 1: Determine the pattern
|
|
38
|
+
|
|
39
|
+
1. Read `src/parser.ts` to see existing ignoreTags entries
|
|
40
|
+
2. Define the new tag's `type`, `start`, and `end` patterns
|
|
41
|
+
3. Determine the correct position in the array (more specific patterns first)
|
|
42
|
+
|
|
43
|
+
### Step 2: Add the entry
|
|
44
|
+
|
|
45
|
+
1. Add the new entry to the `ignoreTags` array in the `ERubyParser` constructor
|
|
46
|
+
2. Use a string for literal start patterns, or a regex for patterns requiring lookahead/lookbehind
|
|
47
|
+
|
|
48
|
+
### Step 3: Verify
|
|
49
|
+
|
|
50
|
+
1. Build: `yarn build --scope @markuplint/erb-parser`
|
|
51
|
+
2. Add test cases to `src/index.spec.ts` verifying the new tag type appears as `#ps:<type>` in the AST
|
|
52
|
+
3. Test: `yarn test --scope @markuplint/erb-parser`
|
|
53
|
+
|
|
54
|
+
## Task: modify-ignore-tag
|
|
55
|
+
|
|
56
|
+
Modify an existing ignoreTags pattern. Follow recipe #2 in `docs/maintenance.md`.
|
|
57
|
+
|
|
58
|
+
### Step 1: Identify the pattern
|
|
59
|
+
|
|
60
|
+
1. Read `src/parser.ts` and locate the ignoreTags entry to modify
|
|
61
|
+
2. Understand why the change is needed (e.g., new ERB syntax, false matches)
|
|
62
|
+
|
|
63
|
+
### Step 2: Make the change
|
|
64
|
+
|
|
65
|
+
1. Update the `start`, `end`, or `type` fields as needed
|
|
66
|
+
2. Ensure pattern ordering is still correct (more specific patterns first)
|
|
67
|
+
3. If changing a regex pattern, verify it does not match escaped ERB delimiters (`<%%`)
|
|
68
|
+
|
|
69
|
+
### Step 3: Verify
|
|
70
|
+
|
|
71
|
+
1. Build: `yarn build --scope @markuplint/erb-parser`
|
|
72
|
+
2. Update test cases in `src/index.spec.ts` if the AST node names changed
|
|
73
|
+
3. Test: `yarn test --scope @markuplint/erb-parser`
|
|
74
|
+
|
|
75
|
+
## Rules
|
|
76
|
+
|
|
77
|
+
1. **Pattern order matters** -- More specific patterns (e.g., `<%=`, `<%#`) must appear before general patterns (e.g., `/<%(?!%)/`).
|
|
78
|
+
2. **Escaped delimiters** -- `<%%` must not be matched by any pattern. Use negative lookahead `(?!%)` on general patterns.
|
|
79
|
+
3. **Add JSDoc comments** to document any new tag types.
|
|
80
|
+
4. **No downstream impact** -- This is a leaf parser with no downstream dependencies.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# メンテナンスガイド
|
|
2
|
+
|
|
3
|
+
## コマンド
|
|
4
|
+
|
|
5
|
+
| コマンド | 説明 |
|
|
6
|
+
| ------------------------------------------- | ---------------------- |
|
|
7
|
+
| `yarn build --scope @markuplint/erb-parser` | このパッケージをビルド |
|
|
8
|
+
| `yarn dev --scope @markuplint/erb-parser` | ウォッチモードでビルド |
|
|
9
|
+
| `yarn clean --scope @markuplint/erb-parser` | ビルド成果物を削除 |
|
|
10
|
+
| `yarn test --scope @markuplint/erb-parser` | テストを実行 |
|
|
11
|
+
|
|
12
|
+
## テスト
|
|
13
|
+
|
|
14
|
+
テストファイルは `*.spec.ts` の命名規則に従い、`src/` ディレクトリに配置されています:
|
|
15
|
+
|
|
16
|
+
| テストファイル | カバレッジ |
|
|
17
|
+
| --------------- | ----------------------------------------------------------- |
|
|
18
|
+
| `index.spec.ts` | ERB タグパース、HTML/ERB 混在コンテンツ、エスケープデリミタ |
|
|
19
|
+
|
|
20
|
+
主なテストパターンでは `nodeListToDebugMaps` を使用したスナップショット形式のアサーションを行います:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { nodeListToDebugMaps } from '@markuplint/parser-utils';
|
|
24
|
+
import { parser } from './parser.js';
|
|
25
|
+
|
|
26
|
+
const parse = parser.parse.bind(parser);
|
|
27
|
+
const doc = parse('<div><%= name %></div>');
|
|
28
|
+
expect(nodeListToDebugMaps(doc.nodeList)).toStrictEqual([
|
|
29
|
+
'[1:1]>[1:6](0,5)div: <div>',
|
|
30
|
+
'[1:6]>[1:18](5,17)#ps:erb-ruby-expression: <%=\u2420name\u2420%>',
|
|
31
|
+
'[1:18]>[1:24](17,23)div: </div>',
|
|
32
|
+
]);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
タグタイプが正しく認識されているかの検証:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
expect(parse('<%= any %>').nodeList[0].nodeName).toBe('#ps:erb-ruby-expression');
|
|
39
|
+
expect(parse('<%# any %>').nodeList[0].nodeName).toBe('#ps:erb-comment');
|
|
40
|
+
expect(parse('<% any %>').nodeList[0].nodeName).toBe('#ps:erb-ruby-code');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## レシピ
|
|
44
|
+
|
|
45
|
+
### 1. 新しい ignoreTags パターンの追加
|
|
46
|
+
|
|
47
|
+
1. `src/parser.ts` を読み、既存の `ignoreTags` 配列を確認
|
|
48
|
+
2. 新しいタグの `type` 名を決定(命名規則: `erb-<説明>`)
|
|
49
|
+
3. `start` と `end` パターンを定義:
|
|
50
|
+
- 固定の開始シーケンスには文字列リテラルを使用(例: `'<%='`)
|
|
51
|
+
- 先読み/後読みが必要なパターンには正規表現を使用(例: `/<%(?!%)/`)
|
|
52
|
+
4. 正しい位置にエントリを挿入:
|
|
53
|
+
- より具体的なパターンを汎用パターンの前に配置
|
|
54
|
+
- 例: `<%=` を `<%` の前に
|
|
55
|
+
5. `src/index.spec.ts` にテストケースを追加:
|
|
56
|
+
- ノード名が `#ps:<type>` であることを検証
|
|
57
|
+
- エスケープされたデリミタ(`<%%`)にマッチしないことを検証
|
|
58
|
+
6. ビルドとテスト:
|
|
59
|
+
|
|
60
|
+
```shell
|
|
61
|
+
yarn build --scope @markuplint/erb-parser && yarn test --scope @markuplint/erb-parser
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. 既存の ignoreTags パターンの変更
|
|
65
|
+
|
|
66
|
+
1. `src/parser.ts` を読み、変更するエントリを特定
|
|
67
|
+
2. `start`、`end`、または `type` を変更
|
|
68
|
+
3. 変更後もパターンの順序が正しいことを確認
|
|
69
|
+
4. ノード名が変更された場合は `src/index.spec.ts` のテストケースを更新
|
|
70
|
+
5. ビルドとテスト:
|
|
71
|
+
|
|
72
|
+
```shell
|
|
73
|
+
yarn build --scope @markuplint/erb-parser && yarn test --scope @markuplint/erb-parser
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 下流影響
|
|
77
|
+
|
|
78
|
+
このパッケージには下流のパーサー依存はありません。markuplint エンジンから直接使用されるリーフパーサーであるため、変更が他のパーサーパッケージに影響を与えることはありません。
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Maintenance Guide
|
|
2
|
+
|
|
3
|
+
## Commands
|
|
4
|
+
|
|
5
|
+
| Command | Description |
|
|
6
|
+
| ------------------------------------------- | ---------------------- |
|
|
7
|
+
| `yarn build --scope @markuplint/erb-parser` | Build this package |
|
|
8
|
+
| `yarn dev --scope @markuplint/erb-parser` | Watch mode build |
|
|
9
|
+
| `yarn clean --scope @markuplint/erb-parser` | Remove build artifacts |
|
|
10
|
+
| `yarn test --scope @markuplint/erb-parser` | Run tests |
|
|
11
|
+
|
|
12
|
+
## Testing
|
|
13
|
+
|
|
14
|
+
Test files follow the `*.spec.ts` naming convention and are located in the `src/` directory:
|
|
15
|
+
|
|
16
|
+
| Test File | Coverage |
|
|
17
|
+
| --------------- | ----------------------------------------------------------- |
|
|
18
|
+
| `index.spec.ts` | ERB tag parsing, mixed HTML/ERB content, escaped delimiters |
|
|
19
|
+
|
|
20
|
+
The primary testing pattern uses `nodeListToDebugMaps` for snapshot-style assertions:
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { nodeListToDebugMaps } from '@markuplint/parser-utils';
|
|
24
|
+
import { parser } from './parser.js';
|
|
25
|
+
|
|
26
|
+
const parse = parser.parse.bind(parser);
|
|
27
|
+
const doc = parse('<div><%= name %></div>');
|
|
28
|
+
expect(nodeListToDebugMaps(doc.nodeList)).toStrictEqual([
|
|
29
|
+
'[1:1]>[1:6](0,5)div: <div>',
|
|
30
|
+
'[1:6]>[1:18](5,17)#ps:erb-ruby-expression: <%=\u2420name\u2420%>',
|
|
31
|
+
'[1:18]>[1:24](17,23)div: </div>',
|
|
32
|
+
]);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
To verify a tag type is correctly recognized:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
expect(parse('<%= any %>').nodeList[0].nodeName).toBe('#ps:erb-ruby-expression');
|
|
39
|
+
expect(parse('<%# any %>').nodeList[0].nodeName).toBe('#ps:erb-comment');
|
|
40
|
+
expect(parse('<% any %>').nodeList[0].nodeName).toBe('#ps:erb-ruby-code');
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Recipes
|
|
44
|
+
|
|
45
|
+
### 1. Adding a New ignoreTags Pattern
|
|
46
|
+
|
|
47
|
+
1. Read `src/parser.ts` and review the existing `ignoreTags` array
|
|
48
|
+
2. Determine the new tag's `type` name (convention: `erb-<description>`)
|
|
49
|
+
3. Define the `start` and `end` patterns:
|
|
50
|
+
- Use a string literal for fixed start sequences (e.g., `'<%='`)
|
|
51
|
+
- Use a regex for patterns requiring lookahead/lookbehind (e.g., `/<%(?!%)/`)
|
|
52
|
+
4. Insert the entry in the correct position:
|
|
53
|
+
- More specific patterns must come before general patterns
|
|
54
|
+
- Example: `<%=` before `<%`
|
|
55
|
+
5. Add test cases to `src/index.spec.ts`:
|
|
56
|
+
- Verify the node name is `#ps:<type>`
|
|
57
|
+
- Verify it doesn't match escaped delimiters (`<%%`)
|
|
58
|
+
6. Build and test:
|
|
59
|
+
|
|
60
|
+
```shell
|
|
61
|
+
yarn build --scope @markuplint/erb-parser && yarn test --scope @markuplint/erb-parser
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Modifying an Existing ignoreTags Pattern
|
|
65
|
+
|
|
66
|
+
1. Read `src/parser.ts` and locate the entry to modify
|
|
67
|
+
2. Make the change to `start`, `end`, or `type`
|
|
68
|
+
3. Verify pattern ordering is still correct after the change
|
|
69
|
+
4. Update test cases in `src/index.spec.ts` if node names changed
|
|
70
|
+
5. Build and test:
|
|
71
|
+
|
|
72
|
+
```shell
|
|
73
|
+
yarn build --scope @markuplint/erb-parser && yarn test --scope @markuplint/erb-parser
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Downstream Impact
|
|
77
|
+
|
|
78
|
+
This package has no downstream parser dependencies. It is a leaf parser consumed directly by the markuplint engine, so changes do not affect other parser packages.
|
package/lib/index.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/erb-parser
|
|
3
|
+
* Markuplint parser plugin for ERB (Embedded Ruby) templates. Extends the standard
|
|
4
|
+
* HTML parser to treat ERB tags as opaque blocks, allowing markuplint to lint
|
|
5
|
+
* the surrounding HTML structure.
|
|
6
|
+
*/
|
|
1
7
|
export { parser } from './parser.js';
|
package/lib/index.js
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @markuplint/erb-parser
|
|
3
|
+
* Markuplint parser plugin for ERB (Embedded Ruby) templates. Extends the standard
|
|
4
|
+
* HTML parser to treat ERB tags as opaque blocks, allowing markuplint to lint
|
|
5
|
+
* the surrounding HTML structure.
|
|
6
|
+
*/
|
|
1
7
|
export { parser } from './parser.js';
|
package/lib/parser.d.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { HtmlParser } from '@markuplint/html-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Parser for ERB (Embedded Ruby) templates that extends the standard HTML parser.
|
|
4
|
+
*
|
|
5
|
+
* Configures the HTML parser to recognize ERB tag variants as opaque blocks:
|
|
6
|
+
* - `<%= ... %>` (Ruby expression output)
|
|
7
|
+
* - `<%# ... %>` (comments)
|
|
8
|
+
* - `<% ... %>` (Ruby code execution)
|
|
9
|
+
*
|
|
10
|
+
* Note: trim_mode (`%`-prefixed lines) is not currently supported.
|
|
11
|
+
*/
|
|
2
12
|
declare class ERubyParser extends HtmlParser {
|
|
3
13
|
constructor();
|
|
4
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* Singleton ERB parser instance for use by the markuplint engine.
|
|
17
|
+
*/
|
|
5
18
|
export declare const parser: ERubyParser;
|
|
6
19
|
export {};
|
package/lib/parser.js
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import { HtmlParser } from '@markuplint/html-parser';
|
|
2
|
+
/**
|
|
3
|
+
* Parser for ERB (Embedded Ruby) templates that extends the standard HTML parser.
|
|
4
|
+
*
|
|
5
|
+
* Configures the HTML parser to recognize ERB tag variants as opaque blocks:
|
|
6
|
+
* - `<%= ... %>` (Ruby expression output)
|
|
7
|
+
* - `<%# ... %>` (comments)
|
|
8
|
+
* - `<% ... %>` (Ruby code execution)
|
|
9
|
+
*
|
|
10
|
+
* Note: trim_mode (`%`-prefixed lines) is not currently supported.
|
|
11
|
+
*/
|
|
2
12
|
class ERubyParser extends HtmlParser {
|
|
3
13
|
constructor() {
|
|
4
14
|
super({
|
|
@@ -29,4 +39,7 @@ class ERubyParser extends HtmlParser {
|
|
|
29
39
|
});
|
|
30
40
|
}
|
|
31
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Singleton ERB parser instance for use by the markuplint engine.
|
|
44
|
+
*/
|
|
32
45
|
export const parser = new ERubyParser();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markuplint/erb-parser",
|
|
3
|
-
"version": "4.6.
|
|
3
|
+
"version": "4.6.23",
|
|
4
4
|
"description": "eRuby template parser for markuplint",
|
|
5
5
|
"repository": "git@github.com:markuplint/markuplint.git",
|
|
6
6
|
"author": "Yusuke Hirao <yusukehirao@me.com>",
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"clean": "tsc --build --clean tsconfig.build.json"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@markuplint/html-parser": "4.6.
|
|
24
|
+
"@markuplint/html-parser": "4.6.23"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@markuplint/parser-utils": "4.8.
|
|
27
|
+
"@markuplint/parser-utils": "4.8.11"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "193ee7c1262bbed95424e38efdf1a8e56ff049f4"
|
|
30
30
|
}
|