mirror of
https://github.com/iOfficeAI/OfficeCLI
synced 2026-04-21 13:37:23 +00:00
refactor: fold 'check' command into 'view <file> issues'
Text-overflow scanning now emits as DocumentIssue (Format+Warning, Id prefix 'O') from ExcelHandler/PowerPointHandler ViewAsIssues, reusing the existing CheckAllCellOverflow and CheckTextOverflow logic. The standalone 'officecli check' command is removed — users migrate to 'officecli view <file> issues' (optionally '--type format'). Underlying CheckShapeTextOverflow/CheckCellOverflow/CheckAllCellOverflow handler APIs are retained; they still back the inline overflow warning emitted on add/set through the resident server.
This commit is contained in:
parent
f6e28edcd8
commit
b18e52687a
5 changed files with 35 additions and 87 deletions
2
SKILL.md
2
SKILL.md
|
|
@ -100,7 +100,7 @@ officecli view <file> <mode> # outline | stats | issues | text | annota
|
|||
officecli get <file> <path> --depth N # Get a node and its children [--json]
|
||||
officecli query <file> <selector> # CSS-like query
|
||||
officecli validate <file> # Validate against OpenXML schema
|
||||
officecli check <file> # Scan .pptx/.xlsx for text-overflow layout issues
|
||||
officecli view <file> issues # Enumerate issues (text overflow, missing alt, formula errors, ...)
|
||||
```
|
||||
|
||||
### view modes
|
||||
|
|
|
|||
|
|
@ -54,86 +54,4 @@ static partial class CommandBuilder
|
|||
|
||||
return validateCommand;
|
||||
}
|
||||
|
||||
private static Command BuildCheckCommand(Option<bool> jsonOption)
|
||||
{
|
||||
var checkFileArg = new Argument<FileInfo>("file") { Description = "Office document path (.pptx, .xlsx)" };
|
||||
var checkCommand = new Command("check", "Scan document for layout issues (text overflow, etc.)");
|
||||
checkCommand.Add(checkFileArg);
|
||||
checkCommand.Add(jsonOption);
|
||||
checkCommand.SetAction(result => { var json = result.GetValue(jsonOption); return SafeRun(() =>
|
||||
{
|
||||
var file = result.GetValue(checkFileArg)!;
|
||||
var ext = file.Extension.ToLowerInvariant();
|
||||
if (ext != ".pptx" && ext != ".xlsx")
|
||||
throw new OfficeCli.Core.CliException("The 'check' command currently supports .pptx and .xlsx files only.");
|
||||
|
||||
using var handler = DocumentHandlerFactory.Open(file.FullName, editable: false);
|
||||
var issues = new List<(string Path, string Message)>();
|
||||
|
||||
if (ext == ".pptx")
|
||||
{
|
||||
var pptHandler = handler as OfficeCli.Handlers.PowerPointHandler
|
||||
?? throw new OfficeCli.Core.CliException("Failed to open file as PowerPoint document.");
|
||||
var root = pptHandler.Get("/");
|
||||
int slideCount = root?.Children?.Count ?? 0;
|
||||
for (int s = 1; s <= slideCount; s++)
|
||||
{
|
||||
var slideNode = pptHandler.Get($"/slide[{s}]");
|
||||
int shapeCount = slideNode?.Children?.Count ?? 0;
|
||||
for (int sh = 1; sh <= shapeCount; sh++)
|
||||
{
|
||||
var shapePath = $"/slide[{s}]/shape[{sh}]";
|
||||
var warning = pptHandler.CheckShapeTextOverflow(shapePath);
|
||||
if (warning != null)
|
||||
issues.Add((shapePath, warning));
|
||||
}
|
||||
}
|
||||
}
|
||||
else // .xlsx
|
||||
{
|
||||
var xlHandler = handler as OfficeCli.Handlers.ExcelHandler
|
||||
?? throw new OfficeCli.Core.CliException("Failed to open file as Excel document.");
|
||||
issues.AddRange(xlHandler.CheckAllCellOverflow());
|
||||
}
|
||||
|
||||
if (json)
|
||||
{
|
||||
var arr = new System.Text.Json.Nodes.JsonArray();
|
||||
foreach (var (path, msg) in issues)
|
||||
{
|
||||
arr.Add((System.Text.Json.Nodes.JsonNode)new System.Text.Json.Nodes.JsonObject
|
||||
{
|
||||
["path"] = path,
|
||||
["issue"] = msg
|
||||
});
|
||||
}
|
||||
var envelope = new System.Text.Json.Nodes.JsonObject
|
||||
{
|
||||
["success"] = true,
|
||||
["file"] = file.FullName,
|
||||
["issueCount"] = issues.Count,
|
||||
["issues"] = arr
|
||||
};
|
||||
Console.WriteLine(envelope.ToJsonString(OutputFormatter.PublicJsonOptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Checking layout: {file.FullName}");
|
||||
if (issues.Count == 0)
|
||||
{
|
||||
Console.WriteLine("No layout issues found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var (path, msg) in issues)
|
||||
Console.WriteLine($" {path}: {msg}");
|
||||
Console.WriteLine($"Found {issues.Count} layout issue(s).");
|
||||
}
|
||||
}
|
||||
return issues.Count > 0 ? 2 : 0;
|
||||
}, json); });
|
||||
|
||||
return checkCommand;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ static partial class CommandBuilder
|
|||
rootCommand.Add(BuildRawSetCommand(jsonOption));
|
||||
rootCommand.Add(BuildAddPartCommand(jsonOption));
|
||||
rootCommand.Add(BuildValidateCommand(jsonOption));
|
||||
rootCommand.Add(BuildCheckCommand(jsonOption));
|
||||
rootCommand.Add(BuildBatchCommand(jsonOption));
|
||||
rootCommand.Add(BuildImportCommand(jsonOption));
|
||||
rootCommand.Add(BuildCreateCommand(jsonOption));
|
||||
|
|
|
|||
|
|
@ -464,6 +464,21 @@ public partial class ExcelHandler
|
|||
}
|
||||
}
|
||||
|
||||
// CONSISTENCY(text-overflow-check): merged in from former `check` command.
|
||||
// Emits wrapText-cells whose visible row-height budget can't fit the wrapped text.
|
||||
foreach (var (path, msg) in CheckAllCellOverflow())
|
||||
{
|
||||
if (limit.HasValue && issues.Count >= limit.Value) break;
|
||||
issues.Add(new DocumentIssue
|
||||
{
|
||||
Id = $"O{++issueNum}",
|
||||
Type = IssueType.Format,
|
||||
Severity = IssueSeverity.Warning,
|
||||
Path = path,
|
||||
Message = msg
|
||||
});
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -457,8 +457,25 @@ public partial class PowerPointHandler
|
|||
int shapeIdx = 0;
|
||||
foreach (var shape in shapes)
|
||||
{
|
||||
shapeIdx++;
|
||||
var shapePath = $"/slide[{slideNum}]/{BuildElementPathSegment("shape", shape, shapeIdx)}";
|
||||
|
||||
// CONSISTENCY(text-overflow-check): merged in from former `check` command.
|
||||
var overflow = CheckTextOverflow(shape);
|
||||
if (overflow != null)
|
||||
{
|
||||
issues.Add(new DocumentIssue
|
||||
{
|
||||
Id = $"O{++issueNum}",
|
||||
Type = IssueType.Format,
|
||||
Severity = IssueSeverity.Warning,
|
||||
Path = shapePath,
|
||||
Message = overflow
|
||||
});
|
||||
}
|
||||
|
||||
var runs = shape.Descendants<Drawing.Run>().ToList();
|
||||
if (runs.Count <= 1) { shapeIdx++; continue; }
|
||||
if (runs.Count <= 1) continue;
|
||||
|
||||
var fonts = runs.Select(r =>
|
||||
r.RunProperties?.GetFirstChild<Drawing.LatinFont>()?.Typeface
|
||||
|
|
@ -472,11 +489,10 @@ public partial class PowerPointHandler
|
|||
Id = $"F{++issueNum}",
|
||||
Type = IssueType.Format,
|
||||
Severity = IssueSeverity.Info,
|
||||
Path = $"/slide[{slideNum}]/{BuildElementPathSegment("shape", shape, shapeIdx + 1)}",
|
||||
Path = shapePath,
|
||||
Message = $"Inconsistent fonts in text box: {string.Join(", ", fonts)}"
|
||||
});
|
||||
}
|
||||
shapeIdx++;
|
||||
}
|
||||
|
||||
foreach (var pic in shapeTree.Elements<Picture>())
|
||||
|
|
|
|||
Loading…
Reference in a new issue