refactor(mcp): drop dead tree-build helpers from element-tool-helpers
Post-42/42 delegate refactor: pen-mcp handlers all import assignIdsRecursively + buildScrollWrapper + CJK helpers from @zseven-w/pen-core/element-builders. The local copies in element-tool-helpers.ts had zero callers and could drift from the canonical pen-core versions. Re-export from pen-core so any external caller that was still reaching in by path keeps compiling without churn. File shrinks from ~276 to ~189 lines. Kept: ensureParentExists, insertElementTree (with its simulateDslParentResolve helper, rollback + post-insert verification) — these are pen-mcp-specific server I/O / integrity logic that have no place in pen-core.
This commit is contained in:
parent
d10ff757c3
commit
05cfa53795
|
|
@ -7,38 +7,20 @@ import {
|
|||
resolveDocPath,
|
||||
} from '../document-manager';
|
||||
import { findNodeInTree, findParentInTree, getDocChildren } from '../utils/node-operations';
|
||||
import { generateId } from '../utils/id';
|
||||
import { handleBatchDesign } from './batch-design';
|
||||
|
||||
export type CjkScript = null | 'chinese' | 'japanese' | 'korean';
|
||||
|
||||
export function detectCjkScript(s: string): CjkScript {
|
||||
// Hiragana U+3040-309F + Katakana U+30A0-30FF → Japanese
|
||||
if (/[\u3040-\u309f\u30a0-\u30ff]/.test(s)) return 'japanese';
|
||||
// Hangul Syllables U+AC00-D7AF → Korean
|
||||
if (/[\uac00-\ud7af]/.test(s)) return 'korean';
|
||||
// CJK Symbols / Punctuation U+3000-303F + CJK Unified Ideographs U+4E00-9FFF → Chinese
|
||||
if (/[\u3000-\u303f\u4e00-\u9fff]/.test(s)) return 'chinese';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a CJK script to its Noto Sans font family. Returns undefined for
|
||||
* non-CJK so callers can fall back to theme default (Inter for body,
|
||||
* theme heading for headings).
|
||||
*/
|
||||
export function cjkFontFamily(script: CjkScript): string | undefined {
|
||||
switch (script) {
|
||||
case 'japanese':
|
||||
return 'Noto Sans JP';
|
||||
case 'korean':
|
||||
return 'Noto Sans KR';
|
||||
case 'chinese':
|
||||
return 'Noto Sans SC';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
// CJK script detection + font-family dispatch + tree-build helpers all
|
||||
// moved to @zseven-w/pen-core/element-builders so apps/web client shims
|
||||
// and pen-mcp handlers share identical logic. Re-export here so any
|
||||
// external caller that imported these from `./element-tool-helpers`
|
||||
// keeps compiling without churn.
|
||||
export {
|
||||
assignIdsRecursively,
|
||||
buildScrollWrapper,
|
||||
cjkFontFamily,
|
||||
detectCjkScript,
|
||||
type CjkScript,
|
||||
} from '@zseven-w/pen-core';
|
||||
|
||||
/**
|
||||
* Simulate how batch-design.ts:resolveRef will interpret a JSON.stringify'd
|
||||
|
|
@ -57,8 +39,7 @@ function simulateDslParentResolve(parentId: string): string {
|
|||
* handleBatchDesign. batch_design's underlying `insertNodeInTree` silently
|
||||
* returns the original tree when the parent is missing, producing a
|
||||
* success-looking response (binding + nodeId) with an orphaned node that
|
||||
* never lands on disk. Element tools (add_scroll_row_v0 / add_bottom_nav_v0
|
||||
* / add_activity_ring_v0) must fail fast with a clear error instead.
|
||||
* never lands on disk. Element tools must fail fast with a clear error.
|
||||
*
|
||||
* Skips validation when parent_id is falsy (root-level insertion is always
|
||||
* valid). Throws a descriptive Error otherwise.
|
||||
|
|
@ -82,63 +63,6 @@ export async function ensureParentExists(params: {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walk a node subtree and stamp every node with a fresh id. batch_design's
|
||||
* downstream DSL only assigns an id to the TOP-level inserted node —
|
||||
* nested children arrive unchanged, leaving them unreferenceable by any
|
||||
* later tree operation.
|
||||
*/
|
||||
export function assignIdsRecursively(node: Record<string, unknown>): void {
|
||||
if (typeof node.id !== 'string') node.id = generateId();
|
||||
const children = node.children;
|
||||
if (Array.isArray(children)) {
|
||||
for (const child of children) {
|
||||
if (child && typeof child === 'object') {
|
||||
assignIdsRecursively(child as Record<string, unknown>);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the canonical scroll-row wrapper taught in
|
||||
* `packages/pen-ai-skills/skills/phases/generation/overflow.md` §HORIZONTAL
|
||||
* SCROLL ROWS: outer wrapper (fill_container + clipContent + vertical) >
|
||||
* inner row (fit_content + horizontal + gap + padding=[0,20]) > children.
|
||||
*
|
||||
* Shared by all three narrow row tools (add_card_row_v0 /
|
||||
* add_metric_row_v0 / add_nav_chip_row_v0). Each tool only differs in the
|
||||
* per-item node builder; the wrapper is identical.
|
||||
*/
|
||||
export function buildScrollWrapper(opts: {
|
||||
rowName: string;
|
||||
innerChildren: Record<string, unknown>[];
|
||||
gap: number;
|
||||
}): Record<string, unknown> {
|
||||
return {
|
||||
type: 'frame',
|
||||
name: opts.rowName,
|
||||
role: 'scroll-row-wrapper',
|
||||
width: 'fill_container',
|
||||
height: 'fit_content',
|
||||
layout: 'vertical',
|
||||
clipContent: true,
|
||||
children: [
|
||||
{
|
||||
type: 'frame',
|
||||
name: 'Scroll Inner Row',
|
||||
role: 'scroll-row',
|
||||
width: 'fit_content',
|
||||
height: 'fit_content',
|
||||
layout: 'horizontal',
|
||||
gap: opts.gap,
|
||||
padding: [0, 20],
|
||||
children: opts.innerChildren,
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a fully-built node subtree via handleBatchDesign's single-insert
|
||||
* DSL. Centralizes the parent_ref serialization + batch_design call
|
||||
|
|
|
|||
Loading…
Reference in a new issue