@visulima/tui 0.0.1 → 1.0.0-alpha.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.
- package/CHANGELOG.md +200 -0
- package/LICENSE.md +303 -0
- package/README.md +173 -29
- package/dist/core/app.d.ts +50 -0
- package/dist/core/cell.d.ts +33 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.js +5 -0
- package/dist/core/inline.d.ts +22 -0
- package/dist/core/input.d.ts +18 -0
- package/dist/core/native-binding.d.ts +22 -0
- package/dist/ink/ansi-to-cell.d.ts +5 -0
- package/dist/ink/ansi-tokenizer.d.ts +38 -0
- package/dist/ink/clipboard.d.ts +29 -0
- package/dist/ink/color-matrix.d.ts +49 -0
- package/dist/ink/color-utils.d.ts +30 -0
- package/dist/ink/colorize.d.ts +4 -0
- package/dist/ink/components/AccessibilityContext.d.ts +4 -0
- package/dist/ink/components/Alert.d.ts +30 -0
- package/dist/ink/components/AnimationContext.d.ts +10 -0
- package/dist/ink/components/App.d.ts +19 -0
- package/dist/ink/components/AppContext.d.ts +38 -0
- package/dist/ink/components/BackgroundContext.d.ts +5 -0
- package/dist/ink/components/Badge.d.ts +27 -0
- package/dist/ink/components/BigText.d.ts +71 -0
- package/dist/ink/components/Box.d.ts +58 -0
- package/dist/ink/components/Code.d.ts +46 -0
- package/dist/ink/components/ConfirmInput.d.ts +40 -0
- package/dist/ink/components/ConsoleOverlay.d.ts +52 -0
- package/dist/ink/components/Cursor.d.ts +43 -0
- package/dist/ink/components/CursorContext.d.ts +12 -0
- package/dist/ink/components/Dialog.d.ts +93 -0
- package/dist/ink/components/DiffView.d.ts +71 -0
- package/dist/ink/components/ErrorBoundary.d.ts +17 -0
- package/dist/ink/components/ErrorOverview.d.ts +6 -0
- package/dist/ink/components/FocusContext.d.ts +17 -0
- package/dist/ink/components/Gradient.d.ts +38 -0
- package/dist/ink/components/Help.d.ts +49 -0
- package/dist/ink/components/Link.d.ts +34 -0
- package/dist/ink/components/Markdown.d.ts +34 -0
- package/dist/ink/components/MultiSelect.d.ts +63 -0
- package/dist/ink/components/Newline.d.ts +12 -0
- package/dist/ink/components/OrderedList.d.ts +30 -0
- package/dist/ink/components/Paginator.d.ts +75 -0
- package/dist/ink/components/ProgressBar.d.ts +51 -0
- package/dist/ink/components/SelectInput.d.ts +96 -0
- package/dist/ink/components/SelectInputIndicator.d.ts +36 -0
- package/dist/ink/components/SelectInputItem.d.ts +43 -0
- package/dist/ink/components/Slider.d.ts +92 -0
- package/dist/ink/components/Spacer.d.ts +7 -0
- package/dist/ink/components/Spinner.d.ts +42 -0
- package/dist/ink/components/Static.d.ts +24 -0
- package/dist/ink/components/StaticRender.d.ts +28 -0
- package/dist/ink/components/StatusMessage.d.ts +26 -0
- package/dist/ink/components/StderrContext.d.ts +16 -0
- package/dist/ink/components/StdinContext.d.ts +29 -0
- package/dist/ink/components/StdoutContext.d.ts +16 -0
- package/dist/ink/components/Stopwatch.d.ts +44 -0
- package/dist/ink/components/Tab.d.ts +25 -0
- package/dist/ink/components/Table.d.ts +80 -0
- package/dist/ink/components/Tabs.d.ts +104 -0
- package/dist/ink/components/Text.d.ts +63 -0
- package/dist/ink/components/TextInput.d.ts +48 -0
- package/dist/ink/components/Textarea.d.ts +62 -0
- package/dist/ink/components/Timer.d.ts +52 -0
- package/dist/ink/components/Transform.d.ts +16 -0
- package/dist/ink/components/UnorderedList.d.ts +35 -0
- package/dist/ink/components/file-picker/FilePicker.d.ts +75 -0
- package/dist/ink/components/file-picker/index.d.ts +3 -0
- package/dist/ink/components/file-picker/types.d.ts +38 -0
- package/dist/ink/components/file-picker/use-file-system.d.ts +16 -0
- package/dist/ink/components/scroll/ControlledScrollView.d.ts +43 -0
- package/dist/ink/components/scroll/ScrollBar.d.ts +20 -0
- package/dist/ink/components/scroll/ScrollBarBox.d.ts +15 -0
- package/dist/ink/components/scroll/ScrollList.d.ts +12 -0
- package/dist/ink/components/scroll/ScrollView.d.ts +98 -0
- package/dist/ink/components/scroll/index.d.ts +10 -0
- package/dist/ink/components/scroll/use-state-ref.d.ts +8 -0
- package/dist/ink/components/tree-view/TreeView.d.ts +89 -0
- package/dist/ink/components/tree-view/TreeViewNode.d.ts +29 -0
- package/dist/ink/components/tree-view/index.d.ts +11 -0
- package/dist/ink/components/tree-view/theme.d.ts +24 -0
- package/dist/ink/components/tree-view/tree-node-map.d.ts +72 -0
- package/dist/ink/components/tree-view/types.d.ts +55 -0
- package/dist/ink/components/tree-view/use-tree-view-state.d.ts +135 -0
- package/dist/ink/components/tree-view/use-tree-view.d.ts +26 -0
- package/dist/ink/components/variant-config.d.ts +10 -0
- package/dist/ink/cursor-helpers.d.ts +38 -0
- package/dist/ink/data-limited-lru-map.d.ts +21 -0
- package/dist/ink/devtools-window-polyfill.d.ts +1 -0
- package/dist/ink/devtools.d.ts +1 -0
- package/dist/ink/dom.d.ts +213 -0
- package/dist/ink/get-max-width.d.ts +3 -0
- package/dist/ink/highlighter.d.ts +28 -0
- package/dist/ink/hooks/use-animation.d.ts +43 -0
- package/dist/ink/hooks/use-app.d.ts +6 -0
- package/dist/ink/hooks/use-box-metrics.d.ts +58 -0
- package/dist/ink/hooks/use-clipboard.d.ts +29 -0
- package/dist/ink/hooks/use-color-blindness.d.ts +33 -0
- package/dist/ink/hooks/use-console-capture.d.ts +43 -0
- package/dist/ink/hooks/use-cursor.d.ts +12 -0
- package/dist/ink/hooks/use-focus-manager.d.ts +42 -0
- package/dist/ink/hooks/use-focus.d.ts +30 -0
- package/dist/ink/hooks/use-input.d.ts +149 -0
- package/dist/ink/hooks/use-is-screen-reader-enabled.d.ts +6 -0
- package/dist/ink/hooks/use-key-bindings.d.ts +61 -0
- package/dist/ink/hooks/use-linked-scroll.d.ts +41 -0
- package/dist/ink/hooks/use-paste.d.ts +44 -0
- package/dist/ink/hooks/use-scroll-acceleration.d.ts +47 -0
- package/dist/ink/hooks/use-scroll-input.d.ts +34 -0
- package/dist/ink/hooks/use-stderr.d.ts +6 -0
- package/dist/ink/hooks/use-stdin.d.ts +7 -0
- package/dist/ink/hooks/use-stdout.d.ts +6 -0
- package/dist/ink/hooks/use-stopwatch.d.ts +40 -0
- package/dist/ink/hooks/use-terminal-palette.d.ts +19 -0
- package/dist/ink/hooks/use-text-buffer.d.ts +42 -0
- package/dist/ink/hooks/use-text-selection.d.ts +45 -0
- package/dist/ink/hooks/use-timer.d.ts +49 -0
- package/dist/ink/hooks/use-window-size.d.ts +18 -0
- package/dist/ink/ime-utils.d.ts +25 -0
- package/dist/ink/index.d.ts +159 -0
- package/dist/ink/index.js +100 -0
- package/dist/ink/ink.d.ts +189 -0
- package/dist/ink/input-parser.d.ts +10 -0
- package/dist/ink/input-utils.d.ts +16 -0
- package/dist/ink/instances.d.ts +3 -0
- package/dist/ink/kitty-keyboard.d.ts +23 -0
- package/dist/ink/layout.d.ts +26 -0
- package/dist/ink/log-update-native.d.ts +14 -0
- package/dist/ink/log-update.d.ts +21 -0
- package/dist/ink/measure-element.d.ts +147 -0
- package/dist/ink/measure-text.d.ts +56 -0
- package/dist/ink/mouse/Fullscreen.d.ts +8 -0
- package/dist/ink/mouse/MouseProvider.d.ts +11 -0
- package/dist/ink/mouse/ansi-parser.d.ts +37 -0
- package/dist/ink/mouse/constants.d.ts +59 -0
- package/dist/ink/mouse/index.d.ts +20 -0
- package/dist/ink/mouse/is-intersecting.d.ts +18 -0
- package/dist/ink/mouse/mouse-context.d.ts +36 -0
- package/dist/ink/mouse/use-element-position.d.ts +29 -0
- package/dist/ink/mouse/use-mouse-action.d.ts +7 -0
- package/dist/ink/mouse/use-mouse-position.d.ts +7 -0
- package/dist/ink/mouse/use-mouse.d.ts +7 -0
- package/dist/ink/mouse/use-on-mouse-click.d.ts +14 -0
- package/dist/ink/mouse/use-on-mouse-hover.d.ts +8 -0
- package/dist/ink/mouse/use-on-mouse-state.d.ts +11 -0
- package/dist/ink/output.d.ts +74 -0
- package/dist/ink/parse-keypress.d.ts +22 -0
- package/dist/ink/reconciler.d.ts +3 -0
- package/dist/ink/region.d.ts +99 -0
- package/dist/ink/render-background.d.ts +4 -0
- package/dist/ink/render-border.d.ts +4 -0
- package/dist/ink/render-node-to-output.d.ts +38 -0
- package/dist/ink/render-scrollbar.d.ts +9 -0
- package/dist/ink/render-sticky.d.ts +44 -0
- package/dist/ink/render-to-string.d.ts +37 -0
- package/dist/ink/render.d.ts +191 -0
- package/dist/ink/renderer.d.ts +17 -0
- package/dist/ink/resize-observer.d.ts +44 -0
- package/dist/ink/sanitize-ansi.d.ts +2 -0
- package/dist/ink/scroll.d.ts +23 -0
- package/dist/ink/selection.d.ts +70 -0
- package/dist/ink/squash-text-nodes.d.ts +18 -0
- package/dist/ink/style-flags.d.ts +17 -0
- package/dist/ink/styled-line-factory.d.ts +25 -0
- package/dist/ink/styled-line-serializer.d.ts +18 -0
- package/dist/ink/styled-line.d.ts +109 -0
- package/dist/ink/styles.d.ts +369 -0
- package/dist/ink/terminal-palette.d.ts +25 -0
- package/dist/ink/text-wrap.d.ts +10 -0
- package/dist/ink/token-to-elements.d.ts +22 -0
- package/dist/ink/utils/format-time.d.ts +4 -0
- package/dist/ink/utils.d.ts +9 -0
- package/dist/ink/wrap-text.d.ts +3 -0
- package/dist/ink/write-synchronized.d.ts +4 -0
- package/dist/packem_chunks/devtools.js +27 -0
- package/dist/packem_shared/AccessibilityContext-BLelHhNU.js +7 -0
- package/dist/packem_shared/Alert-Dr3s_LD9.js +17 -0
- package/dist/packem_shared/AnimationContext-BcJg8Jr6.js +15 -0
- package/dist/packem_shared/AppContext-CP0U6H7O.js +11 -0
- package/dist/packem_shared/BackgroundContext-BAUaxfOb.js +5 -0
- package/dist/packem_shared/Badge-Dk7EGGM6.js +13 -0
- package/dist/packem_shared/BigText-CjMdY63X.js +24 -0
- package/dist/packem_shared/Box-D_pSJ9Jp.js +73 -0
- package/dist/packem_shared/COLOR_BLINDNESS_SIMULATION-BsMy5Ewl.js +81 -0
- package/dist/packem_shared/Cell-DCg1kJY-.js +48 -0
- package/dist/packem_shared/Code-DjQvPBD9.js +53 -0
- package/dist/packem_shared/ConfirmInput-85Y4kRQW.js +44 -0
- package/dist/packem_shared/ConsoleOverlay-DBNa4vtj.js +57 -0
- package/dist/packem_shared/ControlledScrollView-BlOaxcsN.js +286 -0
- package/dist/packem_shared/ControlledScrollView-DfAhcufF.js +5 -0
- package/dist/packem_shared/Cursor-DiW7YoSK.js +18 -0
- package/dist/packem_shared/CursorContext-JxRzlqAx.js +9 -0
- package/dist/packem_shared/DevTools-aMPIsaHx.js +61 -0
- package/dist/packem_shared/Dialog-DsSNAVgC.js +71 -0
- package/dist/packem_shared/DiffView-hqaw-2S6.js +329 -0
- package/dist/packem_shared/FilePicker-DNwFxRhq.js +254 -0
- package/dist/packem_shared/FocusContext-CWkYtgcm.js +26 -0
- package/dist/packem_shared/FocusContext-D5wFxSRz.js +153 -0
- package/dist/packem_shared/Fullscreen-DrElAE1o.js +11 -0
- package/dist/packem_shared/Gradient-Ql5P0GUd.js +136 -0
- package/dist/packem_shared/Help-6wanGG38.js +112 -0
- package/dist/packem_shared/IMECompositionBuffer-Dl3S0KnF.js +55 -0
- package/dist/packem_shared/InputParser-BKHpWfvN.js +156 -0
- package/dist/packem_shared/LayoutNode-Cjnsodiy.js +131 -0
- package/dist/packem_shared/Link-COcKYfGT.js +66 -0
- package/dist/packem_shared/Markdown-y1ISztof.js +212 -0
- package/dist/packem_shared/MouseProvider-Y9TSSEGl.js +136 -0
- package/dist/packem_shared/MultiSelect-ChoLUcDI.js +129 -0
- package/dist/packem_shared/NAMED_COLORS-a4QBvb5r.js +262 -0
- package/dist/packem_shared/Newline-DBtYEg8x.js +7 -0
- package/dist/packem_shared/OrderedList-Cp7pXr6m.js +26 -0
- package/dist/packem_shared/Paginator-D1AuD-kj.js +104 -0
- package/dist/packem_shared/ProgressBar-DOfpVagn.js +22 -0
- package/dist/packem_shared/Renderer-zZ5O3vxc.js +31 -0
- package/dist/packem_shared/ResizeObserverEntry-Br4seLeQ.js +102 -0
- package/dist/packem_shared/ScrollBar-EWAs2Uc7.js +106 -0
- package/dist/packem_shared/ScrollBarBox-DTNNlh7R.js +72 -0
- package/dist/packem_shared/ScrollList-DCeIFL8M.js +227 -0
- package/dist/packem_shared/ScrollView-v3MCNIyX.js +196 -0
- package/dist/packem_shared/SelectInput-BN2TMyxp.js +260 -0
- package/dist/packem_shared/SelectInputIndicator-DkRMoH_b.js +9 -0
- package/dist/packem_shared/SelectInputItem-BF9LQgKu.js +8 -0
- package/dist/packem_shared/Slider-BWD7xZX6.js +116 -0
- package/dist/packem_shared/Spacer-Bs4ER-HK.js +8 -0
- package/dist/packem_shared/Spinner-BuI-kN4p.js +1799 -0
- package/dist/packem_shared/Static-DpTd6Eed.js +22 -0
- package/dist/packem_shared/Static-xmD9giJj.js +18 -0
- package/dist/packem_shared/StaticRender-tYwH6QXl.js +33 -0
- package/dist/packem_shared/StatusMessage-BtSYxzwb.js +14 -0
- package/dist/packem_shared/StderrContext-Bj4Mf7v7.js +17 -0
- package/dist/packem_shared/StdinContext-Bq_GNJ3z.js +38 -0
- package/dist/packem_shared/StdoutContext-CgjWeCdO.js +17 -0
- package/dist/packem_shared/Stopwatch-DjtTCyHn.js +23 -0
- package/dist/packem_shared/Tab-C6r5q4hR.js +7 -0
- package/dist/packem_shared/Table-D-rSVlzb.js +82 -0
- package/dist/packem_shared/Tabs-hki-KRnx.js +153 -0
- package/dist/packem_shared/Text-DvAUdZcK.js +65 -0
- package/dist/packem_shared/TextInput-C79WEQ5U.js +137 -0
- package/dist/packem_shared/Textarea-Dj06R6Zd.js +272 -0
- package/dist/packem_shared/Timer-wi9zuh4n.js +22 -0
- package/dist/packem_shared/Transform-BHxY_dAM.js +14 -0
- package/dist/packem_shared/TreeNodeMap-CtJUvBnd.js +155 -0
- package/dist/packem_shared/TreeView-C2062dtj.js +148 -0
- package/dist/packem_shared/TuiApp-DfxOnXqi.js +120 -0
- package/dist/packem_shared/TuiContext-CqEjMyXd.js +415 -0
- package/dist/packem_shared/UnorderedList-DhnadWjX.js +33 -0
- package/dist/packem_shared/ansi-parser-0BdVTKho.js +41 -0
- package/dist/packem_shared/ansi-tokenizer-LHq2LUWA.js +307 -0
- package/dist/packem_shared/boxes-oi3WUbyR.js +92 -0
- package/dist/packem_shared/colorize-88_Vk8cn.js +48 -0
- package/dist/packem_shared/comparePoints-CGMDnd3_.js +287 -0
- package/dist/packem_shared/createInlineLoop-BxMmcq9D.js +93 -0
- package/dist/packem_shared/createLinkedScrollGroup-Djw4Ceo0.js +44 -0
- package/dist/packem_shared/dom-DvzhsAez.js +225 -0
- package/dist/packem_shared/format-time-BGmnDukX.js +12 -0
- package/dist/packem_shared/getPathToRoot-a1wbwxfL.js +4 -0
- package/dist/packem_shared/getScrollHeight-BubfU_df.js +63 -0
- package/dist/packem_shared/input-utils-ViAEXa0Z.js +19 -0
- package/dist/packem_shared/isIntersecting-fEXHJN5R.js +10 -0
- package/dist/packem_shared/isOsc52Supported-G0k4sXJx.js +36 -0
- package/dist/packem_shared/isTerminalPaletteQuerySupported-EeiwMKbr.js +93 -0
- package/dist/packem_shared/kittyFlags-bNNf_9kX.js +26 -0
- package/dist/packem_shared/measure-element-Reza_yfC.js +396 -0
- package/dist/packem_shared/measure-text-DItZYotK.js +1189 -0
- package/dist/packem_shared/measureElement-CTgFCmKd.js +4 -0
- package/dist/packem_shared/mouse-context-BUHWKEIe.js +6 -0
- package/dist/packem_shared/parseSgrMouse-BHVBPP9G.js +1 -0
- package/dist/packem_shared/processLayout-BQ9kXfd3.js +2 -0
- package/dist/packem_shared/reconciler-BXf6miSS.js +211 -0
- package/dist/packem_shared/reconciler-gfmqURLy.js +680 -0
- package/dist/packem_shared/render-BAwdjfki.js +2806 -0
- package/dist/packem_shared/render-Bpjhf0lD.js +195 -0
- package/dist/packem_shared/renderToString-Cfg55DRD.js +62 -0
- package/dist/packem_shared/renderToString-ClIaXgrC.js +86 -0
- package/dist/packem_shared/renderTreeToBuffer-D3mo7M7m.js +308 -0
- package/dist/packem_shared/renderer-B3wROkeg.js +1431 -0
- package/dist/packem_shared/setEnableStyledLineCache-BpskngSJ.js +2 -0
- package/dist/packem_shared/squashTextNodesWithMap-iqm6OMMT.js +100 -0
- package/dist/packem_shared/text-width-DhuarWcB.js +42 -0
- package/dist/packem_shared/token-to-elements-BRFl_rzw.js +249 -0
- package/dist/packem_shared/treeViewTheme-BpSw9TMf.js +52 -0
- package/dist/packem_shared/useAnimation-kj31sA-T.js +62 -0
- package/dist/packem_shared/useApp-DPQlRzi5.js +6 -0
- package/dist/packem_shared/useBoxMetrics-rBjKc-g4.js +54 -0
- package/dist/packem_shared/useClipboard-B_9-adw1.js +23 -0
- package/dist/packem_shared/useColorBlindness-D_sTIhcb.js +30 -0
- package/dist/packem_shared/useConsoleCapture-Dvt7G1W1.js +61 -0
- package/dist/packem_shared/useCursor-BIJzc8k9.js +19 -0
- package/dist/packem_shared/useElementDimensions-CAoKitVD.js +67 -0
- package/dist/packem_shared/useFocus-CNl5QHHf.js +37 -0
- package/dist/packem_shared/useFocusManager-BPYaUuKQ.js +16 -0
- package/dist/packem_shared/useInput-Cfp5zB2s.js +594 -0
- package/dist/packem_shared/useIsScreenReaderEnabled-CnGKCe0f.js +9 -0
- package/dist/packem_shared/useKeyBindings-B78l1E1n.js +66 -0
- package/dist/packem_shared/useMouseAction-C5gZ2nj7.js +29 -0
- package/dist/packem_shared/useMouseContext-D-rFy60Q.js +12 -0
- package/dist/packem_shared/useMousePosition-BHBJ-kBk.js +25 -0
- package/dist/packem_shared/useOnMouseClick--ZIyBOBO.js +35 -0
- package/dist/packem_shared/useOnMouseHover-26diuXUC.js +32 -0
- package/dist/packem_shared/useOnMouseState-NO_Kda_C.js +13 -0
- package/dist/packem_shared/usePaste-Ct8J4AGR.js +35 -0
- package/dist/packem_shared/useScrollAcceleration-R9LfrPVG.js +73 -0
- package/dist/packem_shared/useScrollInput-D3CpBq_a.js +72 -0
- package/dist/packem_shared/useStderr-CAOVUh4E.js +6 -0
- package/dist/packem_shared/useStdin-X-O0kd-n.js +7 -0
- package/dist/packem_shared/useStdout-DyF6DSH0.js +6 -0
- package/dist/packem_shared/useStopwatch-qC4Beai4.js +33 -0
- package/dist/packem_shared/useTerminalPalette-BaWO2c4Q.js +38 -0
- package/dist/packem_shared/useTextBuffer-C8fEe9Ly.js +398 -0
- package/dist/packem_shared/useTextSelection-mXtxgsPK.js +50 -0
- package/dist/packem_shared/useTimer-CPQ7j827.js +46 -0
- package/dist/packem_shared/useTreeView-BT57P3Kx.js +101 -0
- package/dist/packem_shared/useTreeViewState-BpS_KZ-K.js +502 -0
- package/dist/packem_shared/useWindowSize-ugEmGZJm.js +20 -0
- package/dist/packem_shared/utils-BgdlrbOH.js +140 -0
- package/dist/packem_shared/variant-config-DSZoX5TM.js +8 -0
- package/dist/packem_shared/wrapOrTruncateStyledLine-DN3Nogoc.js +147 -0
- package/dist/react/devtools.d.ts +27 -0
- package/dist/react/focus.d.ts +39 -0
- package/dist/react/hooks.d.ts +238 -0
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.js +9 -0
- package/dist/react/layout.d.ts +35 -0
- package/dist/react/react.d.ts +57 -0
- package/dist/react/reconciler.d.ts +4 -0
- package/dist/react/render-to-string.d.ts +21 -0
- package/dist/react/renderer.d.ts +2 -0
- package/dist/react/scene.d.ts +3 -0
- package/dist/react/static.d.ts +39 -0
- package/dist/react/styles.d.ts +83 -0
- package/dist/react/text-width.d.ts +20 -0
- package/dist/testing/index.d.ts +144 -0
- package/dist/testing/index.js +260 -0
- package/dist/testing/keys.d.ts +89 -0
- package/dist/testing/screen.d.ts +35 -0
- package/dist/testing/wait-for.d.ts +21 -0
- package/index.js +585 -0
- package/package.json +117 -7
|
@@ -0,0 +1,1189 @@
|
|
|
1
|
+
import { isFullwidthCodePoint, getStringWidth } from '@visulima/string';
|
|
2
|
+
import { t as tokenizeAnsi } from './ansi-tokenizer-LHq2LUWA.js';
|
|
3
|
+
|
|
4
|
+
class DataLimitedLruMap {
|
|
5
|
+
map;
|
|
6
|
+
maxDataSize;
|
|
7
|
+
maxKeys;
|
|
8
|
+
currentDataSize = 0;
|
|
9
|
+
constructor(maxKeys, maxDataSize) {
|
|
10
|
+
this.map = /* @__PURE__ */ new Map();
|
|
11
|
+
this.maxKeys = maxKeys;
|
|
12
|
+
this.maxDataSize = maxDataSize;
|
|
13
|
+
}
|
|
14
|
+
get size() {
|
|
15
|
+
return this.map.size;
|
|
16
|
+
}
|
|
17
|
+
clear() {
|
|
18
|
+
this.map.clear();
|
|
19
|
+
this.currentDataSize = 0;
|
|
20
|
+
}
|
|
21
|
+
get(key) {
|
|
22
|
+
if (!this.map.has(key)) {
|
|
23
|
+
return void 0;
|
|
24
|
+
}
|
|
25
|
+
const value = this.map.get(key);
|
|
26
|
+
this.map.delete(key);
|
|
27
|
+
this.map.set(key, value);
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
set(key, value) {
|
|
31
|
+
const size = key.length;
|
|
32
|
+
if (size > this.maxDataSize) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const hasKey = this.map.has(key);
|
|
36
|
+
if (hasKey) {
|
|
37
|
+
this.map.delete(key);
|
|
38
|
+
this.currentDataSize -= size;
|
|
39
|
+
}
|
|
40
|
+
while (this.currentDataSize + size > this.maxDataSize && this.map.size > 0) {
|
|
41
|
+
const lruKey = this.map.keys().next().value;
|
|
42
|
+
if (lruKey === void 0) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
this.map.delete(lruKey);
|
|
46
|
+
this.currentDataSize -= lruKey.length;
|
|
47
|
+
}
|
|
48
|
+
while (this.map.size >= this.maxKeys) {
|
|
49
|
+
const lruKey = this.map.keys().next().value;
|
|
50
|
+
if (lruKey === void 0) {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
this.map.delete(lruKey);
|
|
54
|
+
this.currentDataSize -= lruKey.length;
|
|
55
|
+
}
|
|
56
|
+
this.map.set(key, value);
|
|
57
|
+
this.currentDataSize += size;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const BOLD_MASK = 1;
|
|
62
|
+
const DIM_MASK = 1 << 1;
|
|
63
|
+
const ITALIC_MASK = 1 << 2;
|
|
64
|
+
const UNDERLINE_MASK = 1 << 3;
|
|
65
|
+
const STRIKETHROUGH_MASK = 1 << 4;
|
|
66
|
+
const INVERSE_MASK = 1 << 5;
|
|
67
|
+
const HIDDEN_MASK = 1 << 6;
|
|
68
|
+
const FULL_WIDTH_MASK = 1 << 7;
|
|
69
|
+
|
|
70
|
+
const OFFSET_MASK = 1073741823;
|
|
71
|
+
const FULL_WIDTH_FLAG = 1073741824;
|
|
72
|
+
class StyledLine {
|
|
73
|
+
length = 0;
|
|
74
|
+
static emptyCache = /* @__PURE__ */ new Map();
|
|
75
|
+
text;
|
|
76
|
+
charData;
|
|
77
|
+
spans;
|
|
78
|
+
_cachedTrimmedLength;
|
|
79
|
+
static empty(length) {
|
|
80
|
+
if (length <= 0) {
|
|
81
|
+
return new StyledLine();
|
|
82
|
+
}
|
|
83
|
+
const cached = StyledLine.emptyCache.get(length);
|
|
84
|
+
if (cached) {
|
|
85
|
+
return cached.clone();
|
|
86
|
+
}
|
|
87
|
+
const line = new StyledLine();
|
|
88
|
+
line.length = length;
|
|
89
|
+
line.text = " ".repeat(length);
|
|
90
|
+
line.charData = Array.from({ length });
|
|
91
|
+
for (let i = 0; i < length; i++) {
|
|
92
|
+
line.charData[i] = i;
|
|
93
|
+
}
|
|
94
|
+
line.spans = [{ formatFlags: 0, length }];
|
|
95
|
+
line._cachedTrimmedLength = 0;
|
|
96
|
+
Object.freeze(line.spans[0]);
|
|
97
|
+
Object.freeze(line.spans);
|
|
98
|
+
Object.freeze(line);
|
|
99
|
+
StyledLine.emptyCache.set(length, line);
|
|
100
|
+
return line.clone();
|
|
101
|
+
}
|
|
102
|
+
getValue(index) {
|
|
103
|
+
if (this.text === void 0 || index < 0 || index >= this.length) {
|
|
104
|
+
return "";
|
|
105
|
+
}
|
|
106
|
+
const start = this.charData[index] & OFFSET_MASK;
|
|
107
|
+
const end = index + 1 < this.length ? this.charData[index + 1] & OFFSET_MASK : this.text.length;
|
|
108
|
+
return this.text.slice(start, end);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get the raw text for a range of characters as a single string slice.
|
|
112
|
+
* Much faster than calling getValue() per character.
|
|
113
|
+
*/
|
|
114
|
+
getTextRange(start, end) {
|
|
115
|
+
if (this.text === void 0 || start < 0 || end > this.length || start >= end) {
|
|
116
|
+
return "";
|
|
117
|
+
}
|
|
118
|
+
const textStart = this.charData[start] & OFFSET_MASK;
|
|
119
|
+
const textEnd = end < this.length ? this.charData[end] & OFFSET_MASK : this.text.length;
|
|
120
|
+
return this.text.slice(textStart, textEnd);
|
|
121
|
+
}
|
|
122
|
+
getSpan(index) {
|
|
123
|
+
if (this.spans === void 0 || index < 0 || index >= this.length) {
|
|
124
|
+
return void 0;
|
|
125
|
+
}
|
|
126
|
+
let current = 0;
|
|
127
|
+
for (const span of this.spans) {
|
|
128
|
+
if (index < current + span.length) {
|
|
129
|
+
return span;
|
|
130
|
+
}
|
|
131
|
+
current += span.length;
|
|
132
|
+
}
|
|
133
|
+
return void 0;
|
|
134
|
+
}
|
|
135
|
+
getFullWidth(index) {
|
|
136
|
+
if (this.charData === void 0 || index < 0 || index >= this.length) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
return (this.charData[index] & FULL_WIDTH_FLAG) !== 0;
|
|
140
|
+
}
|
|
141
|
+
hasStyles(index) {
|
|
142
|
+
const span = this.getSpan(index);
|
|
143
|
+
if (!span) {
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
return (span.formatFlags & ~FULL_WIDTH_MASK) !== 0 || span.fgColor !== void 0 || span.bgColor !== void 0 || span.link !== void 0;
|
|
147
|
+
}
|
|
148
|
+
getFormatFlags(index) {
|
|
149
|
+
let flags = this.getSpan(index)?.formatFlags ?? 0;
|
|
150
|
+
if (this.getFullWidth(index)) {
|
|
151
|
+
flags |= FULL_WIDTH_MASK;
|
|
152
|
+
}
|
|
153
|
+
return flags;
|
|
154
|
+
}
|
|
155
|
+
getFgColor(index) {
|
|
156
|
+
return this.getSpan(index)?.fgColor;
|
|
157
|
+
}
|
|
158
|
+
getBgColor(index) {
|
|
159
|
+
return this.getSpan(index)?.bgColor;
|
|
160
|
+
}
|
|
161
|
+
getLink(index) {
|
|
162
|
+
return this.getSpan(index)?.link;
|
|
163
|
+
}
|
|
164
|
+
setInverted(index, inverted) {
|
|
165
|
+
this._cachedTrimmedLength = void 0;
|
|
166
|
+
this.updateSpanAt(index, (span) => {
|
|
167
|
+
if (inverted) {
|
|
168
|
+
span.formatFlags |= INVERSE_MASK;
|
|
169
|
+
} else {
|
|
170
|
+
span.formatFlags &= ~INVERSE_MASK;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
setBackgroundColor(index, color) {
|
|
175
|
+
this._cachedTrimmedLength = void 0;
|
|
176
|
+
this.updateSpanAt(index, (span) => {
|
|
177
|
+
span.bgColor = color;
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
setForegroundColor(index, color) {
|
|
181
|
+
this._cachedTrimmedLength = void 0;
|
|
182
|
+
this.updateSpanAt(index, (span) => {
|
|
183
|
+
span.fgColor = color;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
setChar(index, value, formatFlags, fgColor, bgColor, link) {
|
|
187
|
+
if (index < 0 || index >= this.length) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
this._cachedTrimmedLength = void 0;
|
|
191
|
+
this.ensureInitialized();
|
|
192
|
+
const isFullWidth = (formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
193
|
+
const cleanFormatFlags = formatFlags & ~FULL_WIDTH_MASK;
|
|
194
|
+
const start = this.charData[index] & OFFSET_MASK;
|
|
195
|
+
const end = index + 1 < this.length ? this.charData[index + 1] & OFFSET_MASK : this.text.length;
|
|
196
|
+
const oldLength = end - start;
|
|
197
|
+
const newLength = value.length;
|
|
198
|
+
this.text = this.text.slice(0, start) + value + this.text.slice(end);
|
|
199
|
+
if (oldLength !== newLength) {
|
|
200
|
+
const diff = newLength - oldLength;
|
|
201
|
+
for (let i = index + 1; i < this.length; i++) {
|
|
202
|
+
const data = this.charData[i];
|
|
203
|
+
const oldOffset = data & OFFSET_MASK;
|
|
204
|
+
const fw = data & FULL_WIDTH_FLAG;
|
|
205
|
+
this.charData[i] = oldOffset + diff | fw;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
this.charData[index] = start | (isFullWidth ? FULL_WIDTH_FLAG : 0);
|
|
209
|
+
this.splitSpansAt(index);
|
|
210
|
+
this.splitSpansAt(index + 1);
|
|
211
|
+
let current = 0;
|
|
212
|
+
for (let i = 0; i < this.spans.length; i++) {
|
|
213
|
+
const span = this.spans[i];
|
|
214
|
+
if (current === index && span.length === 1) {
|
|
215
|
+
this.spans[i] = {
|
|
216
|
+
bgColor,
|
|
217
|
+
fgColor,
|
|
218
|
+
formatFlags: cleanFormatFlags,
|
|
219
|
+
length: 1,
|
|
220
|
+
link
|
|
221
|
+
};
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
current += span.length;
|
|
225
|
+
}
|
|
226
|
+
this.mergeSpans();
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Optimized setChar for same-length single-byte replacement.
|
|
230
|
+
* Skips string rebuild and offset adjustment when old and new values
|
|
231
|
+
* have the same byte length (the common case for ASCII overwrites on empty lines).
|
|
232
|
+
*/
|
|
233
|
+
setCharFast(index, value, formatFlags, fgColor, bgColor, link) {
|
|
234
|
+
if (index < 0 || index >= this.length) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
this._cachedTrimmedLength = void 0;
|
|
238
|
+
this.ensureInitialized();
|
|
239
|
+
const isFullWidth = (formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
240
|
+
const cleanFormatFlags = formatFlags & ~FULL_WIDTH_MASK;
|
|
241
|
+
const start = this.charData[index] & OFFSET_MASK;
|
|
242
|
+
const end = index + 1 < this.length ? this.charData[index + 1] & OFFSET_MASK : this.text.length;
|
|
243
|
+
const oldLength = end - start;
|
|
244
|
+
if (value.length === oldLength) {
|
|
245
|
+
if (value !== this.text.slice(start, end)) {
|
|
246
|
+
this.text = this.text.slice(0, start) + value + this.text.slice(end);
|
|
247
|
+
}
|
|
248
|
+
this.charData[index] = start | (isFullWidth ? FULL_WIDTH_FLAG : 0);
|
|
249
|
+
} else {
|
|
250
|
+
this.text = this.text.slice(0, start) + value + this.text.slice(end);
|
|
251
|
+
if (oldLength !== value.length) {
|
|
252
|
+
const diff = value.length - oldLength;
|
|
253
|
+
for (let i = index + 1; i < this.length; i++) {
|
|
254
|
+
const data = this.charData[i];
|
|
255
|
+
this.charData[i] = (data & OFFSET_MASK) + diff | data & FULL_WIDTH_FLAG;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
this.charData[index] = start | (isFullWidth ? FULL_WIDTH_FLAG : 0);
|
|
259
|
+
}
|
|
260
|
+
const existingSpan = this.getSpan(index);
|
|
261
|
+
if (existingSpan?.formatFlags === cleanFormatFlags && existingSpan.fgColor === fgColor && existingSpan.bgColor === bgColor && existingSpan.link === link) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
this.splitSpansAt(index);
|
|
265
|
+
this.splitSpansAt(index + 1);
|
|
266
|
+
let current = 0;
|
|
267
|
+
for (let i = 0; i < this.spans.length; i++) {
|
|
268
|
+
const span = this.spans[i];
|
|
269
|
+
if (current === index && span.length === 1) {
|
|
270
|
+
this.spans[i] = {
|
|
271
|
+
bgColor,
|
|
272
|
+
fgColor,
|
|
273
|
+
formatFlags: cleanFormatFlags,
|
|
274
|
+
length: 1,
|
|
275
|
+
link
|
|
276
|
+
};
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
current += span.length;
|
|
280
|
+
}
|
|
281
|
+
this.mergeSpans();
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Overwrite a range of this line with content from a source StyledLine.
|
|
285
|
+
* More efficient than calling setChar() per character because it does
|
|
286
|
+
* a single span split + rebuild instead of per-character span manipulation.
|
|
287
|
+
* @param destinationStart — start index in this line
|
|
288
|
+
* @param source — the StyledLine to copy from
|
|
289
|
+
* @param srcStart — start index in source (default 0)
|
|
290
|
+
* @param count — number of characters to copy (default: source.length)
|
|
291
|
+
*/
|
|
292
|
+
writeFrom(destinationStart, source, srcStart = 0, count) {
|
|
293
|
+
const n = count ?? source.length - srcStart;
|
|
294
|
+
if (n <= 0 || destinationStart >= this.length) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
this._cachedTrimmedLength = void 0;
|
|
298
|
+
this.ensureInitialized();
|
|
299
|
+
const actualCount = Math.min(n, this.length - destinationStart, source.length - srcStart);
|
|
300
|
+
const destinationTextStart = this.charData[destinationStart] & OFFSET_MASK;
|
|
301
|
+
const destinationTextEnd = destinationStart + actualCount < this.length ? this.charData[destinationStart + actualCount] & OFFSET_MASK : this.text.length;
|
|
302
|
+
let newSegment = "";
|
|
303
|
+
for (let i = 0; i < actualCount; i++) {
|
|
304
|
+
newSegment += source.getValue(srcStart + i);
|
|
305
|
+
}
|
|
306
|
+
const oldSegLength = destinationTextEnd - destinationTextStart;
|
|
307
|
+
const diff = newSegment.length - oldSegLength;
|
|
308
|
+
this.text = this.text.slice(0, destinationTextStart) + newSegment + this.text.slice(destinationTextEnd);
|
|
309
|
+
let offset = destinationTextStart;
|
|
310
|
+
for (let i = 0; i < actualCount; i++) {
|
|
311
|
+
const srcFullWidth = source.getFullWidth(srcStart + i);
|
|
312
|
+
this.charData[destinationStart + i] = offset | (srcFullWidth ? FULL_WIDTH_FLAG : 0);
|
|
313
|
+
offset += source.getValue(srcStart + i).length;
|
|
314
|
+
}
|
|
315
|
+
if (diff !== 0) {
|
|
316
|
+
for (let i = destinationStart + actualCount; i < this.length; i++) {
|
|
317
|
+
const data = this.charData[i];
|
|
318
|
+
this.charData[i] = (data & OFFSET_MASK) + diff | data & FULL_WIDTH_FLAG;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
this.splitSpansAt(destinationStart);
|
|
322
|
+
this.splitSpansAt(destinationStart + actualCount);
|
|
323
|
+
const newSpans = [];
|
|
324
|
+
let srcSpanStart = 0;
|
|
325
|
+
for (const span of source.getSpans()) {
|
|
326
|
+
const spanEnd = srcSpanStart + span.length;
|
|
327
|
+
const overlapStart = Math.max(srcStart, srcSpanStart);
|
|
328
|
+
const overlapEnd = Math.min(srcStart + actualCount, spanEnd);
|
|
329
|
+
if (overlapStart < overlapEnd) {
|
|
330
|
+
newSpans.push({ ...span, length: overlapEnd - overlapStart });
|
|
331
|
+
}
|
|
332
|
+
srcSpanStart = spanEnd;
|
|
333
|
+
if (srcSpanStart >= srcStart + actualCount) {
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
let destinationSpanIndex = 0;
|
|
338
|
+
let destinationSpanOffset = 0;
|
|
339
|
+
for (let i = 0; i < this.spans.length; i++) {
|
|
340
|
+
if (destinationSpanOffset === destinationStart) {
|
|
341
|
+
destinationSpanIndex = i;
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
destinationSpanOffset += this.spans[i].length;
|
|
345
|
+
}
|
|
346
|
+
let removeCount = 0;
|
|
347
|
+
let covered = 0;
|
|
348
|
+
for (let i = destinationSpanIndex; i < this.spans.length && covered < actualCount; i++) {
|
|
349
|
+
covered += this.spans[i].length;
|
|
350
|
+
removeCount++;
|
|
351
|
+
}
|
|
352
|
+
this.spans.splice(destinationSpanIndex, removeCount, ...newSpans);
|
|
353
|
+
this.mergeSpans();
|
|
354
|
+
}
|
|
355
|
+
pushChar(value, formatFlags, fgColor, bgColor, link) {
|
|
356
|
+
this._cachedTrimmedLength = void 0;
|
|
357
|
+
this.ensureInitialized();
|
|
358
|
+
const isFullWidth = (formatFlags & FULL_WIDTH_MASK) !== 0;
|
|
359
|
+
const cleanFormatFlags = formatFlags & ~FULL_WIDTH_MASK;
|
|
360
|
+
const offset = this.text.length;
|
|
361
|
+
this.text = (this.text ?? "") + value;
|
|
362
|
+
this.charData.push(offset | (isFullWidth ? FULL_WIDTH_FLAG : 0));
|
|
363
|
+
const lastSpan = this.spans.at(-1);
|
|
364
|
+
if (lastSpan?.formatFlags === cleanFormatFlags && lastSpan.fgColor === fgColor && lastSpan.bgColor === bgColor && lastSpan.link === link) {
|
|
365
|
+
lastSpan.length++;
|
|
366
|
+
} else {
|
|
367
|
+
this.spans.push({
|
|
368
|
+
bgColor,
|
|
369
|
+
fgColor,
|
|
370
|
+
formatFlags: cleanFormatFlags,
|
|
371
|
+
length: 1,
|
|
372
|
+
link
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
this.length++;
|
|
376
|
+
}
|
|
377
|
+
clone() {
|
|
378
|
+
if (this.charData === void 0) {
|
|
379
|
+
return new StyledLine();
|
|
380
|
+
}
|
|
381
|
+
const result = new StyledLine();
|
|
382
|
+
result.length = this.length;
|
|
383
|
+
result.text = this.text;
|
|
384
|
+
result.charData = [...this.charData];
|
|
385
|
+
result.spans = this.spans.map((span) => {
|
|
386
|
+
return {
|
|
387
|
+
...span
|
|
388
|
+
};
|
|
389
|
+
});
|
|
390
|
+
result._cachedTrimmedLength = this._cachedTrimmedLength;
|
|
391
|
+
return result;
|
|
392
|
+
}
|
|
393
|
+
slice(start, end) {
|
|
394
|
+
if (this.charData === void 0) {
|
|
395
|
+
return new StyledLine();
|
|
396
|
+
}
|
|
397
|
+
const actualStart = Math.max(0, start);
|
|
398
|
+
const actualEnd = end === void 0 ? this.length : Math.min(this.length, end);
|
|
399
|
+
if (actualStart >= actualEnd) {
|
|
400
|
+
return new StyledLine();
|
|
401
|
+
}
|
|
402
|
+
if (actualStart === 0 && actualEnd === this.length) {
|
|
403
|
+
return this.clone();
|
|
404
|
+
}
|
|
405
|
+
const result = new StyledLine();
|
|
406
|
+
result.length = actualEnd - actualStart;
|
|
407
|
+
result.charData = Array.from({ length: result.length });
|
|
408
|
+
const textStart = this.charData[actualStart] & OFFSET_MASK;
|
|
409
|
+
const textEnd = actualEnd < this.length ? this.charData[actualEnd] & OFFSET_MASK : this.text.length;
|
|
410
|
+
result.text = this.text.slice(textStart, textEnd);
|
|
411
|
+
for (let i = 0; i < result.length; i++) {
|
|
412
|
+
const oldData = this.charData[actualStart + i];
|
|
413
|
+
const oldOffset = oldData & OFFSET_MASK;
|
|
414
|
+
const fw = oldData & FULL_WIDTH_FLAG;
|
|
415
|
+
result.charData[i] = oldOffset - textStart | fw;
|
|
416
|
+
}
|
|
417
|
+
const newSpans = [];
|
|
418
|
+
let current = 0;
|
|
419
|
+
for (const span of this.spans) {
|
|
420
|
+
const spanStart = current;
|
|
421
|
+
const spanEnd = current + span.length;
|
|
422
|
+
const intersectStart = Math.max(actualStart, spanStart);
|
|
423
|
+
const intersectEnd = Math.min(actualEnd, spanEnd);
|
|
424
|
+
if (intersectStart < intersectEnd) {
|
|
425
|
+
newSpans.push({
|
|
426
|
+
...span,
|
|
427
|
+
length: intersectEnd - intersectStart
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
current += span.length;
|
|
431
|
+
if (current >= actualEnd) {
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
result.spans = newSpans;
|
|
436
|
+
result.mergeSpans();
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
combine(...others) {
|
|
440
|
+
if (others.length === 0) {
|
|
441
|
+
return this.clone();
|
|
442
|
+
}
|
|
443
|
+
const allLines = [this, ...others].filter((l) => l.length > 0);
|
|
444
|
+
if (allLines.length === 0) {
|
|
445
|
+
return new StyledLine();
|
|
446
|
+
}
|
|
447
|
+
if (allLines.length === 1) {
|
|
448
|
+
return allLines[0].clone();
|
|
449
|
+
}
|
|
450
|
+
let totalChars = 0;
|
|
451
|
+
for (const line of allLines) {
|
|
452
|
+
totalChars += line.length;
|
|
453
|
+
}
|
|
454
|
+
const result = new StyledLine();
|
|
455
|
+
result.length = totalChars;
|
|
456
|
+
result.text = allLines.map((l) => l.getText()).join("");
|
|
457
|
+
result.charData = Array.from({ length: totalChars });
|
|
458
|
+
let currentChar = 0;
|
|
459
|
+
let currentOffset = 0;
|
|
460
|
+
for (const line of allLines) {
|
|
461
|
+
const lineCharData = line.charData;
|
|
462
|
+
const lineText = line.getText();
|
|
463
|
+
if (lineCharData) {
|
|
464
|
+
for (let i = 0; i < line.length; i++) {
|
|
465
|
+
const data = lineCharData[i];
|
|
466
|
+
const lineOffset = data & OFFSET_MASK;
|
|
467
|
+
const fw = data & FULL_WIDTH_FLAG;
|
|
468
|
+
result.charData[currentChar + i] = currentOffset + lineOffset | fw;
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
for (let i = 0; i < line.length; i++) {
|
|
472
|
+
result.charData[currentChar + i] = currentOffset + i;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
currentChar += line.length;
|
|
476
|
+
currentOffset += lineText.length;
|
|
477
|
+
}
|
|
478
|
+
result.spans = allLines.flatMap((l) => l.getSpans().map((s) => {
|
|
479
|
+
return {
|
|
480
|
+
...s
|
|
481
|
+
};
|
|
482
|
+
}));
|
|
483
|
+
result.mergeSpans();
|
|
484
|
+
return result;
|
|
485
|
+
}
|
|
486
|
+
getTrimmedLength() {
|
|
487
|
+
if (this._cachedTrimmedLength !== void 0) {
|
|
488
|
+
return this._cachedTrimmedLength;
|
|
489
|
+
}
|
|
490
|
+
if (this.length === 0) {
|
|
491
|
+
this._cachedTrimmedLength = 0;
|
|
492
|
+
return 0;
|
|
493
|
+
}
|
|
494
|
+
if (this.text === void 0 || this.charData === void 0) {
|
|
495
|
+
this._cachedTrimmedLength = 0;
|
|
496
|
+
return 0;
|
|
497
|
+
}
|
|
498
|
+
let currentIndex = this.length - 1;
|
|
499
|
+
if (this.spans) {
|
|
500
|
+
for (let s = this.spans.length - 1; s >= 0; s--) {
|
|
501
|
+
const span = this.spans[s];
|
|
502
|
+
const hasStylesOnSpan = (span.formatFlags & ~FULL_WIDTH_MASK) !== 0 || span.fgColor !== void 0 || span.bgColor !== void 0 || span.link !== void 0;
|
|
503
|
+
if (hasStylesOnSpan) {
|
|
504
|
+
this._cachedTrimmedLength = currentIndex + 1;
|
|
505
|
+
return this._cachedTrimmedLength;
|
|
506
|
+
}
|
|
507
|
+
for (let i = 0; i < span.length; i++) {
|
|
508
|
+
const charStart = this.charData[currentIndex] & OFFSET_MASK;
|
|
509
|
+
const charEnd = currentIndex + 1 < this.length ? this.charData[currentIndex + 1] & OFFSET_MASK : this.text.length;
|
|
510
|
+
if (charEnd - charStart !== 1 || this.text[charStart] !== " ") {
|
|
511
|
+
this._cachedTrimmedLength = currentIndex + 1;
|
|
512
|
+
return this._cachedTrimmedLength;
|
|
513
|
+
}
|
|
514
|
+
currentIndex--;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
this._cachedTrimmedLength = 0;
|
|
519
|
+
return 0;
|
|
520
|
+
}
|
|
521
|
+
trimEnd() {
|
|
522
|
+
const trimmedLength = this.getTrimmedLength();
|
|
523
|
+
if (trimmedLength === this.length) {
|
|
524
|
+
return this;
|
|
525
|
+
}
|
|
526
|
+
if (trimmedLength === 0) {
|
|
527
|
+
return new StyledLine();
|
|
528
|
+
}
|
|
529
|
+
return this.slice(0, trimmedLength);
|
|
530
|
+
}
|
|
531
|
+
equals(other) {
|
|
532
|
+
if (this.length !== other.length) {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
if (this.length === 0) {
|
|
536
|
+
return true;
|
|
537
|
+
}
|
|
538
|
+
if (this.getText() !== other.getText()) {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
const s1 = this.getSpans();
|
|
542
|
+
const s2 = other.getSpans();
|
|
543
|
+
if (s1.length !== s2.length) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
for (const [i, element] of s1.entries()) {
|
|
547
|
+
const sp1 = element;
|
|
548
|
+
const sp2 = s2[i];
|
|
549
|
+
if (sp1.length !== sp2.length || sp1.formatFlags !== sp2.formatFlags || sp1.fgColor !== sp2.fgColor || sp1.bgColor !== sp2.bgColor || sp1.link !== sp2.link) {
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
const thisCharData = this.charData;
|
|
554
|
+
const otherCharData = other.charData;
|
|
555
|
+
if (thisCharData && otherCharData) {
|
|
556
|
+
for (let i = 0; i < this.length; i++) {
|
|
557
|
+
if (thisCharData[i] !== otherCharData[i]) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return true;
|
|
563
|
+
}
|
|
564
|
+
getText() {
|
|
565
|
+
return this.text ?? "";
|
|
566
|
+
}
|
|
567
|
+
getSpans() {
|
|
568
|
+
return this.spans ?? [];
|
|
569
|
+
}
|
|
570
|
+
getValues() {
|
|
571
|
+
return Array.from({ length: this.length }, (_, i) => this.getValue(i));
|
|
572
|
+
}
|
|
573
|
+
*[Symbol.iterator]() {
|
|
574
|
+
if (this.length === 0) {
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
577
|
+
let currentSpanIndex = 0;
|
|
578
|
+
let currentSpanPos = 0;
|
|
579
|
+
const spans = this.getSpans();
|
|
580
|
+
for (let i = 0; i < this.length; i++) {
|
|
581
|
+
const span = spans[currentSpanIndex];
|
|
582
|
+
const flags = span ? span.formatFlags : 0;
|
|
583
|
+
const isFullWidth = this.getFullWidth(i);
|
|
584
|
+
yield {
|
|
585
|
+
bgColor: span?.bgColor,
|
|
586
|
+
fgColor: span?.fgColor,
|
|
587
|
+
formatFlags: flags | (isFullWidth ? FULL_WIDTH_MASK : 0),
|
|
588
|
+
fullWidth: isFullWidth,
|
|
589
|
+
hasStyles: (flags & ~FULL_WIDTH_MASK) !== 0 || span?.fgColor !== void 0 || span?.bgColor !== void 0 || span?.link !== void 0,
|
|
590
|
+
link: span?.link,
|
|
591
|
+
value: this.getValue(i)
|
|
592
|
+
};
|
|
593
|
+
if (span) {
|
|
594
|
+
currentSpanPos++;
|
|
595
|
+
if (currentSpanPos >= span.length) {
|
|
596
|
+
currentSpanIndex++;
|
|
597
|
+
currentSpanPos = 0;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Split the span at `index` into a single-char span, apply the updater,
|
|
604
|
+
* then merge adjacent spans. Shared by setInverted/setBackgroundColor/setForegroundColor.
|
|
605
|
+
*/
|
|
606
|
+
updateSpanAt(index, updater) {
|
|
607
|
+
if (index < 0 || index >= this.length) {
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
this.ensureInitialized();
|
|
611
|
+
this.splitSpansAt(index);
|
|
612
|
+
this.splitSpansAt(index + 1);
|
|
613
|
+
let current = 0;
|
|
614
|
+
for (const span of this.spans) {
|
|
615
|
+
if (current === index && span.length === 1) {
|
|
616
|
+
updater(span);
|
|
617
|
+
break;
|
|
618
|
+
}
|
|
619
|
+
current += span.length;
|
|
620
|
+
}
|
|
621
|
+
this.mergeSpans();
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Grow the line to at least `minWidth` columns, filling new cells with
|
|
625
|
+
* empty strings (zero-width placeholders). This matches the behavior of
|
|
626
|
+
* sparse JS arrays in the original ink Output where out-of-bounds writes
|
|
627
|
+
* created gaps that produced no visible output.
|
|
628
|
+
*/
|
|
629
|
+
ensureWidth(minWidth) {
|
|
630
|
+
if (minWidth <= this.length) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
this.ensureInitialized();
|
|
634
|
+
const oldLength = this.length;
|
|
635
|
+
const extraCount = minWidth - oldLength;
|
|
636
|
+
const oldTextLength = this.text.length;
|
|
637
|
+
for (let i = 0; i < extraCount; i++) {
|
|
638
|
+
this.charData.push(oldTextLength);
|
|
639
|
+
}
|
|
640
|
+
this.length = minWidth;
|
|
641
|
+
const lastSpan = this.spans.at(-1);
|
|
642
|
+
if (lastSpan?.formatFlags === 0 && lastSpan.fgColor === void 0 && lastSpan.bgColor === void 0 && lastSpan.link === void 0) {
|
|
643
|
+
lastSpan.length += extraCount;
|
|
644
|
+
} else {
|
|
645
|
+
this.spans.push({ formatFlags: 0, length: extraCount });
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
ensureInitialized() {
|
|
649
|
+
if (this.charData === void 0) {
|
|
650
|
+
this.text = "";
|
|
651
|
+
this.charData = Array.from({ length: this.length });
|
|
652
|
+
this.spans = this.length > 0 ? [{ formatFlags: 0, length: this.length }] : [];
|
|
653
|
+
if (this.length > 0 && this.text.length === 0) {
|
|
654
|
+
this.text = " ".repeat(this.length);
|
|
655
|
+
for (let i = 0; i < this.length; i++) {
|
|
656
|
+
this.charData[i] = i;
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
splitSpansAt(index) {
|
|
662
|
+
if (this.spans === void 0 || index <= 0 || index >= this.length) {
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
let current = 0;
|
|
666
|
+
for (let i = 0; i < this.spans.length; i++) {
|
|
667
|
+
const span = this.spans[i];
|
|
668
|
+
if (index > current && index < current + span.length) {
|
|
669
|
+
const leftLength = index - current;
|
|
670
|
+
const rightLength = span.length - leftLength;
|
|
671
|
+
this.spans.splice(i, 1, { ...span, length: leftLength }, { ...span, length: rightLength });
|
|
672
|
+
return;
|
|
673
|
+
}
|
|
674
|
+
current += span.length;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
mergeSpans() {
|
|
678
|
+
if (this.spans === void 0) {
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
const newSpans = [];
|
|
682
|
+
for (const span of this.spans) {
|
|
683
|
+
if (span.length === 0) {
|
|
684
|
+
continue;
|
|
685
|
+
}
|
|
686
|
+
const last = newSpans.at(-1);
|
|
687
|
+
if (last?.formatFlags === span.formatFlags && last.fgColor === span.fgColor && last.bgColor === span.bgColor && last.link === span.link) {
|
|
688
|
+
last.length += span.length;
|
|
689
|
+
} else {
|
|
690
|
+
newSpans.push({ ...span });
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
this.spans = newSpans;
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const NAMED_COLORS = {
|
|
698
|
+
black: 0,
|
|
699
|
+
blue: 4,
|
|
700
|
+
cyan: 6,
|
|
701
|
+
gray: 8,
|
|
702
|
+
green: 2,
|
|
703
|
+
grey: 8,
|
|
704
|
+
magenta: 5,
|
|
705
|
+
red: 1,
|
|
706
|
+
white: 7,
|
|
707
|
+
yellow: 3
|
|
708
|
+
};
|
|
709
|
+
const BRIGHT_COLORS = {
|
|
710
|
+
blackBright: 8,
|
|
711
|
+
blueBright: 12,
|
|
712
|
+
cyanBright: 14,
|
|
713
|
+
greenBright: 10,
|
|
714
|
+
magentaBright: 13,
|
|
715
|
+
redBright: 9,
|
|
716
|
+
whiteBright: 15,
|
|
717
|
+
yellowBright: 11
|
|
718
|
+
};
|
|
719
|
+
const ansi256Regex = /^ansi256\(\s?(\d+)\s?\)$/;
|
|
720
|
+
const rgbRegex = /^rgb\(\s?(\d+),\s?(\d+),\s?(\d+)\s?\)$/;
|
|
721
|
+
const colorToAnsi256 = (color) => {
|
|
722
|
+
const named = NAMED_COLORS[color];
|
|
723
|
+
if (named !== void 0) {
|
|
724
|
+
return named;
|
|
725
|
+
}
|
|
726
|
+
const bright = BRIGHT_COLORS[color];
|
|
727
|
+
if (bright !== void 0) {
|
|
728
|
+
return bright;
|
|
729
|
+
}
|
|
730
|
+
const ansi256Match = ansi256Regex.exec(color);
|
|
731
|
+
if (ansi256Match) {
|
|
732
|
+
return Number(ansi256Match[1]) & 255;
|
|
733
|
+
}
|
|
734
|
+
if (color.startsWith("#") && color.length === 7) {
|
|
735
|
+
const r = Number.parseInt(color.slice(1, 3), 16);
|
|
736
|
+
const g = Number.parseInt(color.slice(3, 5), 16);
|
|
737
|
+
const b = Number.parseInt(color.slice(5, 7), 16);
|
|
738
|
+
return 16 + 36 * Math.round(r / 51) + 6 * Math.round(g / 51) + Math.round(b / 51);
|
|
739
|
+
}
|
|
740
|
+
const rgbMatch = rgbRegex.exec(color);
|
|
741
|
+
if (rgbMatch) {
|
|
742
|
+
return 16 + 36 * Math.round(Number(rgbMatch[1]) / 51) + 6 * Math.round(Number(rgbMatch[2]) / 51) + Math.round(Number(rgbMatch[3]) / 51);
|
|
743
|
+
}
|
|
744
|
+
return 255;
|
|
745
|
+
};
|
|
746
|
+
const colorToSgrParams = (color, isFg) => {
|
|
747
|
+
const base = isFg ? 30 : 40;
|
|
748
|
+
const named = NAMED_COLORS[color];
|
|
749
|
+
if (named !== void 0) {
|
|
750
|
+
return [base + named];
|
|
751
|
+
}
|
|
752
|
+
const bright = BRIGHT_COLORS[color];
|
|
753
|
+
if (bright !== void 0) {
|
|
754
|
+
return [base + 60 + (bright - 8)];
|
|
755
|
+
}
|
|
756
|
+
if (color.startsWith("#") && color.length === 7) {
|
|
757
|
+
const r = Number.parseInt(color.slice(1, 3), 16);
|
|
758
|
+
const g = Number.parseInt(color.slice(3, 5), 16);
|
|
759
|
+
const b = Number.parseInt(color.slice(5, 7), 16);
|
|
760
|
+
return [isFg ? 38 : 48, 2, r, g, b];
|
|
761
|
+
}
|
|
762
|
+
const ansi256Match = ansi256Regex.exec(color);
|
|
763
|
+
if (ansi256Match) {
|
|
764
|
+
return [isFg ? 38 : 48, 5, Number(ansi256Match[1])];
|
|
765
|
+
}
|
|
766
|
+
const rgbMatch = rgbRegex.exec(color);
|
|
767
|
+
if (rgbMatch) {
|
|
768
|
+
return [isFg ? 38 : 48, 2, Number(rgbMatch[1]), Number(rgbMatch[2]), Number(rgbMatch[3])];
|
|
769
|
+
}
|
|
770
|
+
return [];
|
|
771
|
+
};
|
|
772
|
+
const ansi256ToColorName = (index) => {
|
|
773
|
+
const standardNames = ["black", "red", "green", "yellow", "blue", "magenta", "cyan", "white"];
|
|
774
|
+
if (index >= 0 && index <= 7) {
|
|
775
|
+
return standardNames[index];
|
|
776
|
+
}
|
|
777
|
+
return `ansi256(${index})`;
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
const createSgrState = () => {
|
|
781
|
+
return {
|
|
782
|
+
bgColor: void 0,
|
|
783
|
+
fgColor: void 0,
|
|
784
|
+
formatFlags: 0,
|
|
785
|
+
link: void 0
|
|
786
|
+
};
|
|
787
|
+
};
|
|
788
|
+
const applySgrParams = (state, parameterString) => {
|
|
789
|
+
if (parameterString.length === 0) {
|
|
790
|
+
return createSgrState();
|
|
791
|
+
}
|
|
792
|
+
const normalizedParams = parameterString.includes(":") ? parameterString.replaceAll(":", ";") : parameterString;
|
|
793
|
+
const params = normalizedParams.split(";").filter((s) => s.length > 0).map(Number);
|
|
794
|
+
let { bgColor, fgColor, formatFlags, link } = state;
|
|
795
|
+
let index = 0;
|
|
796
|
+
while (index < params.length) {
|
|
797
|
+
const code = params[index];
|
|
798
|
+
switch (code) {
|
|
799
|
+
case 0: {
|
|
800
|
+
formatFlags = 0;
|
|
801
|
+
fgColor = void 0;
|
|
802
|
+
bgColor = void 0;
|
|
803
|
+
link = void 0;
|
|
804
|
+
break;
|
|
805
|
+
}
|
|
806
|
+
case 1: {
|
|
807
|
+
formatFlags |= BOLD_MASK;
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
case 2: {
|
|
811
|
+
formatFlags |= DIM_MASK;
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
case 3: {
|
|
815
|
+
formatFlags |= ITALIC_MASK;
|
|
816
|
+
break;
|
|
817
|
+
}
|
|
818
|
+
case 4: {
|
|
819
|
+
formatFlags |= UNDERLINE_MASK;
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
822
|
+
case 7: {
|
|
823
|
+
formatFlags |= INVERSE_MASK;
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
case 8: {
|
|
827
|
+
formatFlags |= HIDDEN_MASK;
|
|
828
|
+
break;
|
|
829
|
+
}
|
|
830
|
+
case 9: {
|
|
831
|
+
formatFlags |= STRIKETHROUGH_MASK;
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
// Reset individual attributes
|
|
835
|
+
case 22: {
|
|
836
|
+
formatFlags &= -4;
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
case 23: {
|
|
840
|
+
formatFlags &= ~ITALIC_MASK;
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
case 24: {
|
|
844
|
+
formatFlags &= ~UNDERLINE_MASK;
|
|
845
|
+
break;
|
|
846
|
+
}
|
|
847
|
+
case 27: {
|
|
848
|
+
formatFlags &= ~INVERSE_MASK;
|
|
849
|
+
break;
|
|
850
|
+
}
|
|
851
|
+
case 28: {
|
|
852
|
+
formatFlags &= ~HIDDEN_MASK;
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
case 29: {
|
|
856
|
+
formatFlags &= ~STRIKETHROUGH_MASK;
|
|
857
|
+
break;
|
|
858
|
+
}
|
|
859
|
+
// Standard foreground colors (30-37)
|
|
860
|
+
case 30:
|
|
861
|
+
case 31:
|
|
862
|
+
case 32:
|
|
863
|
+
case 33:
|
|
864
|
+
case 34:
|
|
865
|
+
case 35:
|
|
866
|
+
case 36:
|
|
867
|
+
case 37: {
|
|
868
|
+
fgColor = ansi256ToColorName(code - 30);
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
// Extended foreground: 256-color or RGB
|
|
872
|
+
case 38: {
|
|
873
|
+
if (params[index + 1] === 5 && params[index + 2] !== void 0) {
|
|
874
|
+
fgColor = ansi256ToColorName(params[index + 2]);
|
|
875
|
+
index += 2;
|
|
876
|
+
} else if (params[index + 1] === 2 && index + 4 < params.length) {
|
|
877
|
+
fgColor = `rgb(${params[index + 2]}, ${params[index + 3]}, ${params[index + 4]})`;
|
|
878
|
+
index += 4;
|
|
879
|
+
}
|
|
880
|
+
break;
|
|
881
|
+
}
|
|
882
|
+
// Default foreground
|
|
883
|
+
case 39: {
|
|
884
|
+
fgColor = void 0;
|
|
885
|
+
break;
|
|
886
|
+
}
|
|
887
|
+
// Standard background colors (40-47)
|
|
888
|
+
case 40:
|
|
889
|
+
case 41:
|
|
890
|
+
case 42:
|
|
891
|
+
case 43:
|
|
892
|
+
case 44:
|
|
893
|
+
case 45:
|
|
894
|
+
case 46:
|
|
895
|
+
case 47: {
|
|
896
|
+
bgColor = ansi256ToColorName(code - 40);
|
|
897
|
+
break;
|
|
898
|
+
}
|
|
899
|
+
// Extended background: 256-color or RGB
|
|
900
|
+
case 48: {
|
|
901
|
+
if (params[index + 1] === 5 && params[index + 2] !== void 0) {
|
|
902
|
+
bgColor = ansi256ToColorName(params[index + 2]);
|
|
903
|
+
index += 2;
|
|
904
|
+
} else if (params[index + 1] === 2 && index + 4 < params.length) {
|
|
905
|
+
bgColor = `rgb(${params[index + 2]}, ${params[index + 3]}, ${params[index + 4]})`;
|
|
906
|
+
index += 4;
|
|
907
|
+
}
|
|
908
|
+
break;
|
|
909
|
+
}
|
|
910
|
+
// Default background
|
|
911
|
+
case 49: {
|
|
912
|
+
bgColor = void 0;
|
|
913
|
+
break;
|
|
914
|
+
}
|
|
915
|
+
// Bright foreground (90-97)
|
|
916
|
+
case 90:
|
|
917
|
+
case 91:
|
|
918
|
+
case 92:
|
|
919
|
+
case 93:
|
|
920
|
+
case 94:
|
|
921
|
+
case 95:
|
|
922
|
+
case 96:
|
|
923
|
+
case 97: {
|
|
924
|
+
fgColor = `ansi256(${code - 90 + 8})`;
|
|
925
|
+
break;
|
|
926
|
+
}
|
|
927
|
+
// Bright background (100-107)
|
|
928
|
+
case 100:
|
|
929
|
+
case 101:
|
|
930
|
+
case 102:
|
|
931
|
+
case 103:
|
|
932
|
+
case 104:
|
|
933
|
+
case 105:
|
|
934
|
+
case 106:
|
|
935
|
+
case 107: {
|
|
936
|
+
bgColor = `ansi256(${code - 100 + 8})`;
|
|
937
|
+
break;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
index++;
|
|
941
|
+
}
|
|
942
|
+
return { bgColor, fgColor, formatFlags, link };
|
|
943
|
+
};
|
|
944
|
+
const REGIONAL_INDICATOR_START = 127462;
|
|
945
|
+
const REGIONAL_INDICATOR_END = 127487;
|
|
946
|
+
const SKIN_TONE_START = 127995;
|
|
947
|
+
const SKIN_TONE_END = 127999;
|
|
948
|
+
const ZWJ = 8205;
|
|
949
|
+
const TAGS_BLOCK_START = 917504;
|
|
950
|
+
const TAGS_BLOCK_END = 917631;
|
|
951
|
+
const unicodeMarkRegex = new RegExp("\\p{Mark}", "u");
|
|
952
|
+
const graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
953
|
+
const isFullwidthGrapheme = (grapheme, codePoint) => {
|
|
954
|
+
if (isFullwidthCodePoint(codePoint)) {
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
if (grapheme.includes("️")) {
|
|
958
|
+
return true;
|
|
959
|
+
}
|
|
960
|
+
if (codePoint >= REGIONAL_INDICATOR_START && codePoint <= REGIONAL_INDICATOR_END) {
|
|
961
|
+
return true;
|
|
962
|
+
}
|
|
963
|
+
return false;
|
|
964
|
+
};
|
|
965
|
+
const oscHyperlinkRegex = /(?:\u001B\]|\u009D)8;([^;]*);(.*?)(?:\u001B\\|\u0007|\u009C)/;
|
|
966
|
+
const parseOscHyperlink = (oscValue) => {
|
|
967
|
+
const match = oscHyperlinkRegex.exec(oscValue);
|
|
968
|
+
if (!match?.[2]) {
|
|
969
|
+
return void 0;
|
|
970
|
+
}
|
|
971
|
+
if (match[2].length === 0) {
|
|
972
|
+
return void 0;
|
|
973
|
+
}
|
|
974
|
+
const usesST = oscValue.endsWith("\x1B\\");
|
|
975
|
+
return usesST ? `ST:${match[2]}` : match[2];
|
|
976
|
+
};
|
|
977
|
+
const processTextToken = (text, line, state) => {
|
|
978
|
+
const segments = graphemeSegmenter.segment(text);
|
|
979
|
+
const graphemes = [];
|
|
980
|
+
for (const { segment } of segments) {
|
|
981
|
+
graphemes.push(segment);
|
|
982
|
+
}
|
|
983
|
+
for (let i = 0; i < graphemes.length; i++) {
|
|
984
|
+
let value = graphemes[i];
|
|
985
|
+
if (value === " ") {
|
|
986
|
+
for (let s = 0; s < 4; s++) {
|
|
987
|
+
line.pushChar(" ", state.formatFlags, state.fgColor, state.bgColor, state.link);
|
|
988
|
+
}
|
|
989
|
+
continue;
|
|
990
|
+
}
|
|
991
|
+
if (value === "\b") {
|
|
992
|
+
continue;
|
|
993
|
+
}
|
|
994
|
+
const firstCodePoint = value.codePointAt(0);
|
|
995
|
+
if (!firstCodePoint) {
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
if (firstCodePoint >= REGIONAL_INDICATOR_START && firstCodePoint <= REGIONAL_INDICATOR_END && i + 1 < graphemes.length) {
|
|
999
|
+
const nextGrapheme = graphemes[i + 1];
|
|
1000
|
+
const nextCodePoint = nextGrapheme.codePointAt(0);
|
|
1001
|
+
if (nextCodePoint && nextCodePoint >= REGIONAL_INDICATOR_START && nextCodePoint <= REGIONAL_INDICATOR_END) {
|
|
1002
|
+
value += nextGrapheme;
|
|
1003
|
+
i++;
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
while (i + 1 < graphemes.length) {
|
|
1007
|
+
const nextGrapheme = graphemes[i + 1];
|
|
1008
|
+
const nextCodePoint = nextGrapheme.codePointAt(0);
|
|
1009
|
+
if (!nextCodePoint) {
|
|
1010
|
+
break;
|
|
1011
|
+
}
|
|
1012
|
+
const firstCharIsUnicodeMark = unicodeMarkRegex.test(String.fromCodePoint(nextCodePoint));
|
|
1013
|
+
const isSkinToneModifier = nextCodePoint >= SKIN_TONE_START && nextCodePoint <= SKIN_TONE_END;
|
|
1014
|
+
const isZeroWidthJoiner = nextCodePoint === ZWJ;
|
|
1015
|
+
const isTagsBlock = nextCodePoint >= TAGS_BLOCK_START && nextCodePoint <= TAGS_BLOCK_END;
|
|
1016
|
+
if (!firstCharIsUnicodeMark && !isSkinToneModifier && !isZeroWidthJoiner && !isTagsBlock) {
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
value += nextGrapheme;
|
|
1020
|
+
i++;
|
|
1021
|
+
if (isZeroWidthJoiner && i + 1 < graphemes.length) {
|
|
1022
|
+
value += graphemes[i + 1];
|
|
1023
|
+
i++;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
const fw = isFullwidthGrapheme(value, firstCodePoint);
|
|
1028
|
+
const flags = fw ? state.formatFlags | FULL_WIDTH_MASK : state.formatFlags;
|
|
1029
|
+
line.pushChar(value, flags, state.fgColor, state.bgColor, state.link);
|
|
1030
|
+
}
|
|
1031
|
+
};
|
|
1032
|
+
const textToStyledLine = (text) => {
|
|
1033
|
+
if (text.length === 0) {
|
|
1034
|
+
return new StyledLine();
|
|
1035
|
+
}
|
|
1036
|
+
const tokens = tokenizeAnsi(text);
|
|
1037
|
+
const line = new StyledLine();
|
|
1038
|
+
let sgrState = createSgrState();
|
|
1039
|
+
for (const token of tokens) {
|
|
1040
|
+
switch (token.type) {
|
|
1041
|
+
case "csi": {
|
|
1042
|
+
if (token.finalCharacter === "m") {
|
|
1043
|
+
sgrState = applySgrParams(sgrState, token.parameterString);
|
|
1044
|
+
}
|
|
1045
|
+
break;
|
|
1046
|
+
}
|
|
1047
|
+
case "osc": {
|
|
1048
|
+
const link = parseOscHyperlink(token.value);
|
|
1049
|
+
if (link !== void 0) {
|
|
1050
|
+
sgrState = { ...sgrState, link };
|
|
1051
|
+
} else if (token.value.includes("8;")) {
|
|
1052
|
+
sgrState = { ...sgrState, link: void 0 };
|
|
1053
|
+
}
|
|
1054
|
+
break;
|
|
1055
|
+
}
|
|
1056
|
+
case "text": {
|
|
1057
|
+
processTextToken(token.value, line, sgrState);
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return line;
|
|
1063
|
+
};
|
|
1064
|
+
const asciiPrintableRegex = /^[\u0020-\u007E]*$/;
|
|
1065
|
+
const plainTextToStyledLine = (text) => {
|
|
1066
|
+
if (text.length === 0) {
|
|
1067
|
+
return new StyledLine();
|
|
1068
|
+
}
|
|
1069
|
+
const line = new StyledLine();
|
|
1070
|
+
if (asciiPrintableRegex.test(text)) {
|
|
1071
|
+
for (const element of text) {
|
|
1072
|
+
line.pushChar(element, 0);
|
|
1073
|
+
}
|
|
1074
|
+
return line;
|
|
1075
|
+
}
|
|
1076
|
+
processTextToken(text, line, createSgrState());
|
|
1077
|
+
return line;
|
|
1078
|
+
};
|
|
1079
|
+
|
|
1080
|
+
const cache = new DataLimitedLruMap(1e4, 1e6);
|
|
1081
|
+
const widthCache = /* @__PURE__ */ new Map();
|
|
1082
|
+
const styledLineCache = new DataLimitedLruMap(1e4, 1e6);
|
|
1083
|
+
let styledLineCacheEnabled = true;
|
|
1084
|
+
let currentStringWidth = getStringWidth;
|
|
1085
|
+
const setEnableStyledLineCache = (enabled) => {
|
|
1086
|
+
styledLineCacheEnabled = enabled;
|
|
1087
|
+
if (!enabled) {
|
|
1088
|
+
styledLineCache.clear();
|
|
1089
|
+
}
|
|
1090
|
+
};
|
|
1091
|
+
const clearStyledLineCache = () => {
|
|
1092
|
+
styledLineCache.clear();
|
|
1093
|
+
};
|
|
1094
|
+
const setStringWidthFunction = (function_) => {
|
|
1095
|
+
currentStringWidth = function_;
|
|
1096
|
+
clearStringWidthCache();
|
|
1097
|
+
};
|
|
1098
|
+
const clearStringWidthCache = () => {
|
|
1099
|
+
cache.clear();
|
|
1100
|
+
widthCache.clear();
|
|
1101
|
+
styledLineCache.clear();
|
|
1102
|
+
};
|
|
1103
|
+
const inkCharacterWidth = (text) => {
|
|
1104
|
+
const cached = widthCache.get(text);
|
|
1105
|
+
if (cached !== void 0) {
|
|
1106
|
+
return cached;
|
|
1107
|
+
}
|
|
1108
|
+
let calculatedWidth;
|
|
1109
|
+
try {
|
|
1110
|
+
calculatedWidth = currentStringWidth(text);
|
|
1111
|
+
} catch {
|
|
1112
|
+
calculatedWidth = 1;
|
|
1113
|
+
}
|
|
1114
|
+
widthCache.set(text, calculatedWidth);
|
|
1115
|
+
return calculatedWidth;
|
|
1116
|
+
};
|
|
1117
|
+
const safeGetStringWidth = (text) => {
|
|
1118
|
+
try {
|
|
1119
|
+
return currentStringWidth(text);
|
|
1120
|
+
} catch {
|
|
1121
|
+
return 1;
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
const measureText = (text) => {
|
|
1125
|
+
if (text.length === 0) {
|
|
1126
|
+
return {
|
|
1127
|
+
height: 0,
|
|
1128
|
+
width: 0
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
const cachedDimensions = cache.get(text);
|
|
1132
|
+
if (cachedDimensions) {
|
|
1133
|
+
return cachedDimensions;
|
|
1134
|
+
}
|
|
1135
|
+
const lines = text.split("\n");
|
|
1136
|
+
const width = Math.max(...lines.map((line) => safeGetStringWidth(line)));
|
|
1137
|
+
const height = lines.length;
|
|
1138
|
+
const dimensions = { height, width };
|
|
1139
|
+
cache.set(text, dimensions);
|
|
1140
|
+
return dimensions;
|
|
1141
|
+
};
|
|
1142
|
+
const toStyledLine = (text) => {
|
|
1143
|
+
if (styledLineCacheEnabled) {
|
|
1144
|
+
const cached = styledLineCache.get(text);
|
|
1145
|
+
if (cached !== void 0) {
|
|
1146
|
+
return cached;
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
const line = textToStyledLine(text);
|
|
1150
|
+
if (styledLineCacheEnabled) {
|
|
1151
|
+
styledLineCache.set(text, line);
|
|
1152
|
+
}
|
|
1153
|
+
return line;
|
|
1154
|
+
};
|
|
1155
|
+
const styledLineWidth = (line) => {
|
|
1156
|
+
let length = 0;
|
|
1157
|
+
for (let i = 0; i < line.length; i++) {
|
|
1158
|
+
length += inkCharacterWidth(line.getValue(i));
|
|
1159
|
+
}
|
|
1160
|
+
return length;
|
|
1161
|
+
};
|
|
1162
|
+
const splitStyledLineByNewline = (line) => {
|
|
1163
|
+
if (line.length === 0) {
|
|
1164
|
+
return [new StyledLine()];
|
|
1165
|
+
}
|
|
1166
|
+
const lines = [];
|
|
1167
|
+
let start = 0;
|
|
1168
|
+
for (let i = 0; i < line.length; i++) {
|
|
1169
|
+
if (line.getValue(i) === "\n") {
|
|
1170
|
+
lines.push(i > start ? line.slice(start, i) : new StyledLine());
|
|
1171
|
+
start = i + 1;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
lines.push(start < line.length ? line.slice(start) : new StyledLine());
|
|
1175
|
+
return lines;
|
|
1176
|
+
};
|
|
1177
|
+
const measureStyledLine = (line) => {
|
|
1178
|
+
if (line.length === 0) {
|
|
1179
|
+
return { height: 0, width: 0 };
|
|
1180
|
+
}
|
|
1181
|
+
const lines = splitStyledLineByNewline(line);
|
|
1182
|
+
let maxWidth = 0;
|
|
1183
|
+
for (const l of lines) {
|
|
1184
|
+
maxWidth = Math.max(maxWidth, styledLineWidth(l));
|
|
1185
|
+
}
|
|
1186
|
+
return { height: lines.length, width: maxWidth };
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
export { BOLD_MASK as B, DIM_MASK as D, FULL_WIDTH_MASK as F, HIDDEN_MASK as H, ITALIC_MASK as I, StyledLine as S, UNDERLINE_MASK as U, clearStyledLineCache as a, setStringWidthFunction as b, clearStringWidthCache as c, styledLineWidth as d, INVERSE_MASK as e, STRIKETHROUGH_MASK as f, colorToSgrParams as g, colorToAnsi256 as h, inkCharacterWidth as i, textToStyledLine as j, measureStyledLine as k, splitStyledLineByNewline as l, measureText as m, plainTextToStyledLine as p, setEnableStyledLineCache as s, toStyledLine as t };
|