mirror of
https://github.com/backnotprop/plannotator.git
synced 2026-09-14 14:17:26 +08:00
feat(plan,annotate): include source line numbers in exported feedback (#623)
Each annotation in exported plan/annotate feedback now carries source line numbers — single-line blocks show `(line N)`, multi-line blocks show `(lines N–M)`. Diff-context and global comments stay lineless. When the document was produced by Turndown/Jina (HTML file or URL), the export carries a caveat that line numbers refer to the converted markdown rather than the original source. Key implementation details: - extractFrontmatter() returns contentStartLine so block line numbers account for stripped YAML headers - blockEndLine() computes end lines per block type, with code blocks, directives, and alerts accounting for stripped wrapper lines - isConvertedSource() helper in url-to-markdown.ts centralizes the source-type check across all entry points - sourceConverted threaded from all CLIs through annotate servers to the /api/plan payload; isConverted added to /api/doc responses - Per-document conversion tracking in useLinkedDoc ensures the correct flag is used when viewing linked HTML docs Supersedes #621. For provenance purposes, this commit was AI assisted.
This commit is contained in:
@@ -25,7 +25,7 @@ import { resolveMarkdownFile, resolveUserPath, hasMarkdownFiles } from "@plannot
|
||||
import { FILE_BROWSER_EXCLUDED } from "@plannotator/shared/reference-common";
|
||||
import { htmlToMarkdown } from "@plannotator/shared/html-to-markdown";
|
||||
import { parseAnnotateArgs } from "@plannotator/shared/annotate-args";
|
||||
import { urlToMarkdown } from "@plannotator/shared/url-to-markdown";
|
||||
import { urlToMarkdown, isConvertedSource } from "@plannotator/shared/url-to-markdown";
|
||||
import { statSync } from "fs";
|
||||
import path from "path";
|
||||
|
||||
@@ -170,6 +170,7 @@ export async function handleAnnotateCommand(
|
||||
let folderPath: string | undefined;
|
||||
let annotateMode: "annotate" | "annotate-folder" = "annotate";
|
||||
let sourceInfo: string | undefined;
|
||||
let sourceConverted = false;
|
||||
|
||||
// --- URL annotation ---
|
||||
const isUrl = /^https?:\/\//i.test(filePath);
|
||||
@@ -180,6 +181,7 @@ export async function handleAnnotateCommand(
|
||||
try {
|
||||
const result = await urlToMarkdown(filePath, { useJina });
|
||||
markdown = result.markdown;
|
||||
sourceConverted = isConvertedSource(result.source);
|
||||
} catch (err) {
|
||||
client.app.log({ level: "error", message: `Failed to fetch URL: ${err instanceof Error ? err.message : String(err)}` });
|
||||
return;
|
||||
@@ -223,6 +225,7 @@ export async function handleAnnotateCommand(
|
||||
markdown = htmlToMarkdown(html);
|
||||
absolutePath = resolvedArg;
|
||||
sourceInfo = path.basename(resolvedArg);
|
||||
sourceConverted = true;
|
||||
client.app.log({ level: "info", message: `Converted: ${absolutePath}` });
|
||||
} else {
|
||||
// Markdown file annotation
|
||||
@@ -258,6 +261,7 @@ export async function handleAnnotateCommand(
|
||||
mode: annotateMode,
|
||||
folderPath,
|
||||
sourceInfo,
|
||||
sourceConverted,
|
||||
sharingEnabled: await getSharingEnabled(),
|
||||
shareBaseUrl: getShareBaseUrl(),
|
||||
pasteApiUrl: getPasteApiUrl(),
|
||||
|
||||
Reference in New Issue
Block a user