@copylee/dsh-office 0.3.1 → 0.3.3

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.
@@ -1018,11 +1018,40 @@ static class Program
1018
1018
  return made;
1019
1019
  }
1020
1020
 
1021
+ /// Equations on a line of their own built during the current operation (their ranges: these keep pointing at the
1022
+ /// equation while the document grows). They are set off from the text once the operation is done: a paragraph
1023
+ /// inserted after one takes over its look, and must not take over this.
1024
+ static readonly List<object> Displays = new List<object>();
1025
+
1026
+ /// As typeset papers do: some space above and below the equation, and a line that grows with the formula
1027
+ /// (an exact line height would cut a tall one off).
1028
+ static void SetOff()
1029
+ {
1030
+ foreach (dynamic equation in Displays)
1031
+ {
1032
+ try
1033
+ {
1034
+ dynamic paragraph = equation.Paragraphs[1];
1035
+ dynamic range = paragraph.Range;
1036
+ dynamic math = range.OMaths[1].Range;
1037
+ if ((int)range.OMaths.Count != 1) continue;
1038
+ if ((int)range.End - (int)range.Start > (int)math.End - (int)math.Start + 3) continue;
1039
+ dynamic format = paragraph.Format;
1040
+ if ((float)format.SpaceBefore < 6f) format.SpaceBefore = 6f;
1041
+ if ((float)format.SpaceAfter < 6f) format.SpaceAfter = 6f;
1042
+ if ((int)format.LineSpacingRule == 4) format.LineSpacingRule = 3;
1043
+ }
1044
+ catch (Exception) { }
1045
+ }
1046
+ Displays.Clear();
1047
+ }
1048
+
1021
1049
  /// Formulas that could not be turned into equations during the current operation (they stay as text).
1022
1050
  static int MathFailed;
1023
1051
 
1024
1052
  static string MathNote()
1025
1053
  {
1054
+ SetOff();
1026
1055
  if (MathFailed == 0) return "";
1027
1056
  string note = " — NOTE " + MathFailed + " formula(s) could not be built and were left as text: check them with office_render and rewrite them more simply";
1028
1057
  MathFailed = 0;
@@ -1050,6 +1079,7 @@ static class Program
1050
1079
  dynamic math = doc.OMaths.Add(spot);
1051
1080
  math.OMaths[1].BuildUp();
1052
1081
  if (display) { try { math.OMaths[1].Type = 0; math.OMaths[1].Justification = 1; } catch (COMException) { } }
1082
+ if (display) { try { Displays.Add(math.OMaths[1].Range); } catch (Exception) { } }
1053
1083
  return true;
1054
1084
  }
1055
1085
  catch (COMException) { return false; }
@@ -1228,12 +1258,28 @@ static class Program
1228
1258
  if (op.Has("firstLineIndent")) range.ParagraphFormat.FirstLineIndent = (float)op.Num("firstLineIndent", 0);
1229
1259
  if (op.Has("spaceBefore")) range.ParagraphFormat.SpaceBefore = (float)op.Num("spaceBefore", 0);
1230
1260
  if (op.Has("spaceAfter")) range.ParagraphFormat.SpaceAfter = (float)op.Num("spaceAfter", 0);
1231
- if (op.Has("lineSpacing")) { range.ParagraphFormat.LineSpacingRule = 5; range.ParagraphFormat.LineSpacing = (float)(op.Num("lineSpacing", 1) * 12); }
1261
+ if (op.Has("lineSpacing")) LineSpacing(range.ParagraphFormat, op.Raw("lineSpacing"));
1232
1262
  if (op.Has("indentChars")) { range.ParagraphFormat.FirstLineIndent = 0; range.ParagraphFormat.CharacterUnitFirstLineIndent = (float)op.Num("indentChars", 2); }
1233
1263
  if (op.Has("superscript")) range.Font.Superscript = op.Flag("superscript", false) ? 1 : 0;
1234
1264
  if (op.Has("subscript")) range.Font.Subscript = op.Flag("subscript", false) ? 1 : 0;
1235
1265
  }
1236
1266
 
1267
+ /// Line spacing as people state it: a plain number is a multiple of single spacing (1.5), a length is an exact
1268
+ /// height ("20pt", "固定值20磅"), and "at least 20pt" / "最小值20磅" a minimum. A plain number too large to be a
1269
+ /// multiple (5 and up) is taken as points.
1270
+ static void LineSpacing(dynamic format, object raw)
1271
+ {
1272
+ string text = Convert.ToString(raw, System.Globalization.CultureInfo.InvariantCulture).Trim();
1273
+ System.Text.RegularExpressions.Match number = System.Text.RegularExpressions.Regex.Match(text, @"\d+(\.\d+)?");
1274
+ if (!number.Success) throw new Fail("BAD_ARGS", "lineSpacing \"" + text + "\" is not understood: give a multiple (1.5), an exact height (\"20pt\") or a minimum (\"at least 20pt\").");
1275
+ float value = float.Parse(number.Value, System.Globalization.CultureInfo.InvariantCulture);
1276
+ string lower = text.ToLowerInvariant();
1277
+ bool least = lower.Contains("least") || lower.Contains("min") || text.Contains("最小");
1278
+ bool points = least || lower.Contains("pt") || lower.Contains("exact") || lower.Contains("fixed") || text.Contains("磅") || text.Contains("固定") || value >= 5;
1279
+ if (!points) { format.LineSpacingRule = 5; format.LineSpacing = value * 12; }
1280
+ else { format.LineSpacingRule = least ? 3 : 4; format.LineSpacing = value; }
1281
+ }
1282
+
1237
1283
  /// A new empty paragraph where an insert operation points: after / before paragraph "para", or at the start / end.
1238
1284
  static dynamic NewParagraph(dynamic doc, Bag op)
1239
1285
  {
@@ -1805,7 +1851,7 @@ static class Program
1805
1851
  if (op.Has("firstLineIndent")) { format.CharacterUnitFirstLineIndent = 0; format.FirstLineIndent = (float)op.Num("firstLineIndent", 0); }
1806
1852
  if (op.Has("spaceBefore")) format.SpaceBefore = (float)op.Num("spaceBefore", 0);
1807
1853
  if (op.Has("spaceAfter")) format.SpaceAfter = (float)op.Num("spaceAfter", 0);
1808
- if (op.Has("lineSpacing")) { format.LineSpacingRule = 5; format.LineSpacing = (float)(op.Num("lineSpacing", 1) * 12); }
1854
+ if (op.Has("lineSpacing")) LineSpacing(format, op.Raw("lineSpacing"));
1809
1855
  if (op.Has("pageBreakBefore")) format.PageBreakBefore = op.Flag("pageBreakBefore", false) ? -1 : 0;
1810
1856
  if (op.Has("numbering") && !op.On("numbering"))
1811
1857
  {
package/lib/index.js CHANGED
@@ -6122,13 +6122,13 @@ Formulas: write LaTeX between dollar signs in any text (paragraphs, table cells,
6122
6122
  - insert_paragraphs {items:[{text, style?}], para?, expect?, where?} — style: Normal, Title, Heading 1..6, List Bullet, List Number, Quote, or a style name the document has. Without style a paragraph is body text in the font, size and spacing of the text it is placed next to. A newline in text starts another paragraph. Items also take the format_text fields.
6123
6123
  - set_text {para, expect, text} — rewrite one paragraph, keeping its style. expect is required ("" for an empty paragraph).
6124
6124
  - replace_text {find, replace, all?} — find is literal text within one paragraph; replace may hold formulas and citations.
6125
- - format_text {para?, to?, find?, style?, font?, size?, bold?, italic?, underline?, superscript?, subscript?, color?, align?, indentChars?, firstLineIndent?, spaceBefore?, spaceAfter?, lineSpacing?} — para..to, or the first match of find.
6125
+ - format_text {para?, to?, find?, style?, font?, size?, bold?, italic?, underline?, superscript?, subscript?, color?, align?, indentChars?, firstLineIndent?, spaceBefore?, spaceAfter?, lineSpacing?} — para..to, or the first match of find. lineSpacing: a number is a multiple (1.5 = 1.5 倍行距), "20pt" an exact height (固定值 20 磅), "at least 20pt" a minimum (最小值).
6126
6126
  - delete_range {para, expect, to?} — expect is required; para..to in one operation removes a run of paragraphs (leftover hints, surplus blank lines). Paragraph numbers shift after every insert or delete; each result tells you the new numbers.
6127
6127
  - insert_table {data:[[cell,..],..], caption?, para?, where?, header?} — with para inside a cell, the table goes inside that cell. set_cell {table, row, col, text}
6128
6128
  - Captions: give caption (the title only, no "表 1") on insert_table / insert_image. It is set the standard way: numbered automatically ("表 1", "图 1"), centred, above a table and below a figure. Do not write captions as ordinary paragraphs.
6129
6129
  - insert_image {path, caption?, para?, where?, width?} — the picture is centred on a line of its own.
6130
6130
  - Citations: write \\cite{1}, \\cite{2,5} or \\cite{3-6} in the text where the source is used; they become superscript [1] that jump to the reference. List the sources with insert_references {items:["Author. Title[M]. ...", ..], para?, where?} (numbered [1], [2].. in order; put it under a "参考文献" heading). Do not type [1] by hand.
6131
- - style_format {style, font?, latinFont?, size?, bold?, italic?, color?, align?, indentChars?, spaceBefore?, spaceAfter?, lineSpacing?, pageBreakBefore?, numbering?: false} — change what a style looks like everywhere it is used (e.g. Heading 1 in 黑体 三号 without automatic numbers; Normal in 宋体 小四, 1.5 lines, 2-character first-line indent). Set the styles first, then write; this replaces fiddling with Word's style dialogs.
6131
+ - style_format {style, font?, latinFont?, size?, bold?, italic?, color?, align?, indentChars?, spaceBefore?, spaceAfter?, lineSpacing? (1.5 | "20pt" | "at least 20pt"), pageBreakBefore?, numbering?: false} — change what a style looks like everywhere it is used (e.g. Heading 1 in 黑体 三号 without automatic numbers; Normal in 宋体 小四, 1.5 lines, 2-character first-line indent). Set the styles first, then write; this replaces fiddling with Word's style dialogs.
6132
6132
  - page_setup {paper?: A4|A3|B5|Letter, orientation?, top?, bottom?, left?, right?} (margins in cm); page_numbers {align?, start?}; header {text}; page_break {para, expect} (that paragraph starts a new page); insert_toc {title?, levels?, para?, where?}; update_fields {}
6133
6133
 
6134
6134
  Excel ops. sheet = sheet name (default: the active sheet).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copylee/dsh-office",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "DeepSeek Harness Office 插件(Windows):AI 直接在你打开的 Word / Excel / PowerPoint 里改文档,改动实时出现在窗口中,你可以同时编辑;读结构、批量编辑、渲染成图核对、保存。",
5
5
  "type": "module",
6
6
  "author": "copylee",