primcli 1.62.0 → 1.62.1

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.
Files changed (2) hide show
  1. package/dist/oclif/index.js +34 -10
  2. package/package.json +1 -1
@@ -42320,6 +42320,8 @@ const HEADER_FROM = /^\s*\*?From:\*?\s+\S/i;
42320
42320
  const HEADER_OTHER = /^\s*\*?(Sent|Date|To|Subject):\*?\s/i;
42321
42321
  const QUOTED_LINE = /^\s*>/;
42322
42322
  const FORWARDED = /^\s*(?:-{2,}\s*Forwarded message\s*-{2,}|Begin forwarded message:)\s*$/i;
42323
+ const FORWARD_SUBJECT = /^\s*(?:fwd?|wg|tr)\s*:/i;
42324
+ const ANSWERS_INLINE = /\b(?:in-?line|below|interleaved|in (?:red|blue|green|bold|caps|capitals))\b/i;
42323
42325
  /**
42324
42326
  * Whether line `i` opens a copied header block ("From:", then "Sent:" or
42325
42327
  * "Date:", "To:" and "Subject:" lines), the way Outlook introduces the message
@@ -42348,6 +42350,11 @@ function onlyQuotedAfter(lines, from) {
42348
42350
  }
42349
42351
  return true;
42350
42352
  }
42353
+ /** Whether line `i` is an "On <date>, <name> wrote:" line, on one line or two. */
42354
+ function isAttribution(lines, i) {
42355
+ const line = lines[i] ?? "";
42356
+ return WROTE_ONE_LINE.test(line) || WROTE_FIRST_LINE.test(line) && WROTE_LAST_LINE.test(lines[i + 1] ?? "");
42357
+ }
42351
42358
  /**
42352
42359
  * Index of the line where quoted history starts, or -1 when there is none.
42353
42360
  */
@@ -42369,25 +42376,35 @@ function quotedHistoryStart(lines) {
42369
42376
  * Remove the quoted history a reply carries below its new text: everything
42370
42377
  * from an attribution line, an "Original Message" rule or a copied header
42371
42378
  * block onward, and any run of ">" lines the message ends with. Quoted lines
42372
- * with the sender's own text after them (an inline reply) are kept. A body
42373
- * that forwards a message is returned whole, since the forwarded text is what
42374
- * the sender wants read, and so is one where removing the history would leave
42375
- * nothing.
42379
+ * with the sender's own text after them (an inline reply) are kept. A message
42380
+ * that forwards another (by its subject or a forwarding banner) is returned
42381
+ * whole, since the forwarded text is what the sender wants read, and so is
42382
+ * one where removing the history would leave nothing.
42376
42383
  */
42377
- function stripQuotedHistory(body) {
42384
+ function stripQuotedHistory(body, subject) {
42378
42385
  const original = body.replace(/\r\n?/g, "\n").trim();
42379
42386
  let lines = original.split("\n");
42380
- if (lines.some((line) => FORWARDED.test(line))) return {
42387
+ if (FORWARD_SUBJECT.test(subject ?? "") || lines.some((line) => FORWARDED.test(line))) return {
42381
42388
  text: original,
42382
42389
  removed: 0
42383
42390
  };
42384
42391
  const start = quotedHistoryStart(lines);
42385
- if (start !== -1) lines = lines.slice(0, start);
42392
+ if (start !== -1) {
42393
+ if (!isAttribution(lines, start) && ANSWERS_INLINE.test(lines.slice(0, start).join("\n"))) return {
42394
+ text: original,
42395
+ removed: 0
42396
+ };
42397
+ lines = lines.slice(0, start);
42398
+ }
42399
+ if (isInlineExchange(lines)) return finish(original, lines);
42386
42400
  while (lines.length > 0) {
42387
42401
  const last = lines[lines.length - 1] ?? "";
42388
42402
  if (last.trim() !== "" && !QUOTED_LINE.test(last)) break;
42389
42403
  lines.pop();
42390
42404
  }
42405
+ return finish(original, lines);
42406
+ }
42407
+ function finish(original, lines) {
42391
42408
  const text = lines.join("\n").trim();
42392
42409
  if (text === "") return {
42393
42410
  text: original,
@@ -42398,6 +42415,13 @@ function stripQuotedHistory(body) {
42398
42415
  removed: original.length - text.length
42399
42416
  };
42400
42417
  }
42418
+ /** Whether a quoted line is followed, somewhere later, by the sender's own text. */
42419
+ function isInlineExchange(lines) {
42420
+ let quoted = false;
42421
+ for (const line of lines) if (QUOTED_LINE.test(line)) quoted = true;
42422
+ else if (quoted && line.trim() !== "") return true;
42423
+ return false;
42424
+ }
42401
42425
  const NAMED_ENTITIES = {
42402
42426
  amp: "&",
42403
42427
  lt: "<",
@@ -42432,8 +42456,8 @@ function removeAll(text, pattern, replacement = " ") {
42432
42456
  function htmlToText(html) {
42433
42457
  let text = removeAll(html, /<!--[\s\S]*?-->/g);
42434
42458
  text = removeAll(text, /<(script|style|head|title)\b[\s\S]*?<\/\1\s*>/gi);
42435
- text = text.replace(/<a\b[^>]*?\bhref\s*=\s*(?:"([^"]*)"|'([^']*)')[^>]*>([\s\S]*?)<\/a\s*>/gi, (_match, double, single, label) => {
42436
- const url = (double ?? single ?? "").trim();
42459
+ text = text.replace(/<a\b[^>]*?\shref\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+))[^>]*>([\s\S]*?)<\/a\s*>/gi, (_match, double, single, bare, label) => {
42460
+ const url = (double ?? single ?? bare ?? "").trim();
42437
42461
  const shown = removeAll(label, /<[^>]*>/g, "").trim();
42438
42462
  if (!/^(https?:|mailto:)/i.test(url)) return label;
42439
42463
  if (shown === url || `mailto:${shown}` === url) return label;
@@ -42453,7 +42477,7 @@ function buildEmailCompact(detail) {
42453
42477
  const text = detail.body_text?.trim() ? detail.body_text : null;
42454
42478
  const html = text === null && detail.body_html?.trim() ? detail.body_html : null;
42455
42479
  const source = text !== null ? "text" : html !== null ? "html" : "none";
42456
- const stripped = stripQuotedHistory(text ?? (html !== null ? htmlToText(html) : ""));
42480
+ const stripped = stripQuotedHistory(text ?? (html !== null ? htmlToText(html) : ""), detail.subject);
42457
42481
  return {
42458
42482
  id: detail.id,
42459
42483
  thread_id: detail.thread_id ?? null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primcli",
3
- "version": "1.62.0",
3
+ "version": "1.62.1",
4
4
  "description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
5
5
  "type": "module",
6
6
  "sideEffects": false,