refactor(oc-path): share JSONL line selection

This commit is contained in:
Vincent Koc
2026-06-22 18:47:24 +08:00
parent f13a10c798
commit bdf75474b9
3 changed files with 38 additions and 71 deletions

View File

@@ -11,6 +11,7 @@ import { isMap, isScalar, isSeq, type Node, type Pair } from "yaml";
import type { MdAst } from "./ast.js";
import type { JsoncValue } from "./jsonc/ast.js";
import type { JsonlAst, JsonlLine } from "./jsonl/ast.js";
import { pickJsonlLine } from "./jsonl/line.js";
import type { OcPath } from "./oc-path.js";
import {
MAX_TRAVERSAL_DEPTH,
@@ -364,7 +365,7 @@ const jsonlOps: WalkOps<JsonlAst> = {
}
},
lookup(ast, key) {
const line = pickLine(ast, key);
const line = pickJsonlLine(ast, key);
if (line === null) {
return null;
}
@@ -440,37 +441,6 @@ function topLevelLeafText(value: JsoncValue, key: string): string | null {
return null;
}
function pickLine(ast: JsonlAst, addr: string): JsonlLine | null {
if (addr === "$first") {
for (const l of ast.lines) {
if (l.kind === "value") {
return l;
}
}
return null;
}
if (addr === "$last") {
for (let i = ast.lines.length - 1; i >= 0; i--) {
const l = ast.lines[i];
if (l !== undefined && l.kind === "value") {
return l;
}
}
return null;
}
const m = /^L(\d+)$/.exec(addr);
if (m === null || m[1] === undefined) {
return null;
}
const target = Number(m[1]);
for (const l of ast.lines) {
if (l.line === target) {
return l;
}
}
return null;
}
// ---------- YAML walker ----------------------------------------------------
function walkYaml(

View File

@@ -0,0 +1,33 @@
import { POS_FIRST, POS_LAST } from "../oc-path.js";
import type { JsonlAst, JsonlLine } from "./ast.js";
export function pickJsonlLine(ast: JsonlAst, addr: string): JsonlLine | null {
if (addr === POS_FIRST) {
for (const line of ast.lines) {
if (line.kind === "value") {
return line;
}
}
return null;
}
if (addr === POS_LAST) {
for (let index = ast.lines.length - 1; index >= 0; index -= 1) {
const line = ast.lines[index];
if (line !== undefined && line.kind === "value") {
return line;
}
}
return null;
}
const match = /^L(\d+)$/.exec(addr);
if (match === null || match[1] === undefined) {
return null;
}
const target = Number(match[1]);
for (const line of ast.lines) {
if (line.line === target) {
return line;
}
}
return null;
}

View File

@@ -18,14 +18,9 @@
import type { JsoncEntry, JsoncValue } from "../jsonc/ast.js";
import { resolveJsoncValueOcPath } from "../jsonc/resolve-value.js";
import type { OcPath } from "../oc-path.js";
import {
POS_FIRST,
POS_LAST,
isQuotedSeg,
splitRespectingBrackets,
unquoteSeg,
} from "../oc-path.js";
import { isQuotedSeg, splitRespectingBrackets, unquoteSeg } from "../oc-path.js";
import type { JsonlAst, JsonlLine } from "./ast.js";
import { pickJsonlLine } from "./line.js";
export type JsonlOcPathMatch =
| { readonly kind: "root"; readonly node: JsonlAst }
@@ -50,7 +45,7 @@ export function resolveJsonlOcPath(ast: JsonlAst, path: OcPath): JsonlOcPathMatc
return { kind: "root", node: ast };
}
const lineEntry = pickLine(ast, head);
const lineEntry = pickJsonlLine(ast, head);
if (lineEntry === null) {
return null;
}
@@ -90,34 +85,3 @@ export function resolveJsonlOcPath(ast: JsonlAst, path: OcPath): JsonlOcPathMatc
}
return { kind: "value", node: match.node, line: lineEntry.line, path: match.path };
}
function pickLine(ast: JsonlAst, addr: string): JsonlLine | null {
if (addr === POS_FIRST) {
for (const l of ast.lines) {
if (l.kind === "value") {
return l;
}
}
return null;
}
if (addr === POS_LAST) {
for (let i = ast.lines.length - 1; i >= 0; i--) {
const l = ast.lines[i];
if (l !== undefined && l.kind === "value") {
return l;
}
}
return null;
}
const m = /^L(\d+)$/.exec(addr);
if (m === null || m[1] === undefined) {
return null;
}
const target = Number(m[1]);
for (const l of ast.lines) {
if (l.line === target) {
return l;
}
}
return null;
}