@bendyline/squisq 2.10.0 → 2.11.1
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.
- package/dist/{Doc-DTyeaFuW.d.ts → Doc-CRPQCkHn.d.ts} +34 -2
- package/dist/{ImageEditDoc-dFEclQ9l.d.ts → ImageEditDoc-MbvJM1HE.d.ts} +1 -1
- package/dist/{chunk-IO5XO6XH.js → chunk-64I44JAP.js} +1 -1
- package/dist/{chunk-CUYHFOFL.js → chunk-6ATZOUCQ.js} +223 -14
- package/dist/{chunk-DRFJU4MK.js → chunk-B26DU2RH.js} +353 -3
- package/dist/{chunk-T3B4WJBR.js → chunk-B3AK7SLZ.js} +87 -5
- package/dist/{chunk-7YEZFHLS.js → chunk-O7HLQ22N.js} +11 -0
- package/dist/{chunk-XSW4QTMB.js → chunk-QQ4I5HWV.js} +228 -6
- package/dist/{chunk-NBKAXPSX.js → chunk-TMOHAFYE.js} +1 -0
- package/dist/{chunk-MIKKUKOD.js → chunk-UBFT2CDQ.js} +30 -15
- package/dist/{chunk-FCG3BIZN.js → chunk-UNVHAK3A.js} +5 -1
- package/dist/{chunk-NFHMHYUV.js → chunk-UXKFSYTQ.js} +1 -1
- package/dist/doc/index.d.ts +123 -6
- package/dist/doc/index.js +13 -5
- package/dist/fence/index.d.ts +1 -1
- package/dist/generate/index.d.ts +1 -1
- package/dist/imageEdit/index.d.ts +3 -3
- package/dist/index.d.ts +8 -7
- package/dist/index.js +22 -10
- package/dist/jsonForm/index.d.ts +1 -1
- package/dist/markdown/index.js +3 -3
- package/dist/{materializePageSection-BRNIINlU.d.ts → materializePageSection-BeUPHeCl.d.ts} +1 -1
- package/dist/narration/index.d.ts +1 -1
- package/dist/narration/index.js +4 -4
- package/dist/proof/index.d.ts +22 -3
- package/dist/proof/index.js +1 -1
- package/dist/recommend/index.js +1 -1
- package/dist/schemas/index.d.ts +4 -4
- package/dist/storage/index.js +1 -1
- package/dist/table/index.d.ts +123 -0
- package/dist/table/index.js +298 -0
- package/dist/{themeLibrary-xaxN5UYu.d.ts → themeLibrary-BG3jr6mT.d.ts} +1 -1
- package/dist/transform/index.d.ts +2 -2
- package/dist/versions/index.d.ts +15 -1
- package/dist/versions/index.js +5 -1
- package/dist/viewState-lTZS-hP_.d.ts +91 -0
- package/package.json +6 -1
|
@@ -475,6 +475,38 @@ interface BigTextInput extends BaseTemplateBlock {
|
|
|
475
475
|
/** Ambient motion for the background image. */
|
|
476
476
|
ambientMotion?: 'zoomIn' | 'zoomOut' | 'panLeft' | 'panRight';
|
|
477
477
|
}
|
|
478
|
+
/**
|
|
479
|
+
* Transcript block - one conversational beat: speaker (avatar + name)
|
|
480
|
+
* and a message bubble. Variants: plain `speech`, private `thought`
|
|
481
|
+
* (muted italic), and `tool` (mono chip + optional result line). A
|
|
482
|
+
* `counterpartName` turns the beat into a two-avatar handoff — how
|
|
483
|
+
* agent-to-agent delegation renders in recorded-session playback.
|
|
484
|
+
*/
|
|
485
|
+
interface TranscriptBlockInput extends BaseTemplateBlock {
|
|
486
|
+
template: 'transcript';
|
|
487
|
+
/** Speaker display name. */
|
|
488
|
+
speaker: string;
|
|
489
|
+
/** Avatar image path (relative media). Missing → initials medallion. */
|
|
490
|
+
speakerImage?: string;
|
|
491
|
+
/** Which side the speaker column sits on. Default 'left'. */
|
|
492
|
+
side?: 'left' | 'right';
|
|
493
|
+
/** Beat kind. Default 'speech'. */
|
|
494
|
+
variant?: 'speech' | 'thought' | 'tool';
|
|
495
|
+
/** The message body. */
|
|
496
|
+
text: string;
|
|
497
|
+
/** Tool variant: the invoked tool's name, shown as a mono chip. */
|
|
498
|
+
toolName?: string;
|
|
499
|
+
/** Tool variant: bounded result line under the bubble. */
|
|
500
|
+
resultText?: string;
|
|
501
|
+
/** Handoff form: the receiving speaker's display name. */
|
|
502
|
+
counterpartName?: string;
|
|
503
|
+
/** Handoff form: the receiving speaker's avatar image path. */
|
|
504
|
+
counterpartImage?: string;
|
|
505
|
+
/** Muted corner line (timestamp, step, etc.). */
|
|
506
|
+
meta?: string;
|
|
507
|
+
/** Color scheme for the accent (tool chip, handoff arrow). */
|
|
508
|
+
colorScheme?: ColorScheme;
|
|
509
|
+
}
|
|
478
510
|
/**
|
|
479
511
|
* Content block - loss-averse heading and body layout.
|
|
480
512
|
*
|
|
@@ -1085,7 +1117,7 @@ type ChartTemplateInput = BarChartInput | ColumnChartInput | PieChartInput | Don
|
|
|
1085
1117
|
/**
|
|
1086
1118
|
* Union of all template block types.
|
|
1087
1119
|
*/
|
|
1088
|
-
type TemplateBlock = TitleBlockInput | SectionHeaderInput | BigTextInput | ContentBlockInput | StatHighlightInput | QuoteBlockInput | FactCardInput | TwoColumnInput | DateEventInput | ImageWithCaptionInput | LeftFeatureInput | RightFeatureInput | MapBlockInput | FullBleedQuoteInput | ListBlockInput | PhotoGridInput | DefinitionCardInput | ComparisonBarInput | PullQuoteInput | VideoWithCaptionInput | VideoPullQuoteInput | DataTableInput | BarChartInput | ColumnChartInput | PieChartInput | DonutChartInput | LineChartInput | AreaChartInput | ScatterChartInput | DiagramBlockInput | TreeBlockInput | TimelineBlockInput | DrawingBlockInput | RawLayersInput;
|
|
1120
|
+
type TemplateBlock = TitleBlockInput | SectionHeaderInput | BigTextInput | TranscriptBlockInput | ContentBlockInput | StatHighlightInput | QuoteBlockInput | FactCardInput | TwoColumnInput | DateEventInput | ImageWithCaptionInput | LeftFeatureInput | RightFeatureInput | MapBlockInput | FullBleedQuoteInput | ListBlockInput | PhotoGridInput | DefinitionCardInput | ComparisonBarInput | PullQuoteInput | VideoWithCaptionInput | VideoPullQuoteInput | DataTableInput | BarChartInput | ColumnChartInput | PieChartInput | DonutChartInput | LineChartInput | AreaChartInput | ScatterChartInput | DiagramBlockInput | TreeBlockInput | TimelineBlockInput | DrawingBlockInput | RawLayersInput;
|
|
1089
1121
|
/**
|
|
1090
1122
|
* A block can be either a raw Block or a TemplateBlock.
|
|
1091
1123
|
*/
|
|
@@ -2798,4 +2830,4 @@ declare function getBlockAtTime(blocks: Block[], time: number): Block | null;
|
|
|
2798
2830
|
*/
|
|
2799
2831
|
declare function getCaptionAtTime(captions: CaptionTrack | undefined, time: number): CaptionPhrase | null;
|
|
2800
2832
|
|
|
2801
|
-
export { type ImageLayer as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, DARK_SURFACE as D, DEFAULT_DOC_FONT as E, DEFAULT_TITLE_FONT as F, type DataTableInput as G, type DateEventInput as H, type DeepPartial as I, type DefinitionCardInput as J, type DiagramBlockInput as K, type DiagramEdgeAnchor as L, type DiagramTemplateEdge as M, type DiagramTemplateNode as N, type Doc as O, type DocBlock as P, type DocDiagnostic as Q, type DonutChartInput as R, type DrawingBlockInput as S, FRONTMATTER_CUSTOM_TEMPLATES_KEY as T, FRONTMATTER_CUSTOM_THEMES_KEY as U, type FactCardInput as V, type FontFamily as W, type FontFamilyKind as X, type FullBleedQuoteInput as Y, type GradientBackgroundConfig as Z, type ImageBackgroundConfig as _, type AccentPosition as a, type ScheduledClip as a$, type ImageTreatment as a0, type ImageWithCaptionInput as a1, LIGHT_SURFACE as a2, type Layer as a3, type LayerRepeat as a4, type LayoutHints as a5, type LeftFeatureInput as a6, type LineChartInput as a7, type LinearGradient as a8, type ListBlockInput as a9, type PageAccentRotation as aA, type PageBackground as aB, type PageDesignFamily as aC, type PageEmphasis as aD, type PageHeadingTreatment as aE, type PageSectionKind as aF, type PageSectionOverride as aG, type PageTokens as aH, type PathLayer as aI, type PatternBackgroundConfig as aJ, type PersistentLayer as aK, type PersistentLayerConfig as aL, type PersistentLayerTemplate as aM, type PersistentLayerTemplateConfig as aN, type PersistentLayerTemplateType as aO, type PhotoGridInput as aP, type PieChartInput as aQ, type PipStyle as aR, type Position as aS, type ProgressIndicatorConfig as aT, type PromotedBodyAnnotation as aU, type PullQuoteInput as aV, type QuoteBlockInput as aW, type RawLayersInput as aX, type RenderStyle as aY, type RightFeatureInput as aZ, type ScatterChartInput as a_, type MapBlockInput as aa, type MapLayer as ab, type MapMarker as ac, type MapTileStyle as ad, type MarkerStyle as ae, type MediaClip as af, type MediaScheduleOptions as ag, type MermaidLayer as ah, PAGE_ACCENT_STRATEGIES as ai, PAGE_BACKGROUNDS as aj, PAGE_BACKGROUND_RHYTHMS as ak, PAGE_DESIGN_FAMILIES as al, PAGE_DIVIDERS as am, PAGE_EMPHASES as an, PAGE_EYEBROWS as ao, PAGE_HEADING_CASES as ap, PAGE_HEADING_SCALES as aq, PAGE_HEADING_UNDERLINES as ar, PAGE_HERO_STYLES as as, PAGE_IMAGE_FRAMINGS as at, PAGE_NUMERAL_STYLES as au, PAGE_PATTERNS as av, PAGE_QUOTE_MARKS as aw, PAGE_SECTION_KINDS as ax, PAGE_SECTION_SPACINGS as ay, PAGE_SHADOWS as az, type AmbientGradientConfig as b,
|
|
2833
|
+
export { type ImageLayer as $, type AccentImage as A, type BarChartInput as B, type CaptionPhrase as C, DARK_SURFACE as D, DEFAULT_DOC_FONT as E, DEFAULT_TITLE_FONT as F, type DataTableInput as G, type DateEventInput as H, type DeepPartial as I, type DefinitionCardInput as J, type DiagramBlockInput as K, type DiagramEdgeAnchor as L, type DiagramTemplateEdge as M, type DiagramTemplateNode as N, type Doc as O, type DocBlock as P, type DocDiagnostic as Q, type DonutChartInput as R, type DrawingBlockInput as S, FRONTMATTER_CUSTOM_TEMPLATES_KEY as T, FRONTMATTER_CUSTOM_THEMES_KEY as U, type FactCardInput as V, type FontFamily as W, type FontFamilyKind as X, type FullBleedQuoteInput as Y, type GradientBackgroundConfig as Z, type ImageBackgroundConfig as _, type AccentPosition as a, type ScheduledClip as a$, type ImageTreatment as a0, type ImageWithCaptionInput as a1, LIGHT_SURFACE as a2, type Layer as a3, type LayerRepeat as a4, type LayoutHints as a5, type LeftFeatureInput as a6, type LineChartInput as a7, type LinearGradient as a8, type ListBlockInput as a9, type PageAccentRotation as aA, type PageBackground as aB, type PageDesignFamily as aC, type PageEmphasis as aD, type PageHeadingTreatment as aE, type PageSectionKind as aF, type PageSectionOverride as aG, type PageTokens as aH, type PathLayer as aI, type PatternBackgroundConfig as aJ, type PersistentLayer as aK, type PersistentLayerConfig as aL, type PersistentLayerTemplate as aM, type PersistentLayerTemplateConfig as aN, type PersistentLayerTemplateType as aO, type PhotoGridInput as aP, type PieChartInput as aQ, type PipStyle as aR, type Position as aS, type ProgressIndicatorConfig as aT, type PromotedBodyAnnotation as aU, type PullQuoteInput as aV, type QuoteBlockInput as aW, type RawLayersInput as aX, type RenderStyle as aY, type RightFeatureInput as aZ, type ScatterChartInput as a_, type MapBlockInput as aa, type MapLayer as ab, type MapMarker as ac, type MapTileStyle as ad, type MarkerStyle as ae, type MediaClip as af, type MediaScheduleOptions as ag, type MermaidLayer as ah, PAGE_ACCENT_STRATEGIES as ai, PAGE_BACKGROUNDS as aj, PAGE_BACKGROUND_RHYTHMS as ak, PAGE_DESIGN_FAMILIES as al, PAGE_DIVIDERS as am, PAGE_EMPHASES as an, PAGE_EYEBROWS as ao, PAGE_HEADING_CASES as ap, PAGE_HEADING_SCALES as aq, PAGE_HEADING_UNDERLINES as ar, PAGE_HERO_STYLES as as, PAGE_IMAGE_FRAMINGS as at, PAGE_NUMERAL_STYLES as au, PAGE_PATTERNS as av, PAGE_QUOTE_MARKS as aw, PAGE_SECTION_KINDS as ax, PAGE_SECTION_SPACINGS as ay, PAGE_SHADOWS as az, type AmbientGradientConfig as b, getSafeTextBounds as b$, type SectionHeaderInput as b0, type ShapeFilter as b1, type ShapeLayer as b2, type ShapePattern as b3, type SolidBackgroundConfig as b4, type StartBlockConfig as b5, type StatHighlightInput as b6, type SurfaceScheme as b7, THEME_SCHEMA_VERSION as b8, type TableLayer as b9, type TreeLayerStyle as bA, type TreeTemplateItem as bB, type TwoColumnInput as bC, VIEWPORT_PRESETS as bD, type VideoLayer as bE, type VideoPipPosition as bF, type VideoPipShape as bG, type VideoPipSize as bH, type VideoPlacement as bI, type VideoPresentation as bJ, type VideoPullQuoteInput as bK, type VideoWithCaptionInput as bL, type ViewportConfig as bM, type ViewportOrientation as bN, type ViewportPreset as bO, type VignetteConfig as bP, applySurface as bQ, calculateDuration as bR, calculateFontScale as bS, createTemplateContext as bT, createTheme as bU, createThemeRegistry as bV, getAspectRatioString as bW, getBlockAtTime as bX, getCaptionAtTime as bY, getDocPlaybackDuration as bZ, getLayoutHints as b_, type TableLayerStyle as ba, type TemplateBlock as bb, type TemplateContext as bc, type TemplateFunction as bd, type TemplateRegistry as be, type TextLayer as bf, type TextStyle as bg, type Theme as bh, type ThemeColorPalette as bi, type ThemeColorScheme as bj, type ThemePageStyle as bk, type ThemeRegistry as bl, type ThemeSchemaVersion as bm, type ThemeSeedColors as bn, type ThemeStyle as bo, type ThemeTypography as bp, type TimelineBlockInput as bq, type TimelineTemplateEvent as br, type TimelineTemplateLink as bs, type TimelineTemplateTrack as bt, type TitleBlockInput as bu, type TitleCaptionConfig as bv, type TranscriptBlockInput as bw, type TreeBlockInput as bx, type TreeLayer as by, type TreeLayerItem as bz, type Animation as c, getSegmentAtTime as c0, getTwoColumnPositions as c1, getViewport as c2, getViewportOrientation as c3, isCustomTemplateDefinition as c4, isPersistentLayerTemplate as c5, isTemplateBlock as c6, scaledFontSize$1 as c7, resolveMediaSchedule as c8, scaledFontSize as c9, validateCustomTemplateDefinition as ca, type AnimationType as d, type AreaChartInput as e, type AudioBookmark as f, type AudioSegment as g, type AudioTimingData as h, type AudioTrack as i, type BigTextInput as j, type Block as k, type BlockConnection as l, type BorderStyle as m, type CaptionTrack as n, type CaptionWord as o, type ChartBaseFields as p, type ChartTemplateInput as q, type ColorScheme as r, type ColumnChartInput as s, type ComparisonBarInput as t, type ContentBlockInput as u, type CornerBrandingConfig as v, type CustomTemplateDefinition as w, type CustomTemplateLayer as x, type CustomTemplateValidationError as y, type CustomTemplateValidationResult as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as ImageLayer, bf as TextLayer, b2 as ShapeLayer, aI as PathLayer } from './Doc-
|
|
1
|
+
import { $ as ImageLayer, bf as TextLayer, b2 as ShapeLayer, aI as PathLayer } from './Doc-CRPQCkHn.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* ImageEditDoc — JSON document describing a layered, editable image.
|
|
@@ -176,6 +176,11 @@ function parseAsciiDiagramWithStats(text) {
|
|
|
176
176
|
const style = detectStyle(grid);
|
|
177
177
|
const rects = traceBoxes(grid);
|
|
178
178
|
const boxes = buildBoxes(grid, rects, warnings);
|
|
179
|
+
const boxNodes = boxes.length;
|
|
180
|
+
const railBoxes = findRailLabels(grid, boxes);
|
|
181
|
+
for (const rail of railBoxes) boxes.push(rail);
|
|
182
|
+
const railNodes = railBoxes.length;
|
|
183
|
+
if (railNodes > 0) warnings.push(`rail-labels(${railNodes})`);
|
|
179
184
|
const mask = new Uint8Array(W * H);
|
|
180
185
|
const perimeterOwners = /* @__PURE__ */ new Map();
|
|
181
186
|
for (let b = 0; b < boxes.length; b++) {
|
|
@@ -248,18 +253,21 @@ function parseAsciiDiagramWithStats(text) {
|
|
|
248
253
|
if (looseRuns.length > MAX_LOOSE_WARNINGS) {
|
|
249
254
|
warnings.push(`loose-text (+${looseRuns.length - MAX_LOOSE_WARNINGS} more)`);
|
|
250
255
|
}
|
|
251
|
-
const nodes = boxes.map((box) =>
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
256
|
+
const nodes = boxes.map((box) => {
|
|
257
|
+
const rect = box.emit ?? box;
|
|
258
|
+
return {
|
|
259
|
+
id: box.id,
|
|
260
|
+
label: box.labelLines.join("\n"),
|
|
261
|
+
col: rect.c0,
|
|
262
|
+
row: rect.r0,
|
|
263
|
+
wCols: rect.c1 - rect.c0 + 1,
|
|
264
|
+
hRows: rect.r1 - rect.r0 + 1,
|
|
265
|
+
...box.parentIdx >= 0 ? { containerId: boxes[box.parentIdx].id } : {}
|
|
266
|
+
};
|
|
267
|
+
}).sort((a, b) => a.row - b.row || a.col - b.col);
|
|
260
268
|
return {
|
|
261
269
|
diagram: { nodes, edges, style, warnings },
|
|
262
|
-
stats: { totalNonSpaceCells, looseNonSpaceCells, hasWideChars }
|
|
270
|
+
stats: { totalNonSpaceCells, looseNonSpaceCells, hasWideChars, boxNodes, railNodes }
|
|
263
271
|
};
|
|
264
272
|
}
|
|
265
273
|
function buildGrid(text, warnings) {
|
|
@@ -497,6 +505,176 @@ function slugify(s) {
|
|
|
497
505
|
const slug2 = s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
498
506
|
return slug2 || "node";
|
|
499
507
|
}
|
|
508
|
+
var BUS_LABEL_LOOKASIDE = 3;
|
|
509
|
+
var RAIL_LABEL_PAD = 1;
|
|
510
|
+
var BOX_SPILL_GAP = 2;
|
|
511
|
+
var RAIL_ROW_SCALE = 3;
|
|
512
|
+
var RAIL_COL_SCALE = 2;
|
|
513
|
+
function railRect(text, lines, boxScale) {
|
|
514
|
+
if (boxScale) {
|
|
515
|
+
const r0 = text.r0 * RAIL_ROW_SCALE;
|
|
516
|
+
const c0 = text.c0 * RAIL_COL_SCALE;
|
|
517
|
+
return {
|
|
518
|
+
r0,
|
|
519
|
+
c0,
|
|
520
|
+
r1: r0 + Math.max(3, lines + 2) - 1,
|
|
521
|
+
c1: c0 + Math.max(3, text.c1 - text.c0 + 1 + 4) - 1
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
const top = Math.max(0, text.r0 - RAIL_LABEL_PAD);
|
|
525
|
+
const left = Math.max(0, text.c0 - RAIL_LABEL_PAD);
|
|
526
|
+
return {
|
|
527
|
+
r0: top,
|
|
528
|
+
c0: left,
|
|
529
|
+
r1: top + (text.r1 - text.r0) + 2 * RAIL_LABEL_PAD,
|
|
530
|
+
c1: left + (text.c1 - text.c0) + 2 * RAIL_LABEL_PAD
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function findRailLabels(grid, boxes) {
|
|
534
|
+
const H = grid.length;
|
|
535
|
+
const W = H > 0 ? grid[0].length : 0;
|
|
536
|
+
if (H === 0 || W === 0) return [];
|
|
537
|
+
const inBox = new Uint8Array(W * H);
|
|
538
|
+
for (const box of boxes) {
|
|
539
|
+
for (let r = Math.max(0, box.r0); r <= Math.min(H - 1, box.r1); r++) {
|
|
540
|
+
for (let c = Math.max(0, box.c0); c <= Math.min(W - 1, box.c1); c++) inBox[r * W + c] = 1;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const at = (r, c) => r >= 0 && r < H && c >= 0 && c < W ? grid[r][c] : " ";
|
|
544
|
+
const joins = (ch) => isLineChar(ch) || isJunction(ch) || isPlus(ch) || isAnyCorner(ch);
|
|
545
|
+
const vertJoins = (ch) => {
|
|
546
|
+
const arrow = arrowDirection(ch);
|
|
547
|
+
return joins(ch) || arrow === "up" || arrow === "down";
|
|
548
|
+
};
|
|
549
|
+
const horizJoins = (ch) => {
|
|
550
|
+
const arrow = arrowDirection(ch);
|
|
551
|
+
return joins(ch) || arrow === "left" || arrow === "right";
|
|
552
|
+
};
|
|
553
|
+
const routingRow = [];
|
|
554
|
+
for (let r = 0; r < H; r++) {
|
|
555
|
+
let any = false;
|
|
556
|
+
let all = true;
|
|
557
|
+
for (let c = 0; c < W && all; c++) {
|
|
558
|
+
const ch = grid[r][c];
|
|
559
|
+
if (ch === " ") continue;
|
|
560
|
+
any = true;
|
|
561
|
+
if (!isLineChar(ch) && arrowDirection(ch) === null) all = false;
|
|
562
|
+
}
|
|
563
|
+
routingRow.push(any && all);
|
|
564
|
+
}
|
|
565
|
+
const structural = (r, c) => {
|
|
566
|
+
const ch = at(r, c);
|
|
567
|
+
if (ch === " ") return false;
|
|
568
|
+
if (arrowDirection(ch) !== null) return true;
|
|
569
|
+
const ascii = asciiArrowDirection(ch);
|
|
570
|
+
if (ascii !== null && asciiArrowGate(grid, r, c, ascii)) return true;
|
|
571
|
+
if (!isLineChar(ch)) return false;
|
|
572
|
+
if (routingRow[r]) return true;
|
|
573
|
+
const vert = vertJoins(at(r - 1, c)) || vertJoins(at(r + 1, c));
|
|
574
|
+
if (isVert(ch)) return vert;
|
|
575
|
+
const horiz = horizJoins(at(r, c - 1)) || horizJoins(at(r, c + 1));
|
|
576
|
+
if (isHoriz(ch)) return horiz;
|
|
577
|
+
return vert || horiz;
|
|
578
|
+
};
|
|
579
|
+
const isTextCell = (r, c) => c >= 0 && c < W && grid[r][c] !== " " && !inBox[r * W + c] && !structural(r, c);
|
|
580
|
+
const runs = [];
|
|
581
|
+
for (let r = 0; r < H; r++) {
|
|
582
|
+
let start = -1;
|
|
583
|
+
let end = -1;
|
|
584
|
+
const flush = () => {
|
|
585
|
+
if (start >= 0) {
|
|
586
|
+
const text = grid[r].slice(start, end + 1).join("").trim();
|
|
587
|
+
if (text.length > 0) runs.push({ row: r, c0: start, c1: end, text });
|
|
588
|
+
}
|
|
589
|
+
start = -1;
|
|
590
|
+
};
|
|
591
|
+
for (let c = 0; c < W; c++) {
|
|
592
|
+
if (isTextCell(r, c)) {
|
|
593
|
+
if (start < 0) start = c;
|
|
594
|
+
end = c;
|
|
595
|
+
} else if (start >= 0 && grid[r][c] === " " && isTextCell(r, c + 1)) {
|
|
596
|
+
continue;
|
|
597
|
+
} else {
|
|
598
|
+
flush();
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
flush();
|
|
602
|
+
}
|
|
603
|
+
const abutsRail = (run) => [-1, 1].some((dir) => {
|
|
604
|
+
for (let step = 1; step <= BUS_LABEL_LOOKASIDE; step++) {
|
|
605
|
+
const c = dir < 0 ? run.c0 - step : run.c1 + step;
|
|
606
|
+
if (at(run.row, c) === " ") continue;
|
|
607
|
+
return structural(run.row, c);
|
|
608
|
+
}
|
|
609
|
+
return false;
|
|
610
|
+
});
|
|
611
|
+
const spillsFromBox = (run) => boxes.some(
|
|
612
|
+
(box) => run.row >= box.r0 && run.row <= box.r1 && run.c0 <= box.c1 + BOX_SPILL_GAP && run.c1 >= box.c0 - BOX_SPILL_GAP
|
|
613
|
+
);
|
|
614
|
+
const candidates = runs.filter(
|
|
615
|
+
(run) => /[a-z0-9]/i.test(run.text) && !abutsRail(run) && !spillsFromBox(run)
|
|
616
|
+
);
|
|
617
|
+
const groups = [];
|
|
618
|
+
let previousRow = [];
|
|
619
|
+
for (let r = 0; r < H; r++) {
|
|
620
|
+
const rowRuns = candidates.filter((run) => run.row === r);
|
|
621
|
+
const currentRow = [];
|
|
622
|
+
for (const run of rowRuns) {
|
|
623
|
+
const host = previousRow.find((group) => {
|
|
624
|
+
const last = group[group.length - 1];
|
|
625
|
+
return last.row === r - 1 && last.c0 <= run.c1 && run.c0 <= last.c1;
|
|
626
|
+
});
|
|
627
|
+
if (host) {
|
|
628
|
+
host.push(run);
|
|
629
|
+
currentRow.push(host);
|
|
630
|
+
} else {
|
|
631
|
+
const group = [run];
|
|
632
|
+
groups.push(group);
|
|
633
|
+
currentRow.push(group);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
previousRow = currentRow;
|
|
637
|
+
}
|
|
638
|
+
const railHead = (r, c) => {
|
|
639
|
+
if (r < 0 || r >= H || inBox[r * W + c] === 1 || !structural(r, c)) return false;
|
|
640
|
+
const ch = grid[r][c];
|
|
641
|
+
const arrow = arrowDirection(ch) ?? asciiArrowDirection(ch);
|
|
642
|
+
return isVert(ch) || isJunction(ch) || isPlus(ch) || arrow === "up" || arrow === "down";
|
|
643
|
+
};
|
|
644
|
+
const railAdjacent = (group) => group.some(
|
|
645
|
+
(run) => [run.row - 1, run.row + 1].some((r) => {
|
|
646
|
+
for (let c = Math.max(0, run.c0 - 1); c <= Math.min(W - 1, run.c1 + 1); c++) {
|
|
647
|
+
if (railHead(r, c)) return true;
|
|
648
|
+
}
|
|
649
|
+
return false;
|
|
650
|
+
})
|
|
651
|
+
);
|
|
652
|
+
const usedIds = /* @__PURE__ */ new Map();
|
|
653
|
+
for (const box of boxes) usedIds.set(box.id, (usedIds.get(box.id) ?? 0) + 1);
|
|
654
|
+
const out = [];
|
|
655
|
+
for (const group of groups) {
|
|
656
|
+
if (!railAdjacent(group)) continue;
|
|
657
|
+
const labelLines = group.map((run) => run.text);
|
|
658
|
+
const r0 = group[0].row;
|
|
659
|
+
const r1 = group[group.length - 1].row;
|
|
660
|
+
const c0 = Math.min(...group.map((run) => run.c0));
|
|
661
|
+
const c1 = Math.max(...group.map((run) => run.c1));
|
|
662
|
+
const base = slugify(labelLines[0]);
|
|
663
|
+
const count = usedIds.get(base) ?? 0;
|
|
664
|
+
usedIds.set(base, count + 1);
|
|
665
|
+
out.push({
|
|
666
|
+
r0,
|
|
667
|
+
c0,
|
|
668
|
+
r1,
|
|
669
|
+
c1,
|
|
670
|
+
parentIdx: -1,
|
|
671
|
+
labelLines,
|
|
672
|
+
id: count === 0 ? base : `${base}-${count + 1}`,
|
|
673
|
+
emit: railRect({ r0, c0, r1, c1 }, labelLines.length, boxes.length === 0)
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
return out;
|
|
677
|
+
}
|
|
500
678
|
function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
501
679
|
const H = grid.length;
|
|
502
680
|
const W = H > 0 ? grid[0].length : 0;
|
|
@@ -687,6 +865,26 @@ function extractEdges(grid, mask, perimeterOwners, boxes, warnings) {
|
|
|
687
865
|
attachmentsByBox.set(boxIdx, { boxIdx, isArrowEnd: false });
|
|
688
866
|
}
|
|
689
867
|
}
|
|
868
|
+
if (attachmentsByBox.size < 2) {
|
|
869
|
+
for (const idx of component) {
|
|
870
|
+
const r = Math.floor(idx / W);
|
|
871
|
+
const c = idx % W;
|
|
872
|
+
const ch = grid[r][c];
|
|
873
|
+
const axis = isVert(ch) ? [
|
|
874
|
+
[-1, 0],
|
|
875
|
+
[1, 0]
|
|
876
|
+
] : isHoriz(ch) ? [
|
|
877
|
+
[0, -1],
|
|
878
|
+
[0, 1]
|
|
879
|
+
] : [];
|
|
880
|
+
for (const [dr, dc] of axis) {
|
|
881
|
+
const boxIdx = nearestOwner(r + dr, c + dc);
|
|
882
|
+
if (boxIdx !== null && !attachmentsByBox.has(boxIdx)) {
|
|
883
|
+
attachmentsByBox.set(boxIdx, { boxIdx, isArrowEnd: false });
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
690
888
|
const attachments = [...attachmentsByBox.values()].sort(
|
|
691
889
|
(a, b) => boxes[a.boxIdx].r0 - boxes[b.boxIdx].r0 || boxes[a.boxIdx].c0 - boxes[b.boxIdx].c0
|
|
692
890
|
);
|
|
@@ -908,6 +1106,7 @@ var MAX_LINES = 400;
|
|
|
908
1106
|
var MAX_COLS = 400;
|
|
909
1107
|
var MIN_LINES = 3;
|
|
910
1108
|
var MAX_LOOSE_RATIO = 0.25;
|
|
1109
|
+
var ROUTING_ROW = /^[\s\u2500-\u257F+\-|^v<>\u25B2\u25BC\u25C0\u25B6\u25C4\u25BA\u2190\u2192\u2191\u2193]+$/;
|
|
911
1110
|
var STRUCTURAL_IN_LABEL = /[│┃║┌┐└┘├┤┬┴┼╭╮╰╯┏┓┗┛╔╗╚╝┣┫┳┻╋╠╣╦╩╬╞╡╥╨╫╪]/;
|
|
912
1111
|
function isEligibleAsciiFenceLang(lang) {
|
|
913
1112
|
if (lang === null || lang === void 0) return true;
|
|
@@ -940,8 +1139,14 @@ function detectAsciiDiagram(text, opts = {}) {
|
|
|
940
1139
|
const plusMatches = line.match(/\+[-+]/g);
|
|
941
1140
|
tlCandidates += plusMatches ? plusMatches.length : 0;
|
|
942
1141
|
}
|
|
943
|
-
|
|
944
|
-
|
|
1142
|
+
const routingRows = lines.filter(
|
|
1143
|
+
(line) => line.trim().length > 0 && ROUTING_ROW.test(line)
|
|
1144
|
+
).length;
|
|
1145
|
+
if (tlCandidates < 2 && routingRows < 2) {
|
|
1146
|
+
return {
|
|
1147
|
+
isDiagram: false,
|
|
1148
|
+
reasons: [`too-few-corner-candidates(${tlCandidates}) routing-rows(${routingRows})`]
|
|
1149
|
+
};
|
|
945
1150
|
}
|
|
946
1151
|
}
|
|
947
1152
|
const nonBlank = lines.filter((l) => l.trim().length > 0);
|
|
@@ -960,6 +1165,9 @@ function detectAsciiDiagram(text, opts = {}) {
|
|
|
960
1165
|
return { isDiagram: false, reasons: [`garbled-labels(${garbled}/${diagram.nodes.length})`] };
|
|
961
1166
|
}
|
|
962
1167
|
if (!explicit) {
|
|
1168
|
+
if (stats.boxNodes === 0 && diagram.edges.length === 0) {
|
|
1169
|
+
return { isDiagram: false, reasons: [`rail-labels-unconnected(${stats.railNodes})`] };
|
|
1170
|
+
}
|
|
963
1171
|
if (diagram.edges.length === 0 && diagram.nodes.length >= 4 && isLattice(diagram)) {
|
|
964
1172
|
return { isDiagram: false, reasons: ["table-lattice"] };
|
|
965
1173
|
}
|
|
@@ -1961,7 +2169,7 @@ function detectAsciiTimeline(text, options = {}) {
|
|
|
1961
2169
|
if (!explicit && lines.some((line) => BOX_TOP_EDGE_RE.test(line))) {
|
|
1962
2170
|
return { isTimeline: false, reasons: ["has-box-corners"] };
|
|
1963
2171
|
}
|
|
1964
|
-
const boxes = parseAsciiDiagramWithStats(text).
|
|
2172
|
+
const boxes = parseAsciiDiagramWithStats(text).stats.boxNodes;
|
|
1965
2173
|
if (boxes >= (explicit ? 2 : 1)) {
|
|
1966
2174
|
return { isTimeline: false, reasons: [`has-boxes(${boxes})`] };
|
|
1967
2175
|
}
|
|
@@ -2205,7 +2413,7 @@ function detectTree(text, opts = {}) {
|
|
|
2205
2413
|
if (!explicit && detectAsciiTimeline(text).isTimeline) {
|
|
2206
2414
|
return { isTree: false, reasons: ["is-timeline"] };
|
|
2207
2415
|
}
|
|
2208
|
-
const boxes = parseAsciiDiagramWithStats(text).
|
|
2416
|
+
const boxes = parseAsciiDiagramWithStats(text).stats.boxNodes;
|
|
2209
2417
|
if (boxes >= 2) {
|
|
2210
2418
|
return { isTree: false, reasons: [`has-boxes(${boxes})`] };
|
|
2211
2419
|
}
|
|
@@ -2488,6 +2696,7 @@ export {
|
|
|
2488
2696
|
isVert,
|
|
2489
2697
|
isJunction,
|
|
2490
2698
|
arrowDirection,
|
|
2699
|
+
isLineChar,
|
|
2491
2700
|
UNICODE_VOCAB,
|
|
2492
2701
|
ASCII_VOCAB,
|
|
2493
2702
|
MAX_BRIDGE_GAP,
|