pi-must-have-extension 0.4.7 → 0.4.9
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/CHANGELOG.md +13 -0
- package/README.md +186 -178
- package/package.json +6 -4
- package/src/constants.ts +63 -63
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.9] - 2026-04-01
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Fixed image link and README formatting
|
|
7
|
+
- Added npm keywords for discoverability (`pi-package`, `pi-extension`, `pi-coding-agent`, `coding-agent`)
|
|
8
|
+
- Added Related Pi Extensions cross-linking section to README
|
|
9
|
+
|
|
10
|
+
## [0.4.8] - 2026-04-01
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Updated `@mariozechner/pi-coding-agent` peer dependency to ^0.64.0
|
|
14
|
+
- Updated `typescript` dev dependency to ^6.0.2
|
|
15
|
+
|
|
3
16
|
## [0.4.7] - 2026-03-23
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/README.md
CHANGED
|
@@ -1,178 +1,186 @@
|
|
|
1
|
-
# pi-must-have-extension
|
|
2
|
-
|
|
3
|
-
Normalize RFC 2119 language in Pi prompts by automatically rewriting lowercase modal terms (`must`, `should not`, `optional`) into uppercase normative forms (`MUST`, `SHOULD NOT`, `OPTIONAL`).
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
- **
|
|
20
|
-
- **
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
//
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"must
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"shall
|
|
84
|
-
"
|
|
85
|
-
"should
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
| `
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
"
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
~/.pi/agent/extensions/must-have-plugin/config.jsonc
|
|
129
|
-
~/.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
├──
|
|
148
|
-
|
|
149
|
-
│ ├──
|
|
150
|
-
│ ├──
|
|
151
|
-
│ ├──
|
|
152
|
-
│
|
|
153
|
-
│ │
|
|
154
|
-
│ └──
|
|
155
|
-
│
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
│
|
|
159
|
-
└──
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
npm
|
|
168
|
-
npm run
|
|
169
|
-
npm run
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
1
|
+
# pi-must-have-extension
|
|
2
|
+
|
|
3
|
+
Normalize RFC 2119 language in Pi prompts by automatically rewriting lowercase modal terms (`must`, `should not`, `optional`) into uppercase normative forms (`MUST`, `SHOULD NOT`, `OPTIONAL`).
|
|
4
|
+
|
|
5
|
+
<img width="1360" height="752" alt="image" src="https://github.com/user-attachments/assets/d5aff97e-ac69-48d1-a071-c7f5460899e4" />
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Demo
|
|
9
|
+
|
|
10
|
+
[](https://github.com/user-attachments/assets/22149125-8976-4d06-98cb-e7cfa180476d)
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **RFC 2119/8174 compliance** — Transforms modal keywords to standard uppercase notation
|
|
15
|
+
- **Intelligent matching** — Case-insensitive with longest-first phrase replacement
|
|
16
|
+
- **Word-boundary aware** — Does not replace keywords embedded inside larger words
|
|
17
|
+
- **Configurable replacements** — Customize or extend the default keyword mappings
|
|
18
|
+
- **Input filtering** — Leaves slash commands (`/`) and shell input (`!`) unchanged
|
|
19
|
+
- **Auto-configuration** — Creates a default config file when none exists
|
|
20
|
+
- **Legacy migration** — Automatically migrates configs from previous plugin versions
|
|
21
|
+
- **Debug mode** — Optional TUI notifications showing replacement counts
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Local Extension Folder
|
|
26
|
+
|
|
27
|
+
Copy this repository to one of the following locations:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
~/.pi/agent/extensions/pi-must-have-extension # Global (all projects)
|
|
31
|
+
.pi/extensions/pi-must-have-extension # Project-specific
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Pi will auto-discover the extension on startup.
|
|
35
|
+
|
|
36
|
+
### NPM Package
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pi install npm:pi-must-have-extension
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
Once installed, the extension works automatically. When you type prompts containing RFC 2119 keywords:
|
|
45
|
+
|
|
46
|
+
**Input:**
|
|
47
|
+
```text
|
|
48
|
+
The function must validate input and should log errors.
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Transformed to:**
|
|
52
|
+
```text
|
|
53
|
+
The function MUST validate input and SHOULD log errors.
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Skipped Input
|
|
57
|
+
|
|
58
|
+
The extension does not transform:
|
|
59
|
+
|
|
60
|
+
- Slash commands (e.g., `/help`, `/reload`)
|
|
61
|
+
- Shell commands (e.g., `!ls`, `!git status`)
|
|
62
|
+
- Empty input
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
The extension uses a JSONC configuration file (JSON with comments):
|
|
67
|
+
|
|
68
|
+
```text
|
|
69
|
+
~/.pi/agent/extensions/pi-must-have-extension/config.jsonc
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Default Configuration
|
|
73
|
+
|
|
74
|
+
```jsonc
|
|
75
|
+
{
|
|
76
|
+
// Enable debug notifications in the TUI
|
|
77
|
+
// "debug": true,
|
|
78
|
+
|
|
79
|
+
"replacements": {
|
|
80
|
+
"must": "MUST",
|
|
81
|
+
"must not": "MUST NOT",
|
|
82
|
+
"required": "REQUIRED",
|
|
83
|
+
"shall": "SHALL",
|
|
84
|
+
"shall not": "SHALL NOT",
|
|
85
|
+
"should": "SHOULD",
|
|
86
|
+
"should not": "SHOULD NOT",
|
|
87
|
+
"recommended": "RECOMMENDED",
|
|
88
|
+
"not recommended": "NOT RECOMMENDED",
|
|
89
|
+
"may": "MAY",
|
|
90
|
+
"optional": "OPTIONAL"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Configuration Options
|
|
96
|
+
|
|
97
|
+
| Option | Type | Default | Description |
|
|
98
|
+
|--------|------|---------|-------------|
|
|
99
|
+
| `debug` | `boolean` | `false` | Enable TUI notifications showing replacement counts |
|
|
100
|
+
| `replacements` | `object` | RFC 2119 defaults | Key-value map of terms to replace |
|
|
101
|
+
|
|
102
|
+
### Custom Replacements
|
|
103
|
+
|
|
104
|
+
You can add custom replacement rules or modify existing ones:
|
|
105
|
+
|
|
106
|
+
```jsonc
|
|
107
|
+
{
|
|
108
|
+
"replacements": {
|
|
109
|
+
// Standard RFC 2119
|
|
110
|
+
"must": "MUST",
|
|
111
|
+
"should": "SHOULD",
|
|
112
|
+
|
|
113
|
+
// Custom shortcuts
|
|
114
|
+
"rfc!": "The key words in this document are to be interpreted as described in RFC 2119.\n\n",
|
|
115
|
+
"always": "**ALWAYS**",
|
|
116
|
+
"never": "**NEVER**"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
An advanced replacement sample is included at `config/replacements.custom-sample.jsonc`.
|
|
122
|
+
|
|
123
|
+
### Legacy Config Paths
|
|
124
|
+
|
|
125
|
+
The extension supports migration from previous versions. Legacy configs are read from:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
~/.pi/agent/extensions/pi-must-have-plugin/config.jsonc
|
|
129
|
+
~/.pi/agent/extensions/must-have-plugin/config.jsonc
|
|
130
|
+
~/.config/opencode/MUST-have-plugin.jsonc
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
On first run, legacy configs are automatically migrated to the new location.
|
|
134
|
+
|
|
135
|
+
## Technical Details
|
|
136
|
+
|
|
137
|
+
### How It Works
|
|
138
|
+
|
|
139
|
+
1. **Session start**: Ensures config exists (creates default or migrates legacy)
|
|
140
|
+
2. **Input event**: Intercepts user prompts before sending to the agent
|
|
141
|
+
3. **Pattern matching**: Uses regex with word boundaries and longest-match-first ordering
|
|
142
|
+
4. **Transformation**: Returns modified text while preserving images and other input data
|
|
143
|
+
|
|
144
|
+
### Project Structure
|
|
145
|
+
|
|
146
|
+
```text
|
|
147
|
+
├── index.ts # Pi extension entrypoint
|
|
148
|
+
├── src/
|
|
149
|
+
│ ├── index.ts # Extension event wiring
|
|
150
|
+
│ ├── constants.ts # Paths, defaults, and extension name
|
|
151
|
+
│ ├── types.ts # TypeScript interfaces
|
|
152
|
+
│ ├── config/
|
|
153
|
+
│ │ ├── config-loader.ts # Config loading and migration
|
|
154
|
+
│ │ └── jsonc.ts # JSONC parser (strips comments)
|
|
155
|
+
│ └── replacements/
|
|
156
|
+
│ └── replacement-engine.ts # Core replacement logic
|
|
157
|
+
├── config/
|
|
158
|
+
│ ├── config.example.jsonc # Starter template
|
|
159
|
+
│ └── replacements.custom-sample.jsonc # Advanced samples
|
|
160
|
+
└── test/
|
|
161
|
+
└── replacement-engine.test.ts # Unit tests
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Development
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npm install # Install dependencies
|
|
168
|
+
npm run build # Type-check with TypeScript
|
|
169
|
+
npm run test # Run test suite
|
|
170
|
+
npm run check # Build + test
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Origin
|
|
174
|
+
|
|
175
|
+
This extension is a Pi-harness adaptation of [ariane-emory/MUST-have-plugin](https://github.com/ariane-emory/MUST-have-plugin), converted into a modular TypeScript Pi extension.
|
|
176
|
+
|
|
177
|
+
## Related Pi Extensions
|
|
178
|
+
|
|
179
|
+
- [pi-permission-system](https://github.com/MasuRii/pi-permission-system) — Permission enforcement for tool and command access
|
|
180
|
+
- [pi-tool-display](https://github.com/MasuRii/pi-tool-display) — Compact tool rendering and diff visualization
|
|
181
|
+
- [pi-rtk-optimizer](https://github.com/MasuRii/pi-rtk-optimizer) — RTK command rewriting and output compaction
|
|
182
|
+
- [pi-multi-auth](https://github.com/MasuRii/pi-multi-auth) — Multi-provider credential management and quota-aware rotation
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-must-have-extension",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.9",
|
|
4
4
|
"description": "RFC 2119 keyword normalizer extension for the Pi coding agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
"bcp14",
|
|
36
36
|
"prompt-normalization",
|
|
37
37
|
"prompt-rewrite",
|
|
38
|
+
"prompt-engineering",
|
|
39
|
+
"keyword-normalization",
|
|
38
40
|
"compliance",
|
|
39
41
|
"jsonc"
|
|
40
42
|
],
|
|
@@ -60,11 +62,11 @@
|
|
|
60
62
|
]
|
|
61
63
|
},
|
|
62
64
|
"peerDependencies": {
|
|
63
|
-
"@mariozechner/pi-coding-agent": "
|
|
65
|
+
"@mariozechner/pi-coding-agent": "^0.64.0"
|
|
64
66
|
},
|
|
65
67
|
"devDependencies": {
|
|
66
|
-
"@mariozechner/pi-coding-agent": "^0.
|
|
68
|
+
"@mariozechner/pi-coding-agent": "^0.64.0",
|
|
67
69
|
"@types/node": "^25.5.0",
|
|
68
|
-
"typescript": "^
|
|
70
|
+
"typescript": "^6.0.2"
|
|
69
71
|
}
|
|
70
72
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
import { homedir } from "node:os";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import type { MustHaveExtensionConfig } from "./types.js";
|
|
4
|
-
|
|
5
|
-
export const EXTENSION_NAME = "pi-must-have-extension";
|
|
6
|
-
export const CONFIG_DIR = join(homedir(), ".pi", "agent", "extensions", EXTENSION_NAME);
|
|
7
|
-
export const CONFIG_PATH = join(CONFIG_DIR, "config.jsonc");
|
|
8
|
-
|
|
9
|
-
export const LEGACY_PI_MUST_HAVE_PLUGIN_CONFIG_PATH = join(
|
|
10
|
-
homedir(),
|
|
11
|
-
".pi",
|
|
12
|
-
"agent",
|
|
13
|
-
"extensions",
|
|
14
|
-
"pi-must-have-plugin",
|
|
15
|
-
"config.jsonc",
|
|
16
|
-
);
|
|
17
|
-
export const LEGACY_MUST_HAVE_PLUGIN_CONFIG_PATH = join(
|
|
18
|
-
homedir(),
|
|
19
|
-
".pi",
|
|
20
|
-
"agent",
|
|
21
|
-
"extensions",
|
|
22
|
-
"must-have-plugin",
|
|
23
|
-
"config.jsonc",
|
|
24
|
-
);
|
|
25
|
-
export const LEGACY_OPENCODE_CONFIG_PATH = join(homedir(), ".config", "opencode", "MUST-have-plugin.jsonc");
|
|
26
|
-
|
|
27
|
-
export const RFC2119_DEFAULTS: Readonly<Record<string, string>> = {
|
|
28
|
-
must: "MUST",
|
|
29
|
-
"must not": "MUST NOT",
|
|
30
|
-
required: "REQUIRED",
|
|
31
|
-
shall: "SHALL",
|
|
32
|
-
"shall not": "SHALL NOT",
|
|
33
|
-
should: "SHOULD",
|
|
34
|
-
"should not": "SHOULD NOT",
|
|
35
|
-
recommended: "RECOMMENDED",
|
|
36
|
-
"not recommended": "NOT RECOMMENDED",
|
|
37
|
-
may: "MAY",
|
|
38
|
-
optional: "OPTIONAL",
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export const FALLBACK_CONFIG: MustHaveExtensionConfig = {
|
|
42
|
-
debug: false,
|
|
43
|
-
replacements: { ...RFC2119_DEFAULTS },
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export const DEFAULT_CONFIG = `{
|
|
47
|
-
// Enable debug notifications in the TUI
|
|
48
|
-
// "debug": true,
|
|
49
|
-
|
|
50
|
-
"replacements": {
|
|
51
|
-
"must": "MUST",
|
|
52
|
-
"must not": "MUST NOT",
|
|
53
|
-
"required": "REQUIRED",
|
|
54
|
-
"shall": "SHALL",
|
|
55
|
-
"shall not": "SHALL NOT",
|
|
56
|
-
"should": "SHOULD",
|
|
57
|
-
"should not": "SHOULD NOT",
|
|
58
|
-
"recommended": "RECOMMENDED",
|
|
59
|
-
"not recommended": "NOT RECOMMENDED",
|
|
60
|
-
"may": "MAY",
|
|
61
|
-
"optional": "OPTIONAL"
|
|
62
|
-
}
|
|
63
|
-
}\n`;
|
|
1
|
+
import { homedir } from "node:os";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { MustHaveExtensionConfig } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export const EXTENSION_NAME = "pi-must-have-extension";
|
|
6
|
+
export const CONFIG_DIR = join(homedir(), ".pi", "agent", "extensions", EXTENSION_NAME);
|
|
7
|
+
export const CONFIG_PATH = join(CONFIG_DIR, "config.jsonc");
|
|
8
|
+
|
|
9
|
+
export const LEGACY_PI_MUST_HAVE_PLUGIN_CONFIG_PATH = join(
|
|
10
|
+
homedir(),
|
|
11
|
+
".pi",
|
|
12
|
+
"agent",
|
|
13
|
+
"extensions",
|
|
14
|
+
"pi-must-have-plugin",
|
|
15
|
+
"config.jsonc",
|
|
16
|
+
);
|
|
17
|
+
export const LEGACY_MUST_HAVE_PLUGIN_CONFIG_PATH = join(
|
|
18
|
+
homedir(),
|
|
19
|
+
".pi",
|
|
20
|
+
"agent",
|
|
21
|
+
"extensions",
|
|
22
|
+
"must-have-plugin",
|
|
23
|
+
"config.jsonc",
|
|
24
|
+
);
|
|
25
|
+
export const LEGACY_OPENCODE_CONFIG_PATH = join(homedir(), ".config", "opencode", "MUST-have-plugin.jsonc");
|
|
26
|
+
|
|
27
|
+
export const RFC2119_DEFAULTS: Readonly<Record<string, string>> = {
|
|
28
|
+
must: "MUST",
|
|
29
|
+
"must not": "MUST NOT",
|
|
30
|
+
required: "REQUIRED",
|
|
31
|
+
shall: "SHALL",
|
|
32
|
+
"shall not": "SHALL NOT",
|
|
33
|
+
should: "SHOULD",
|
|
34
|
+
"should not": "SHOULD NOT",
|
|
35
|
+
recommended: "RECOMMENDED",
|
|
36
|
+
"not recommended": "NOT RECOMMENDED",
|
|
37
|
+
may: "MAY",
|
|
38
|
+
optional: "OPTIONAL",
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const FALLBACK_CONFIG: MustHaveExtensionConfig = {
|
|
42
|
+
debug: false,
|
|
43
|
+
replacements: { ...RFC2119_DEFAULTS },
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const DEFAULT_CONFIG = `{
|
|
47
|
+
// Enable debug notifications in the TUI
|
|
48
|
+
// "debug": true,
|
|
49
|
+
|
|
50
|
+
"replacements": {
|
|
51
|
+
"must": "MUST",
|
|
52
|
+
"must not": "MUST NOT",
|
|
53
|
+
"required": "REQUIRED",
|
|
54
|
+
"shall": "SHALL",
|
|
55
|
+
"shall not": "SHALL NOT",
|
|
56
|
+
"should": "SHOULD",
|
|
57
|
+
"should not": "SHOULD NOT",
|
|
58
|
+
"recommended": "RECOMMENDED",
|
|
59
|
+
"not recommended": "NOT RECOMMENDED",
|
|
60
|
+
"may": "MAY",
|
|
61
|
+
"optional": "OPTIONAL"
|
|
62
|
+
}
|
|
63
|
+
}\n`;
|