fastbrowser_cli 1.0.31 → 1.0.33
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/README.md +1 -2
- package/dist/fastbrowser_cli/fastbrowser_cli.js +11 -19
- package/dist/fastbrowser_cli/fastbrowser_cli.js.map +1 -1
- package/dist/fastbrowser_cli/libs/query-builder.d.ts +2 -0
- package/dist/fastbrowser_cli/libs/query-builder.d.ts.map +1 -1
- package/dist/fastbrowser_cli/libs/query-builder.js +4 -0
- package/dist/fastbrowser_cli/libs/query-builder.js.map +1 -1
- package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts +2 -0
- package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts.map +1 -1
- package/dist/fastbrowser_mcp/fastbrowser_mcp.d.ts.map +1 -1
- package/dist/fastbrowser_mcp/fastbrowser_mcp.js +147 -22
- package/dist/fastbrowser_mcp/fastbrowser_mcp.js.map +1 -1
- package/dist/fastbrowser_mcp/libs/mcp_my_client.d.ts.map +1 -1
- package/dist/fastbrowser_mcp/libs/mcp_my_client.js +8 -0
- package/dist/fastbrowser_mcp/libs/mcp_my_client.js.map +1 -1
- package/dist/fastbrowser_mcp/libs/mcp_target_helper.d.ts.map +1 -1
- package/dist/fastbrowser_mcp/libs/mcp_target_helper.js +15 -2
- package/dist/fastbrowser_mcp/libs/mcp_target_helper.js.map +1 -1
- package/dist/fastbrowser_mcp/libs/schemas.d.ts +4 -0
- package/dist/fastbrowser_mcp/libs/schemas.d.ts.map +1 -1
- package/dist/fastbrowser_mcp/libs/schemas.js +6 -0
- package/dist/fastbrowser_mcp/libs/schemas.js.map +1 -1
- package/dist/shared/logger.d.ts +86 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +269 -0
- package/dist/shared/logger.js.map +1 -0
- package/docs/brainstorm_scrap_by_ai.md +1 -1
- package/docs/feature_support_cli.md +7 -8
- package/docs/target_tools/target_tools_chrome_devtools.md +963 -0
- package/docs/target_tools/target_tools_playwright.md +763 -0
- package/examples/linkedin_cli/linked_dm.sh +16 -0
- package/examples/linkedin_cli/linked_post.sh +13 -0
- package/examples/linkedin_cli/linkedin.snapshot.txt +1245 -0
- package/examples/todomvc/todomvc.a11y.txt +44 -0
- package/examples/todomvc/todomvc.sh +11 -0
- package/examples/wttj_cli/fastbrowser_helper.ts +39 -0
- package/examples/wttj_cli/wttf_job-original.a11y.txt +652 -0
- package/examples/wttj_cli/wttf_job.a11y.txt +317 -0
- package/examples/{welcometothejungle/wttj-job.ts → wttj_cli/wttj_job copy.ts } +60 -11
- package/examples/wttj_cli/wttj_job.ts +179 -0
- package/examples/wttj_cli/wttj_search.ts +162 -0
- package/package.json +9 -3
- package/skills/fastbrowser/SKILL.md +10 -11
- package/skills/fastbrowser-script/SKILL.md +4 -4
- package/src/fastbrowser_cli/fastbrowser_cli.ts +14 -25
- package/src/fastbrowser_cli/libs/query-builder.ts +6 -0
- package/src/fastbrowser_mcp/fastbrowser_mcp.ts +181 -26
- package/src/fastbrowser_mcp/libs/mcp_my_client.ts +17 -0
- package/src/fastbrowser_mcp/libs/mcp_target_helper.ts +15 -2
- package/src/fastbrowser_mcp/libs/schemas.ts +6 -0
- package/src/shared/logger.ts +317 -0
- package/test.a11y.txt +828 -0
- package/tests/query-builder.test.ts +51 -11
- package/examples/welcometothejungle/fastbrowser_helper.ts +0 -39
- package/examples/welcometothejungle/wttj-search.ts +0 -82
- /package/examples/{post-to-x.sh → twitter_cli/twitter_post.sh} +0 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
// npm imports
|
|
2
|
+
import Chalk from 'chalk';
|
|
3
|
+
import { minimatch } from 'minimatch';
|
|
4
|
+
/**
|
|
5
|
+
* Simple logging utility with severity levels, colored output, and metadata support
|
|
6
|
+
*/
|
|
7
|
+
export class Logger {
|
|
8
|
+
/**
|
|
9
|
+
* Factory method to create a Logger from import.meta.url
|
|
10
|
+
* @param metaUrl - import.meta.url from the calling module
|
|
11
|
+
* @param minLevel - Minimum log level to display (defaults to WARN)
|
|
12
|
+
*/
|
|
13
|
+
static fromMetaUrl(metaUrl, loggerConfig = Logger.LoggerConfigDefault) {
|
|
14
|
+
// Use WHATWG URL (available in Node and browsers) instead of node:url.fileURLToPath
|
|
15
|
+
// so this module stays browser-safe when bundled by Vite.
|
|
16
|
+
const parsedUrl = new URL(metaUrl);
|
|
17
|
+
const absFilename = parsedUrl.pathname;
|
|
18
|
+
return new Logger(absFilename, loggerConfig);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* @param absFilename - Logger name (typically module path)
|
|
22
|
+
* @param minLevel - Minimum log level to display (defaults to INFO)
|
|
23
|
+
*/
|
|
24
|
+
constructor(absFilename, loggerConfig) {
|
|
25
|
+
this._loggerConfig = Logger.LoggerConfigDefault;
|
|
26
|
+
this._absFilename = absFilename;
|
|
27
|
+
this._loggerConfig = loggerConfig;
|
|
28
|
+
// Strip file extension from filename for glob matching. Done with string ops
|
|
29
|
+
// so this module avoids node:path and remains browser-safe.
|
|
30
|
+
const lastDotIndex = this._absFilename.lastIndexOf('.');
|
|
31
|
+
const lastSeparatorIndex = this._absFilename.lastIndexOf('/');
|
|
32
|
+
const hasExtension = lastDotIndex !== -1 && lastDotIndex > lastSeparatorIndex;
|
|
33
|
+
this._filenameWithoutExt = hasExtension === true
|
|
34
|
+
? this._absFilename.slice(0, lastDotIndex)
|
|
35
|
+
: this._absFilename;
|
|
36
|
+
// parse LOGGER environment variable for log filtering patterns. `process` is
|
|
37
|
+
// undefined in browsers, so guard the access.
|
|
38
|
+
const loggerEnvVar = typeof process !== 'undefined'
|
|
39
|
+
? process.env['LOGGER']
|
|
40
|
+
: undefined;
|
|
41
|
+
if (loggerEnvVar === undefined || loggerEnvVar === '') {
|
|
42
|
+
this._parsedPatterns = [];
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this._parsedPatterns = Logger.parseLoggerEnv(loggerEnvVar);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
49
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
50
|
+
// log filtering logic based on LOGGER environment variable
|
|
51
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
52
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
53
|
+
/**
|
|
54
|
+
* LOGGER environment variable domain specific language:
|
|
55
|
+
* - comma separated list of patterns
|
|
56
|
+
* - pattern1,pattern2,...,patternN
|
|
57
|
+
* Each pattern is:
|
|
58
|
+
* - {sign}{filename_glob}:{log_level}
|
|
59
|
+
* - sign: [-+] to add/remove filter
|
|
60
|
+
* - if omitted, defaults to + (enable)
|
|
61
|
+
* - if log_level is omitted, it defaults to WARN
|
|
62
|
+
* - log_level can be one of DEBUG, INFO, WARN, ERROR
|
|
63
|
+
* - filename_glob is applied to __filename from import.meta.url without the file extension
|
|
64
|
+
*
|
|
65
|
+
* Example:
|
|
66
|
+
* - LOGGER="*strategy*" enables WARN logs for all loggers with "strategy" in their name
|
|
67
|
+
* - LOGGER="*:DEBUG" enables DEBUG logs for all loggers
|
|
68
|
+
* - LOGGER="*strategy:DEBUG" enables DEBUG logs for all loggers with "strategy" in their name
|
|
69
|
+
* - LOGGER="-*strategy:DEBUG" disables DEBUG logs for all loggers with "strategy" in their name
|
|
70
|
+
* - LOGGER="*trading-core*:INFO" enables INFO logs for all loggers in the trading-core package
|
|
71
|
+
* - LOGGER='**:INFO' npm run dev:batch enables INFO logs for all loggers
|
|
72
|
+
*/
|
|
73
|
+
static parseLoggerEnv(loggerEnv) {
|
|
74
|
+
const loggerPatterns = [];
|
|
75
|
+
for (const rawPattern of loggerEnv.split(',')) {
|
|
76
|
+
const trimmedPattern = rawPattern.trim();
|
|
77
|
+
if (trimmedPattern.length === 0)
|
|
78
|
+
continue;
|
|
79
|
+
let enable = true;
|
|
80
|
+
let patternBody = trimmedPattern;
|
|
81
|
+
if (patternBody.startsWith('-')) {
|
|
82
|
+
enable = false;
|
|
83
|
+
patternBody = patternBody.slice(1);
|
|
84
|
+
}
|
|
85
|
+
else if (patternBody.startsWith('+')) {
|
|
86
|
+
patternBody = patternBody.slice(1);
|
|
87
|
+
}
|
|
88
|
+
const colonIndex = patternBody.lastIndexOf(':');
|
|
89
|
+
let glob;
|
|
90
|
+
let logLevel = Logger.DEFAULT_LEVEL;
|
|
91
|
+
if (colonIndex !== -1) {
|
|
92
|
+
const levelCandidate = patternBody.slice(colonIndex + 1).toUpperCase();
|
|
93
|
+
if (levelCandidate in Logger.LEVEL_RANK) {
|
|
94
|
+
glob = patternBody.slice(0, colonIndex);
|
|
95
|
+
logLevel = levelCandidate;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
glob = patternBody;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
glob = patternBody;
|
|
103
|
+
}
|
|
104
|
+
const loggerPattern = { enable, glob, level: logLevel };
|
|
105
|
+
loggerPatterns.push(loggerPattern);
|
|
106
|
+
}
|
|
107
|
+
return loggerPatterns;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Determine if a log message with the given log level should be filtered out based on the LOGGER environment variable patterns
|
|
111
|
+
* and the logger's filename.
|
|
112
|
+
* @param logLevel - Log level of the message
|
|
113
|
+
* @returns boolean indicating whether the message should be filtered out
|
|
114
|
+
*/
|
|
115
|
+
shouldBeFiltered(logLevel) {
|
|
116
|
+
// If no LOGGER env variable is set, default to filtering out logs below INFO
|
|
117
|
+
if (this._parsedPatterns.length === 0) {
|
|
118
|
+
const currentLevelRank = Logger.LEVEL_RANK[logLevel];
|
|
119
|
+
const minLevelRank = Logger.LEVEL_RANK[Logger.DEFAULT_LEVEL];
|
|
120
|
+
const shouldBeFiltered = currentLevelRank > minLevelRank;
|
|
121
|
+
return shouldBeFiltered;
|
|
122
|
+
}
|
|
123
|
+
// Walk patterns in order; last matching pattern wins
|
|
124
|
+
let minLevel = Logger.DEFAULT_LEVEL;
|
|
125
|
+
let hasMatched = false;
|
|
126
|
+
let isEnabled = true;
|
|
127
|
+
for (const parsedPattern of this._parsedPatterns) {
|
|
128
|
+
const globMatch = minimatch(this._filenameWithoutExt, parsedPattern.glob);
|
|
129
|
+
if (globMatch === false)
|
|
130
|
+
continue;
|
|
131
|
+
hasMatched = true;
|
|
132
|
+
isEnabled = parsedPattern.enable;
|
|
133
|
+
minLevel = parsedPattern.level;
|
|
134
|
+
}
|
|
135
|
+
// if there is filter, and it doesn't match, then filter out
|
|
136
|
+
if (hasMatched === false)
|
|
137
|
+
return true;
|
|
138
|
+
// if there is filter, and it matches, but it's disabled, then filter out
|
|
139
|
+
if (isEnabled === false)
|
|
140
|
+
return true;
|
|
141
|
+
// if there is filter, and it matches, and it's enabled, then check log level
|
|
142
|
+
const currentLevelRank = Logger.LEVEL_RANK[logLevel];
|
|
143
|
+
const minLevelRank = Logger.LEVEL_RANK[minLevel];
|
|
144
|
+
const shouldBeFiltered = currentLevelRank > minLevelRank;
|
|
145
|
+
// if log level is below the minimum level specified in the filter, then filter out
|
|
146
|
+
return shouldBeFiltered;
|
|
147
|
+
}
|
|
148
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
149
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
150
|
+
// private log function
|
|
151
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
152
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
153
|
+
/**
|
|
154
|
+
* Core logging method
|
|
155
|
+
* @param logLevel - Log level
|
|
156
|
+
* @param msg - Log message
|
|
157
|
+
* @param meta - Optional metadata object to display
|
|
158
|
+
*/
|
|
159
|
+
_log(logLevel, msg, meta) {
|
|
160
|
+
// // Skip if log level is below minimum threshold
|
|
161
|
+
const shouldBeFiltered = this.shouldBeFiltered(logLevel);
|
|
162
|
+
if (shouldBeFiltered)
|
|
163
|
+
return;
|
|
164
|
+
// Create a nounce base on this._filenameWithoutExt string
|
|
165
|
+
const nounceFromFilename = this._filenameWithoutExt.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0);
|
|
166
|
+
const colorFns = [
|
|
167
|
+
Chalk.magenta,
|
|
168
|
+
Chalk.blueBright,
|
|
169
|
+
Chalk.green,
|
|
170
|
+
Chalk.yellow,
|
|
171
|
+
];
|
|
172
|
+
const colorFn = colorFns[nounceFromFilename % colorFns.length];
|
|
173
|
+
const timestamp = new Date();
|
|
174
|
+
const colorize = Logger.LEVEL_COLOR[logLevel];
|
|
175
|
+
const fileName15Char = this._filenameWithoutExt.length <= Logger._maxFilenameLength
|
|
176
|
+
? this._filenameWithoutExt
|
|
177
|
+
: '...' + this._filenameWithoutExt.slice(-Logger._maxFilenameLength + 3);
|
|
178
|
+
const parts = [
|
|
179
|
+
// Chalk.dim(timestamp.toISOString()),
|
|
180
|
+
colorize(logLevel.padEnd(5)),
|
|
181
|
+
colorFn(fileName15Char.padEnd(15)),
|
|
182
|
+
msg,
|
|
183
|
+
];
|
|
184
|
+
// Append metadata if provided
|
|
185
|
+
if (meta !== undefined && Object.keys(meta).length > 0) {
|
|
186
|
+
const metaString = Object.entries(meta)
|
|
187
|
+
.map(([key, value]) => `${Chalk.green(key)}=${Chalk.white(typeof value === 'string' ? value : JSON.stringify(value))}`)
|
|
188
|
+
.join(' ');
|
|
189
|
+
parts.push(Chalk.dim('|'), metaString);
|
|
190
|
+
}
|
|
191
|
+
const line = parts.join(' ');
|
|
192
|
+
// Error and warn levels go to stderr, others to stdout
|
|
193
|
+
if (logLevel === 'WARN' || logLevel === 'ERROR' || this._loggerConfig.allToStderr === true) {
|
|
194
|
+
console.error(line);
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
console.log(line);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
201
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
202
|
+
// public logging methods
|
|
203
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
204
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
205
|
+
// Public logging methods for each severity level
|
|
206
|
+
debug(msg, meta) {
|
|
207
|
+
this._log('DEBUG', msg, meta);
|
|
208
|
+
}
|
|
209
|
+
info(msg, meta) {
|
|
210
|
+
this._log('INFO', msg, meta);
|
|
211
|
+
}
|
|
212
|
+
warn(msg, meta) {
|
|
213
|
+
this._log('WARN', msg, meta);
|
|
214
|
+
}
|
|
215
|
+
error(msg, meta) {
|
|
216
|
+
this._log('ERROR', msg, meta);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
Logger.LEVEL = {
|
|
220
|
+
DEBUG: 'DEBUG',
|
|
221
|
+
INFO: 'INFO',
|
|
222
|
+
WARN: 'WARN',
|
|
223
|
+
ERROR: 'ERROR',
|
|
224
|
+
};
|
|
225
|
+
Logger.DEFAULT_LEVEL = Logger.LEVEL.WARN;
|
|
226
|
+
/** Rank mapping for log level filtering */
|
|
227
|
+
Logger.LEVEL_RANK = {
|
|
228
|
+
DEBUG: 3,
|
|
229
|
+
INFO: 2,
|
|
230
|
+
WARN: 1,
|
|
231
|
+
ERROR: 0
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Maximum length for filename in log output; longer names will be truncated with ellipsis. This is to prevent log lines
|
|
235
|
+
* from becoming too long due to long file paths.
|
|
236
|
+
*/
|
|
237
|
+
Logger._maxFilenameLength = 30;
|
|
238
|
+
/** Color scheme for each log level */
|
|
239
|
+
Logger.LEVEL_COLOR = {
|
|
240
|
+
DEBUG: Chalk.gray,
|
|
241
|
+
INFO: Chalk.cyan,
|
|
242
|
+
WARN: Chalk.yellow,
|
|
243
|
+
ERROR: Chalk.red,
|
|
244
|
+
};
|
|
245
|
+
//
|
|
246
|
+
Logger.LoggerConfigDefault = {
|
|
247
|
+
allToStderr: false,
|
|
248
|
+
};
|
|
249
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
250
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
251
|
+
// Usage Example
|
|
252
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
253
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
254
|
+
async function usageExample() {
|
|
255
|
+
process.env.LOGGER = '**:INFO'; // Enable DEBUG logs for this logger
|
|
256
|
+
console.log(Chalk.blue('--- Logger Usage Example ---'));
|
|
257
|
+
console.log(Chalk.blue('Current LOGGER env variable:'), process.env.LOGGER);
|
|
258
|
+
const logger = Logger.fromMetaUrl(import.meta.url);
|
|
259
|
+
logger.debug('This is a debug message', { user: 'alice', action: 'testDebug' });
|
|
260
|
+
logger.info('This is an info message', { user: 'bob', action: 'testInfo' });
|
|
261
|
+
logger.warn('This is a warning message', { user: 'carol', action: 'testWarn' });
|
|
262
|
+
logger.error('This is an error message', { user: 'dave', action: 'testError' });
|
|
263
|
+
}
|
|
264
|
+
if (import.meta.main) {
|
|
265
|
+
usageExample().catch(err => {
|
|
266
|
+
console.error('Error in usage example:', err);
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,4 +29,4 @@
|
|
|
29
29
|
- possible by selector language ? yes
|
|
30
30
|
- get link with an url starting with "https://www.welcometothejungle.com/fr/companies/"
|
|
31
31
|
- on a https://www.welcometothejungle.com/fr/jobs?refinementList%5Boffices.country_code%5D%5B%5D=FR&query=machine%20learning&page=7
|
|
32
|
-
- `npx tsx ./src/fastbrowser_cli/fastbrowser_cli.ts
|
|
32
|
+
- `npx tsx ./src/fastbrowser_cli/fastbrowser_cli.ts query_selectors --all --selector 'RootWebArea > link[url^="https://www.welcometothejungle.com/fr/companies/"]'`
|
|
@@ -56,14 +56,6 @@ fastbrowser-cli click -s 'button[name="Submit"]'
|
|
|
56
56
|
# Fill a form field by accessibility selector
|
|
57
57
|
fastbrowser-cli fill_form -s 'textbox[name="Email"]' --value "hello@example.com"
|
|
58
58
|
|
|
59
|
-
# Query the accessibility tree — --selector can be repeated for multiple selectors.
|
|
60
|
-
# --limit and --with-ancestors apply to all selectors equally.
|
|
61
|
-
fastbrowser-cli query_selectors_all --selector "button" --selector "link" --limit 5 --with-ancestors
|
|
62
|
-
fastbrowser-cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
|
|
63
|
-
|
|
64
|
-
# For per-selector control over limit/withAncestors, pass a JSON array directly:
|
|
65
|
-
fastbrowser-cli query_selectors_all --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
|
|
66
|
-
|
|
67
59
|
# Query the accessibility tree for the first matching element per selector (mirrors DOM querySelector).
|
|
68
60
|
# --selector can be repeated for multiple selectors; --with-ancestors applies to all.
|
|
69
61
|
fastbrowser-cli query_selectors --selector "button"
|
|
@@ -72,6 +64,13 @@ fastbrowser-cli query_selectors --selector "button" --selector "link" --no-with-
|
|
|
72
64
|
# For per-selector control over withAncestors, pass a JSON array directly:
|
|
73
65
|
fastbrowser-cli query_selectors --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
|
|
74
66
|
|
|
67
|
+
# Pass -a/--all to return every match per selector. --limit caps results per selector (0 = unlimited).
|
|
68
|
+
fastbrowser-cli query_selectors --all --selector "button" --selector "link" --limit 5 --with-ancestors
|
|
69
|
+
fastbrowser-cli query_selectors --all --selector 'heading[level="1"]' --no-with-ancestors
|
|
70
|
+
|
|
71
|
+
# For per-selector control over limit/withAncestors with --all, pass a JSON array directly:
|
|
72
|
+
fastbrowser-cli query_selectors --all --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
|
|
73
|
+
|
|
75
74
|
# Press a sequence of keys
|
|
76
75
|
fastbrowser-cli press_keys --keys "Tab, Tab, Enter"
|
|
77
76
|
fastbrowser-cli press_keys --keys "Hello, Tab, Enter"
|