stego-cli 0.3.0 → 0.3.2

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.
@@ -1,7 +1,8 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { CommentsCommandError } from "./errors.js";
4
- const COMMENT_HEADING_REGEX = /^###\s+(CMT-(\d{4,}))\s*$/;
4
+ const COMMENT_DELIMITER_REGEX = /^<!--\s*comment:\s*(CMT-(\d{4,}))\s*-->\s*$/i;
5
+ const LEGACY_COMMENT_HEADING_REGEX = /^###\s+(CMT-(\d{4,}))\s*$/i;
5
6
  const START_SENTINEL = "<!-- stego-comments:start -->";
6
7
  const END_SENTINEL = "<!-- stego-comments:end -->";
7
8
  /** Adds one stego comment entry to a manuscript and writes the updated file. */
@@ -18,7 +19,7 @@ export function addCommentToManuscript(request) {
18
19
  if (!sentinelState.hasSentinels && !hasYamlFrontmatter) {
19
20
  throw new CommentsCommandError("NOT_STEGO_MANUSCRIPT", 3, "File is not recognized as a Stego manuscript (missing frontmatter and comments sentinels).");
20
21
  }
21
- const commentId = getNextCommentId(lines);
22
+ const commentId = getNextCommentId(lines, sentinelState);
22
23
  const createdAt = new Date().toISOString();
23
24
  const meta = buildMetaPayload(request.range, request.sourceMeta);
24
25
  const meta64 = Buffer.from(JSON.stringify(meta), "utf8").toString("base64url");
@@ -75,7 +76,7 @@ function buildCommentEntryLines(commentId, timestamp, author, message, meta64) {
75
76
  .split("\n")
76
77
  .map((line) => line.trimEnd());
77
78
  return [
78
- `### ${commentId}`,
79
+ `<!-- comment: ${commentId} -->`,
79
80
  `<!-- meta64: ${meta64} -->`,
80
81
  `> _${timestamp} | ${safeAuthor}_`,
81
82
  ">",
@@ -142,11 +143,15 @@ function findTrimmedLineIndexes(lines, target) {
142
143
  }
143
144
  return indexes;
144
145
  }
145
- function getNextCommentId(lines) {
146
+ function getNextCommentId(lines, sentinelState) {
147
+ const candidateLines = sentinelState.hasSentinels
148
+ ? lines.slice(sentinelState.startIndex + 1, sentinelState.endIndex)
149
+ : lines;
146
150
  let maxId = 0;
147
- for (const line of lines) {
148
- const match = line.trim().match(COMMENT_HEADING_REGEX);
149
- if (!match) {
151
+ for (const line of candidateLines) {
152
+ const trimmed = line.trim();
153
+ const match = trimmed.match(COMMENT_DELIMITER_REGEX) ?? trimmed.match(LEGACY_COMMENT_HEADING_REGEX);
154
+ if (!match || !match[2]) {
150
155
  continue;
151
156
  }
152
157
  const numeric = Number.parseInt(match[2], 10);
package/dist/stego-cli.js CHANGED
@@ -430,7 +430,7 @@ function parseArgs(argv) {
430
430
  if (token.startsWith("--")) {
431
431
  const key = token.slice(2);
432
432
  const next = rest[i + 1];
433
- if (!next || next.startsWith("-")) {
433
+ if (!next || !canBeOptionValue(next)) {
434
434
  options[key] = true;
435
435
  continue;
436
436
  }
@@ -441,7 +441,7 @@ function parseArgs(argv) {
441
441
  if (token.startsWith("-") && token.length > 1) {
442
442
  const key = token.slice(1);
443
443
  const next = rest[i + 1];
444
- if (!next || next.startsWith("-")) {
444
+ if (!next || !canBeOptionValue(next)) {
445
445
  options[key] = true;
446
446
  continue;
447
447
  }
@@ -456,6 +456,12 @@ function parseArgs(argv) {
456
456
  }
457
457
  return { command, options };
458
458
  }
459
+ function canBeOptionValue(token) {
460
+ if (token === "-") {
461
+ return true;
462
+ }
463
+ return !token.startsWith("-");
464
+ }
459
465
  function resolveWorkspaceContext(rootOption) {
460
466
  if (rootOption) {
461
467
  const explicitRoot = path.resolve(process.cwd(), rootOption);
@@ -1419,19 +1425,18 @@ function parseStegoCommentThreads(lines, relativePath, baseLine, issues) {
1419
1425
  index += 1;
1420
1426
  continue;
1421
1427
  }
1422
- const headingMatch = trimmed.match(/^###\s+(CMT-\d{4})\s*$/);
1423
- if (!headingMatch) {
1424
- issues.push(makeIssue("error", "comments", "Invalid comments appendix line. Expected heading like '### CMT-0001'.", relativePath, baseLine + index));
1428
+ const id = parseCommentThreadDelimiter(trimmed);
1429
+ if (!id) {
1430
+ issues.push(makeIssue("error", "comments", "Invalid comments appendix line. Expected comment delimiter '<!-- comment: CMT-0001 -->'.", relativePath, baseLine + index));
1425
1431
  index += 1;
1426
1432
  continue;
1427
1433
  }
1428
- const id = headingMatch[1];
1429
1434
  index += 1;
1430
1435
  const rowLines = [];
1431
1436
  const rowLineNumbers = [];
1432
1437
  while (index < lines.length) {
1433
1438
  const nextTrimmed = lines[index].trim();
1434
- if (/^###\s+CMT-\d{4}\s*$/.test(nextTrimmed)) {
1439
+ if (parseCommentThreadDelimiter(nextTrimmed)) {
1435
1440
  break;
1436
1441
  }
1437
1442
  rowLines.push(lines[index]);
@@ -1543,6 +1548,17 @@ function parseStegoCommentThreads(lines, relativePath, baseLine, issues) {
1543
1548
  }
1544
1549
  return comments;
1545
1550
  }
1551
+ function parseCommentThreadDelimiter(line) {
1552
+ const markerMatch = line.match(/^<!--\s*comment:\s*(CMT-\d{4,})\s*-->\s*$/i);
1553
+ if (markerMatch?.[1]) {
1554
+ return markerMatch[1].toUpperCase();
1555
+ }
1556
+ const legacyHeadingMatch = line.match(/^###\s+(CMT-\d{4,})\s*$/i);
1557
+ if (legacyHeadingMatch?.[1]) {
1558
+ return legacyHeadingMatch[1].toUpperCase();
1559
+ }
1560
+ return undefined;
1561
+ }
1546
1562
  function decodeCommentMeta64(encoded, commentId, relativePath, lineNumber, issues) {
1547
1563
  let rawJson = "";
1548
1564
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stego-cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "description": "Installable CLI for the Stego writing monorepo workflow.",
6
6
  "license": "Apache-2.0",