openzca 0.1.32 → 0.1.34

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/cli.js +128 -13
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -706,30 +706,108 @@ function asThreadType(groupFlag) {
706
706
  return groupFlag ? ThreadType.Group : ThreadType.User;
707
707
  }
708
708
  function parseTextStyles(input) {
709
- const styles = [];
709
+ const allStyles = [];
710
+ const escapeMap = [];
711
+ const escaped = input.replace(/\\([*_~#\\{}>+\-])/g, (_match, ch) => {
712
+ const idx = escapeMap.length;
713
+ escapeMap.push(ch);
714
+ return `${idx}`;
715
+ });
716
+ const lines = escaped.split("\n");
717
+ const lineStyles = [];
718
+ const processedLines = [];
719
+ for (let i = 0; i < lines.length; i++) {
720
+ let line = lines[i];
721
+ const headingMatch = line.match(/^(#{1,6})\s(.*)$/);
722
+ if (headingMatch) {
723
+ const level = headingMatch[1].length;
724
+ lineStyles.push({ lineIndex: i, style: TextStyle.Bold });
725
+ if (level === 1) lineStyles.push({ lineIndex: i, style: TextStyle.Big });
726
+ else if (level >= 3) lineStyles.push({ lineIndex: i, style: TextStyle.Small });
727
+ processedLines.push(headingMatch[2]);
728
+ continue;
729
+ }
730
+ const bqMatch = line.match(/^(>+)\s?(.*)$/);
731
+ if (bqMatch) {
732
+ lineStyles.push({ lineIndex: i, style: TextStyle.Indent, indentSize: bqMatch[1].length });
733
+ line = bqMatch[2];
734
+ }
735
+ const indentContentMatch = line.match(/^(\s+)(.*)$/);
736
+ let indentLevel = 0;
737
+ let content = line;
738
+ if (indentContentMatch) {
739
+ indentLevel = Math.max(1, Math.floor(indentContentMatch[1].length / 2));
740
+ content = indentContentMatch[2];
741
+ }
742
+ const olMatch = content.match(/^(\d+)\.\s(.*)$/);
743
+ if (olMatch) {
744
+ if (indentLevel > 0) {
745
+ lineStyles.push({ lineIndex: i, style: TextStyle.Indent, indentSize: indentLevel });
746
+ }
747
+ lineStyles.push({ lineIndex: i, style: TextStyle.OrderedList });
748
+ processedLines.push(olMatch[2]);
749
+ continue;
750
+ }
751
+ const ulMatch = content.match(/^[-*+]\s(.*)$/);
752
+ if (ulMatch) {
753
+ if (indentLevel > 0) {
754
+ lineStyles.push({ lineIndex: i, style: TextStyle.Indent, indentSize: indentLevel });
755
+ }
756
+ lineStyles.push({ lineIndex: i, style: TextStyle.UnorderedList });
757
+ processedLines.push(ulMatch[1]);
758
+ continue;
759
+ }
760
+ if (indentLevel > 0) {
761
+ lineStyles.push({ lineIndex: i, style: TextStyle.Indent, indentSize: indentLevel });
762
+ processedLines.push(content);
763
+ continue;
764
+ }
765
+ processedLines.push(line);
766
+ }
767
+ const inlineInput = processedLines.join("\n");
768
+ const colorMap = {
769
+ red: TextStyle.Red,
770
+ orange: TextStyle.Orange,
771
+ yellow: TextStyle.Yellow,
772
+ green: TextStyle.Green,
773
+ small: TextStyle.Small,
774
+ big: TextStyle.Big,
775
+ underline: TextStyle.Underline
776
+ };
777
+ const tagNames = Object.keys(colorMap).join("|");
710
778
  const markers = [
711
- { pattern: /\*\*\*(.+?)\*\*\*/g, style: TextStyle.Bold },
779
+ // Tags first so inner markdown markers are preserved for subsequent passes
780
+ { pattern: new RegExp(`\\{(${tagNames})\\}(.+?)\\{/\\1\\}`, "g"), style: null },
781
+ // *** = bold + italic
782
+ { pattern: /\*\*\*(.+?)\*\*\*/g, style: TextStyle.Bold, extraStyles: [TextStyle.Italic] },
783
+ // ** and __ = bold (standard markdown)
712
784
  { pattern: /\*\*(.+?)\*\*/g, style: TextStyle.Bold },
785
+ { pattern: /__(.+?)__/g, style: TextStyle.Bold },
786
+ // * and _ = italic (standard markdown)
713
787
  { pattern: /\*(.+?)\*/g, style: TextStyle.Italic },
714
- { pattern: /__(.+?)__/g, style: TextStyle.Underline },
788
+ { pattern: /_(.+?)_/g, style: TextStyle.Italic },
789
+ // ~~ = strikethrough
715
790
  { pattern: /~~(.+?)~~/g, style: TextStyle.StrikeThrough }
716
791
  ];
717
- let segments = [{ text: input, styles: [] }];
718
- for (const { pattern, style } of markers) {
792
+ let segments = [{ text: inlineInput, styles: [] }];
793
+ for (const marker of markers) {
719
794
  const next = [];
720
795
  for (const seg of segments) {
721
796
  let lastIndex = 0;
722
- const regex = new RegExp(pattern.source, pattern.flags);
797
+ const regex = new RegExp(marker.pattern.source, marker.pattern.flags);
723
798
  let m;
724
799
  while ((m = regex.exec(seg.text)) !== null) {
725
800
  if (m.index > lastIndex) {
726
801
  next.push({ text: seg.text.slice(lastIndex, m.index), styles: [...seg.styles] });
727
802
  }
728
- const combined = [...seg.styles, style];
729
- if (pattern.source.startsWith("\\*\\*\\*")) {
730
- combined.push(TextStyle.Italic);
803
+ const isTagPattern = marker.style === null;
804
+ const innerText = isTagPattern ? m[2] : m[1];
805
+ const resolvedStyle = isTagPattern ? colorMap[m[1]] : marker.style;
806
+ const combined = [...seg.styles, resolvedStyle];
807
+ if (marker.extraStyles) {
808
+ combined.push(...marker.extraStyles);
731
809
  }
732
- next.push({ text: m[1], styles: combined });
810
+ next.push({ text: innerText, styles: combined });
733
811
  lastIndex = regex.lastIndex;
734
812
  }
735
813
  if (lastIndex < seg.text.length) {
@@ -745,10 +823,47 @@ function parseTextStyles(input) {
745
823
  const start = plainText.length;
746
824
  plainText += seg.text;
747
825
  for (const st of seg.styles) {
748
- styles.push({ start, len: seg.text.length, st });
826
+ allStyles.push({ start, len: seg.text.length, st });
827
+ }
828
+ }
829
+ if (escapeMap.length > 0) {
830
+ const escRegex = /\x01(\d+)\x02/g;
831
+ const shifts = [];
832
+ let cumDelta = 0;
833
+ for (const m of plainText.matchAll(escRegex)) {
834
+ const idx = parseInt(m[1], 10);
835
+ cumDelta += m[0].length - escapeMap[idx].length;
836
+ shifts.push({ pos: m.index + m[0].length, delta: cumDelta });
837
+ }
838
+ for (const s of allStyles) {
839
+ let startDelta = 0;
840
+ let endDelta = 0;
841
+ const end = s.start + s.len;
842
+ for (const sh of shifts) {
843
+ if (sh.pos <= s.start) startDelta = sh.delta;
844
+ if (sh.pos <= end) endDelta = sh.delta;
845
+ }
846
+ s.start -= startDelta;
847
+ s.len -= endDelta - startDelta;
848
+ }
849
+ plainText = plainText.replace(escRegex, (_m, idxStr) => escapeMap[parseInt(idxStr, 10)]);
850
+ }
851
+ const finalLines = plainText.split("\n");
852
+ let offset = 0;
853
+ for (let i = 0; i < finalLines.length; i++) {
854
+ const lineLen = finalLines[i].length;
855
+ for (const ls of lineStyles) {
856
+ if (ls.lineIndex === i && lineLen > 0) {
857
+ if (ls.style === TextStyle.Indent) {
858
+ allStyles.push({ start: offset, len: lineLen, st: TextStyle.Indent, indentSize: ls.indentSize });
859
+ } else {
860
+ allStyles.push({ start: offset, len: lineLen, st: ls.style });
861
+ }
862
+ }
749
863
  }
864
+ offset += lineLen + 1;
750
865
  }
751
- return { text: plainText, styles };
866
+ return { text: plainText, styles: allStyles };
752
867
  }
753
868
  function parseBooleanFromEnv(name, fallback) {
754
869
  const raw = process.env[name]?.trim();
@@ -2933,7 +3048,7 @@ auth.command("cache-clear").description("Clear local cache").action(
2933
3048
  })
2934
3049
  );
2935
3050
  var msg = program.command("msg").description("Messaging commands");
2936
- msg.command("send <threadId> <message>").option("-g, --group", "Send to group").option("--raw", "Send raw text without parsing formatting markers").description("Send text message (supports **bold** *italic* __underline__ ~~strikethrough~~)").action(
3051
+ msg.command("send <threadId> <message>").option("-g, --group", "Send to group").option("--raw", "Send raw text without parsing formatting markers").description("Send text message with formatting (**bold** *italic* __underline__ ~~strike~~ {red}color{/red} {big}size{/big} lists indents)").action(
2937
3052
  wrapAction(async (threadId, message, opts, command) => {
2938
3053
  const { api } = await requireApi(command);
2939
3054
  if (opts.raw) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzca",
3
- "version": "0.1.32",
3
+ "version": "0.1.34",
4
4
  "description": "Open-source zca-compatible CLI to integrate Zalo with OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {