@optique/core 1.0.0-dev.407 → 1.0.0-dev.416

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 CHANGED
@@ -1,9 +1,6 @@
1
1
  @optique/core
2
2
  =============
3
3
 
4
- > [!WARNING]
5
- > The API is stabilizing, but may change before the 1.0 release.
6
-
7
4
  The core package of Optique which provides the shared types and parser
8
5
  combinators. It is designed to be used in universal JavaScript runtimes,
9
6
  including Node.js, Deno, Bun, edge functions, and web browsers—although
package/dist/message.cjs CHANGED
@@ -253,115 +253,127 @@ function formatMessage(msg, options = {}) {
253
253
  const resetSequence = `\x1b[0m${resetSuffix}`;
254
254
  function* stream() {
255
255
  const wordPattern = /\s*\S+\s*/g;
256
- for (const term of msg) if (term.type === "text") if (term.text.includes("\n\n")) {
257
- const paragraphs = term.text.split(/\n\n+/);
258
- for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
259
- if (paragraphIndex > 0) yield {
260
- text: "\n\n",
261
- width: -1
262
- };
263
- const paragraph = paragraphs[paragraphIndex].replace(/\n/g, " ");
264
- wordPattern.lastIndex = 0;
265
- while (true) {
266
- const match = wordPattern.exec(paragraph);
267
- if (match == null) break;
268
- yield {
269
- text: match[0],
270
- width: match[0].length
256
+ let prevWasLineBreak = false;
257
+ for (const term of msg) {
258
+ const isAfterLineBreak = prevWasLineBreak;
259
+ prevWasLineBreak = false;
260
+ if (term.type === "text") {
261
+ const rawText = isAfterLineBreak ? term.text.replace(/^\n(?!\n)/, "") : term.text;
262
+ if (rawText.includes("\n\n")) {
263
+ const paragraphs = rawText.split(/\n\n+/);
264
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
265
+ if (paragraphIndex > 0) {
266
+ const breakText = isAfterLineBreak && paragraphIndex === 1 ? "\n" : "\n\n";
267
+ yield {
268
+ text: breakText,
269
+ width: -1
270
+ };
271
+ }
272
+ const paragraph = paragraphs[paragraphIndex].replace(/\n/g, " ");
273
+ wordPattern.lastIndex = 0;
274
+ while (true) {
275
+ const match = wordPattern.exec(paragraph);
276
+ if (match == null) break;
277
+ yield {
278
+ text: match[0],
279
+ width: match[0].length
280
+ };
281
+ }
282
+ }
283
+ } else {
284
+ const normalizedText = rawText.replace(/\n/g, " ");
285
+ if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
286
+ text: " ",
287
+ width: 1
271
288
  };
289
+ else {
290
+ wordPattern.lastIndex = 0;
291
+ while (true) {
292
+ const match = wordPattern.exec(normalizedText);
293
+ if (match == null) break;
294
+ yield {
295
+ text: match[0],
296
+ width: match[0].length
297
+ };
298
+ }
299
+ }
272
300
  }
273
- }
274
- } else {
275
- const normalizedText = term.text.replace(/\n/g, " ");
276
- if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
277
- text: " ",
278
- width: 1
279
- };
280
- else {
281
- wordPattern.lastIndex = 0;
282
- while (true) {
283
- const match = wordPattern.exec(normalizedText);
284
- if (match == null) break;
301
+ } else if (term.type === "optionName") {
302
+ const name = useQuotes ? `\`${term.optionName}\`` : term.optionName;
303
+ yield {
304
+ text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
305
+ width: name.length
306
+ };
307
+ } else if (term.type === "optionNames") {
308
+ const names = term.optionNames.map((name) => useQuotes ? `\`${name}\`` : name);
309
+ let i = 0;
310
+ for (const name of names) {
311
+ if (i > 0) yield {
312
+ text: "/",
313
+ width: 1
314
+ };
285
315
  yield {
286
- text: match[0],
287
- width: match[0].length
316
+ text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
317
+ width: name.length
288
318
  };
319
+ i++;
289
320
  }
290
- }
291
- }
292
- else if (term.type === "optionName") {
293
- const name = useQuotes ? `\`${term.optionName}\`` : term.optionName;
294
- yield {
295
- text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
296
- width: name.length
297
- };
298
- } else if (term.type === "optionNames") {
299
- const names = term.optionNames.map((name) => useQuotes ? `\`${name}\`` : name);
300
- let i = 0;
301
- for (const name of names) {
321
+ } else if (term.type === "metavar") {
322
+ const metavar$1 = useQuotes ? `\`${term.metavar}\`` : term.metavar;
323
+ yield {
324
+ text: useColors ? `\x1b[1m${metavar$1}${resetSequence}` : metavar$1,
325
+ width: metavar$1.length
326
+ };
327
+ } else if (term.type === "value") {
328
+ const value$1 = useQuotes ? `${JSON.stringify(term.value)}` : term.value;
329
+ yield {
330
+ text: useColors ? `\x1b[32m${value$1}${resetSequence}` : value$1,
331
+ width: value$1.length
332
+ };
333
+ } else if (term.type === "values") for (let i = 0; i < term.values.length; i++) {
302
334
  if (i > 0) yield {
303
- text: "/",
335
+ text: " ",
304
336
  width: 1
305
337
  };
338
+ const value$1 = useQuotes ? JSON.stringify(term.values[i]) : term.values[i];
306
339
  yield {
307
- text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
308
- width: name.length
340
+ text: useColors ? i <= 0 ? `\x1b[32m${value$1}` : i + 1 >= term.values.length ? `${value$1}${resetSequence}` : value$1 : value$1,
341
+ width: value$1.length
309
342
  };
310
- i++;
311
343
  }
312
- } else if (term.type === "metavar") {
313
- const metavar$1 = useQuotes ? `\`${term.metavar}\`` : term.metavar;
314
- yield {
315
- text: useColors ? `\x1b[1m${metavar$1}${resetSequence}` : metavar$1,
316
- width: metavar$1.length
317
- };
318
- } else if (term.type === "value") {
319
- const value$1 = useQuotes ? `${JSON.stringify(term.value)}` : term.value;
320
- yield {
321
- text: useColors ? `\x1b[32m${value$1}${resetSequence}` : value$1,
322
- width: value$1.length
323
- };
324
- } else if (term.type === "values") for (let i = 0; i < term.values.length; i++) {
325
- if (i > 0) yield {
326
- text: " ",
327
- width: 1
328
- };
329
- const value$1 = useQuotes ? JSON.stringify(term.values[i]) : term.values[i];
330
- yield {
331
- text: useColors ? i <= 0 ? `\x1b[32m${value$1}` : i + 1 >= term.values.length ? `${value$1}${resetSequence}` : value$1 : value$1,
332
- width: value$1.length
333
- };
334
- }
335
- else if (term.type === "envVar") {
336
- const envVar$1 = useQuotes ? `\`${term.envVar}\`` : term.envVar;
337
- yield {
338
- text: useColors ? `\x1b[1;4m${envVar$1}${resetSequence}` : envVar$1,
339
- width: envVar$1.length
340
- };
341
- } else if (term.type === "commandLine") {
342
- const cmd = useQuotes ? `\`${term.commandLine}\`` : term.commandLine;
343
- yield {
344
- text: useColors ? `\x1b[36m${cmd}${resetSequence}` : cmd,
345
- width: cmd.length
346
- };
347
- } else if (term.type === "lineBreak") yield {
348
- text: "\n",
349
- width: -1
350
- };
351
- else if (term.type === "url") {
352
- const urlString = term.url.href;
353
- const displayText = useQuotes ? `<${urlString}>` : urlString;
354
- if (useColors) {
355
- const hyperlink = `\x1b]8;;${urlString}\x1b\\${displayText}\x1b]8;;\x1b\\${resetSuffix}`;
344
+ else if (term.type === "envVar") {
345
+ const envVar$1 = useQuotes ? `\`${term.envVar}\`` : term.envVar;
356
346
  yield {
357
- text: hyperlink,
347
+ text: useColors ? `\x1b[1;4m${envVar$1}${resetSequence}` : envVar$1,
348
+ width: envVar$1.length
349
+ };
350
+ } else if (term.type === "commandLine") {
351
+ const cmd = useQuotes ? `\`${term.commandLine}\`` : term.commandLine;
352
+ yield {
353
+ text: useColors ? `\x1b[36m${cmd}${resetSequence}` : cmd,
354
+ width: cmd.length
355
+ };
356
+ } else if (term.type === "lineBreak") {
357
+ yield {
358
+ text: "\n",
359
+ width: -1
360
+ };
361
+ prevWasLineBreak = true;
362
+ } else if (term.type === "url") {
363
+ const urlString = term.url.href;
364
+ const displayText = useQuotes ? `<${urlString}>` : urlString;
365
+ if (useColors) {
366
+ const hyperlink = `\x1b]8;;${urlString}\x1b\\${displayText}\x1b]8;;\x1b\\${resetSuffix}`;
367
+ yield {
368
+ text: hyperlink,
369
+ width: displayText.length
370
+ };
371
+ } else yield {
372
+ text: displayText,
358
373
  width: displayText.length
359
374
  };
360
- } else yield {
361
- text: displayText,
362
- width: displayText.length
363
- };
364
- } else throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
375
+ } else throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
376
+ }
365
377
  }
366
378
  let output = "";
367
379
  let totalWidth = 0;
package/dist/message.js CHANGED
@@ -252,115 +252,127 @@ function formatMessage(msg, options = {}) {
252
252
  const resetSequence = `\x1b[0m${resetSuffix}`;
253
253
  function* stream() {
254
254
  const wordPattern = /\s*\S+\s*/g;
255
- for (const term of msg) if (term.type === "text") if (term.text.includes("\n\n")) {
256
- const paragraphs = term.text.split(/\n\n+/);
257
- for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
258
- if (paragraphIndex > 0) yield {
259
- text: "\n\n",
260
- width: -1
261
- };
262
- const paragraph = paragraphs[paragraphIndex].replace(/\n/g, " ");
263
- wordPattern.lastIndex = 0;
264
- while (true) {
265
- const match = wordPattern.exec(paragraph);
266
- if (match == null) break;
267
- yield {
268
- text: match[0],
269
- width: match[0].length
255
+ let prevWasLineBreak = false;
256
+ for (const term of msg) {
257
+ const isAfterLineBreak = prevWasLineBreak;
258
+ prevWasLineBreak = false;
259
+ if (term.type === "text") {
260
+ const rawText = isAfterLineBreak ? term.text.replace(/^\n(?!\n)/, "") : term.text;
261
+ if (rawText.includes("\n\n")) {
262
+ const paragraphs = rawText.split(/\n\n+/);
263
+ for (let paragraphIndex = 0; paragraphIndex < paragraphs.length; paragraphIndex++) {
264
+ if (paragraphIndex > 0) {
265
+ const breakText = isAfterLineBreak && paragraphIndex === 1 ? "\n" : "\n\n";
266
+ yield {
267
+ text: breakText,
268
+ width: -1
269
+ };
270
+ }
271
+ const paragraph = paragraphs[paragraphIndex].replace(/\n/g, " ");
272
+ wordPattern.lastIndex = 0;
273
+ while (true) {
274
+ const match = wordPattern.exec(paragraph);
275
+ if (match == null) break;
276
+ yield {
277
+ text: match[0],
278
+ width: match[0].length
279
+ };
280
+ }
281
+ }
282
+ } else {
283
+ const normalizedText = rawText.replace(/\n/g, " ");
284
+ if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
285
+ text: " ",
286
+ width: 1
270
287
  };
288
+ else {
289
+ wordPattern.lastIndex = 0;
290
+ while (true) {
291
+ const match = wordPattern.exec(normalizedText);
292
+ if (match == null) break;
293
+ yield {
294
+ text: match[0],
295
+ width: match[0].length
296
+ };
297
+ }
298
+ }
271
299
  }
272
- }
273
- } else {
274
- const normalizedText = term.text.replace(/\n/g, " ");
275
- if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
276
- text: " ",
277
- width: 1
278
- };
279
- else {
280
- wordPattern.lastIndex = 0;
281
- while (true) {
282
- const match = wordPattern.exec(normalizedText);
283
- if (match == null) break;
300
+ } else if (term.type === "optionName") {
301
+ const name = useQuotes ? `\`${term.optionName}\`` : term.optionName;
302
+ yield {
303
+ text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
304
+ width: name.length
305
+ };
306
+ } else if (term.type === "optionNames") {
307
+ const names = term.optionNames.map((name) => useQuotes ? `\`${name}\`` : name);
308
+ let i = 0;
309
+ for (const name of names) {
310
+ if (i > 0) yield {
311
+ text: "/",
312
+ width: 1
313
+ };
284
314
  yield {
285
- text: match[0],
286
- width: match[0].length
315
+ text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
316
+ width: name.length
287
317
  };
318
+ i++;
288
319
  }
289
- }
290
- }
291
- else if (term.type === "optionName") {
292
- const name = useQuotes ? `\`${term.optionName}\`` : term.optionName;
293
- yield {
294
- text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
295
- width: name.length
296
- };
297
- } else if (term.type === "optionNames") {
298
- const names = term.optionNames.map((name) => useQuotes ? `\`${name}\`` : name);
299
- let i = 0;
300
- for (const name of names) {
320
+ } else if (term.type === "metavar") {
321
+ const metavar$1 = useQuotes ? `\`${term.metavar}\`` : term.metavar;
322
+ yield {
323
+ text: useColors ? `\x1b[1m${metavar$1}${resetSequence}` : metavar$1,
324
+ width: metavar$1.length
325
+ };
326
+ } else if (term.type === "value") {
327
+ const value$1 = useQuotes ? `${JSON.stringify(term.value)}` : term.value;
328
+ yield {
329
+ text: useColors ? `\x1b[32m${value$1}${resetSequence}` : value$1,
330
+ width: value$1.length
331
+ };
332
+ } else if (term.type === "values") for (let i = 0; i < term.values.length; i++) {
301
333
  if (i > 0) yield {
302
- text: "/",
334
+ text: " ",
303
335
  width: 1
304
336
  };
337
+ const value$1 = useQuotes ? JSON.stringify(term.values[i]) : term.values[i];
305
338
  yield {
306
- text: useColors ? `\x1b[3m${name}${resetSequence}` : name,
307
- width: name.length
339
+ text: useColors ? i <= 0 ? `\x1b[32m${value$1}` : i + 1 >= term.values.length ? `${value$1}${resetSequence}` : value$1 : value$1,
340
+ width: value$1.length
308
341
  };
309
- i++;
310
342
  }
311
- } else if (term.type === "metavar") {
312
- const metavar$1 = useQuotes ? `\`${term.metavar}\`` : term.metavar;
313
- yield {
314
- text: useColors ? `\x1b[1m${metavar$1}${resetSequence}` : metavar$1,
315
- width: metavar$1.length
316
- };
317
- } else if (term.type === "value") {
318
- const value$1 = useQuotes ? `${JSON.stringify(term.value)}` : term.value;
319
- yield {
320
- text: useColors ? `\x1b[32m${value$1}${resetSequence}` : value$1,
321
- width: value$1.length
322
- };
323
- } else if (term.type === "values") for (let i = 0; i < term.values.length; i++) {
324
- if (i > 0) yield {
325
- text: " ",
326
- width: 1
327
- };
328
- const value$1 = useQuotes ? JSON.stringify(term.values[i]) : term.values[i];
329
- yield {
330
- text: useColors ? i <= 0 ? `\x1b[32m${value$1}` : i + 1 >= term.values.length ? `${value$1}${resetSequence}` : value$1 : value$1,
331
- width: value$1.length
332
- };
333
- }
334
- else if (term.type === "envVar") {
335
- const envVar$1 = useQuotes ? `\`${term.envVar}\`` : term.envVar;
336
- yield {
337
- text: useColors ? `\x1b[1;4m${envVar$1}${resetSequence}` : envVar$1,
338
- width: envVar$1.length
339
- };
340
- } else if (term.type === "commandLine") {
341
- const cmd = useQuotes ? `\`${term.commandLine}\`` : term.commandLine;
342
- yield {
343
- text: useColors ? `\x1b[36m${cmd}${resetSequence}` : cmd,
344
- width: cmd.length
345
- };
346
- } else if (term.type === "lineBreak") yield {
347
- text: "\n",
348
- width: -1
349
- };
350
- else if (term.type === "url") {
351
- const urlString = term.url.href;
352
- const displayText = useQuotes ? `<${urlString}>` : urlString;
353
- if (useColors) {
354
- const hyperlink = `\x1b]8;;${urlString}\x1b\\${displayText}\x1b]8;;\x1b\\${resetSuffix}`;
343
+ else if (term.type === "envVar") {
344
+ const envVar$1 = useQuotes ? `\`${term.envVar}\`` : term.envVar;
355
345
  yield {
356
- text: hyperlink,
346
+ text: useColors ? `\x1b[1;4m${envVar$1}${resetSequence}` : envVar$1,
347
+ width: envVar$1.length
348
+ };
349
+ } else if (term.type === "commandLine") {
350
+ const cmd = useQuotes ? `\`${term.commandLine}\`` : term.commandLine;
351
+ yield {
352
+ text: useColors ? `\x1b[36m${cmd}${resetSequence}` : cmd,
353
+ width: cmd.length
354
+ };
355
+ } else if (term.type === "lineBreak") {
356
+ yield {
357
+ text: "\n",
358
+ width: -1
359
+ };
360
+ prevWasLineBreak = true;
361
+ } else if (term.type === "url") {
362
+ const urlString = term.url.href;
363
+ const displayText = useQuotes ? `<${urlString}>` : urlString;
364
+ if (useColors) {
365
+ const hyperlink = `\x1b]8;;${urlString}\x1b\\${displayText}\x1b]8;;\x1b\\${resetSuffix}`;
366
+ yield {
367
+ text: hyperlink,
368
+ width: displayText.length
369
+ };
370
+ } else yield {
371
+ text: displayText,
357
372
  width: displayText.length
358
373
  };
359
- } else yield {
360
- text: displayText,
361
- width: displayText.length
362
- };
363
- } else throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
374
+ } else throw new TypeError(`Invalid MessageTerm type: ${term["type"]}.`);
375
+ }
364
376
  }
365
377
  let output = "";
366
378
  let totalWidth = 0;
package/dist/parser.cjs CHANGED
@@ -350,11 +350,11 @@ function getDocPageSyncImpl(parser, args, options) {
350
350
  state: initialState,
351
351
  usage: parser.usage
352
352
  };
353
- do {
353
+ while (context.buffer.length > 0) {
354
354
  const result = parser.parse(context);
355
355
  if (!result.success) break;
356
356
  context = result.next;
357
- } while (context.buffer.length > 0);
357
+ }
358
358
  return buildDocPage(parser, context, args);
359
359
  }
360
360
  /**
@@ -372,11 +372,11 @@ async function getDocPageAsyncImpl(parser, args, options) {
372
372
  state: initialState,
373
373
  usage: parser.usage
374
374
  };
375
- do {
375
+ while (context.buffer.length > 0) {
376
376
  const result = await parser.parse(context);
377
377
  if (!result.success) break;
378
378
  context = result.next;
379
- } while (context.buffer.length > 0);
379
+ }
380
380
  return buildDocPage(parser, context, args);
381
381
  }
382
382
  /**
package/dist/parser.js CHANGED
@@ -350,11 +350,11 @@ function getDocPageSyncImpl(parser, args, options) {
350
350
  state: initialState,
351
351
  usage: parser.usage
352
352
  };
353
- do {
353
+ while (context.buffer.length > 0) {
354
354
  const result = parser.parse(context);
355
355
  if (!result.success) break;
356
356
  context = result.next;
357
- } while (context.buffer.length > 0);
357
+ }
358
358
  return buildDocPage(parser, context, args);
359
359
  }
360
360
  /**
@@ -372,11 +372,11 @@ async function getDocPageAsyncImpl(parser, args, options) {
372
372
  state: initialState,
373
373
  usage: parser.usage
374
374
  };
375
- do {
375
+ while (context.buffer.length > 0) {
376
376
  const result = await parser.parse(context);
377
377
  if (!result.success) break;
378
378
  context = result.next;
379
- } while (context.buffer.length > 0);
379
+ }
380
380
  return buildDocPage(parser, context, args);
381
381
  }
382
382
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.0.0-dev.407+21363ee4",
3
+ "version": "1.0.0-dev.416+db8179aa",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",