@gabvdl/ui 0.0.14
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/README.md +95 -0
- package/dist/components/button/button.d.ts +39 -0
- package/dist/components/button/button.d.ts.map +1 -0
- package/dist/components/button/button.js +72 -0
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/button/index.d.ts +5 -0
- package/dist/components/button/index.d.ts.map +1 -0
- package/dist/components/button/tooltip.d.ts +31 -0
- package/dist/components/button/tooltip.d.ts.map +1 -0
- package/dist/components/button/tooltip.js +83 -0
- package/dist/components/button/tooltip.js.map +1 -0
- package/dist/components/changelog/changelog.d.ts +52 -0
- package/dist/components/changelog/changelog.d.ts.map +1 -0
- package/dist/components/changelog/changelog.js +164 -0
- package/dist/components/changelog/changelog.js.map +1 -0
- package/dist/components/changelog/index.d.ts +3 -0
- package/dist/components/changelog/index.d.ts.map +1 -0
- package/dist/components/copy-button/copy-button.d.ts +16 -0
- package/dist/components/copy-button/copy-button.d.ts.map +1 -0
- package/dist/components/copy-button/copy-button.js +40 -0
- package/dist/components/copy-button/copy-button.js.map +1 -0
- package/dist/components/copy-button/index.d.ts +3 -0
- package/dist/components/copy-button/index.d.ts.map +1 -0
- package/dist/components/drop-zone/drop-zone.d.ts +20 -0
- package/dist/components/drop-zone/drop-zone.d.ts.map +1 -0
- package/dist/components/drop-zone/drop-zone.js +54 -0
- package/dist/components/drop-zone/drop-zone.js.map +1 -0
- package/dist/components/drop-zone/index.d.ts +5 -0
- package/dist/components/drop-zone/index.d.ts.map +1 -0
- package/dist/components/drop-zone/use-file-drop.d.ts +45 -0
- package/dist/components/drop-zone/use-file-drop.d.ts.map +1 -0
- package/dist/components/drop-zone/use-file-drop.js +97 -0
- package/dist/components/drop-zone/use-file-drop.js.map +1 -0
- package/dist/components/element-picker/element-picker-field.d.ts +30 -0
- package/dist/components/element-picker/element-picker-field.d.ts.map +1 -0
- package/dist/components/element-picker/element-picker-field.js +273 -0
- package/dist/components/element-picker/element-picker-field.js.map +1 -0
- package/dist/components/element-picker/element-picker.d.ts +45 -0
- package/dist/components/element-picker/element-picker.d.ts.map +1 -0
- package/dist/components/element-picker/element-picker.js +179 -0
- package/dist/components/element-picker/element-picker.js.map +1 -0
- package/dist/components/element-picker/element-preview.d.ts +23 -0
- package/dist/components/element-picker/element-preview.d.ts.map +1 -0
- package/dist/components/element-picker/element-preview.js +72 -0
- package/dist/components/element-picker/element-preview.js.map +1 -0
- package/dist/components/element-picker/index.d.ts +12 -0
- package/dist/components/element-picker/index.d.ts.map +1 -0
- package/dist/components/element-picker/parse.d.ts +32 -0
- package/dist/components/element-picker/parse.d.ts.map +1 -0
- package/dist/components/element-picker/parse.js +230 -0
- package/dist/components/element-picker/parse.js.map +1 -0
- package/dist/components/element-picker/types.d.ts +72 -0
- package/dist/components/element-picker/types.d.ts.map +1 -0
- package/dist/components/element-picker/use-element-picker.d.ts +56 -0
- package/dist/components/element-picker/use-element-picker.d.ts.map +1 -0
- package/dist/components/element-picker/use-element-picker.js +201 -0
- package/dist/components/element-picker/use-element-picker.js.map +1 -0
- package/dist/components/empty-state/empty-state.d.ts +16 -0
- package/dist/components/empty-state/empty-state.d.ts.map +1 -0
- package/dist/components/empty-state/empty-state.js +41 -0
- package/dist/components/empty-state/empty-state.js.map +1 -0
- package/dist/components/empty-state/index.d.ts +3 -0
- package/dist/components/empty-state/index.d.ts.map +1 -0
- package/dist/components/floating-panel/dock-context.d.ts +66 -0
- package/dist/components/floating-panel/dock-context.d.ts.map +1 -0
- package/dist/components/floating-panel/dock-context.js +96 -0
- package/dist/components/floating-panel/dock-context.js.map +1 -0
- package/dist/components/floating-panel/dock.d.ts +26 -0
- package/dist/components/floating-panel/dock.d.ts.map +1 -0
- package/dist/components/floating-panel/dock.js +46 -0
- package/dist/components/floating-panel/dock.js.map +1 -0
- package/dist/components/floating-panel/floating-panel.d.ts +69 -0
- package/dist/components/floating-panel/floating-panel.d.ts.map +1 -0
- package/dist/components/floating-panel/floating-panel.js +285 -0
- package/dist/components/floating-panel/floating-panel.js.map +1 -0
- package/dist/components/floating-panel/index.d.ts +7 -0
- package/dist/components/floating-panel/index.d.ts.map +1 -0
- package/dist/components/fuzzy-list/fuzzy-list.d.ts +96 -0
- package/dist/components/fuzzy-list/fuzzy-list.d.ts.map +1 -0
- package/dist/components/fuzzy-list/fuzzy-list.js +127 -0
- package/dist/components/fuzzy-list/fuzzy-list.js.map +1 -0
- package/dist/components/fuzzy-list/index.d.ts +4 -0
- package/dist/components/fuzzy-list/index.d.ts.map +1 -0
- package/dist/components/global-search/global-search.d.ts +78 -0
- package/dist/components/global-search/global-search.d.ts.map +1 -0
- package/dist/components/global-search/global-search.js +181 -0
- package/dist/components/global-search/global-search.js.map +1 -0
- package/dist/components/global-search/hotkey.d.ts +23 -0
- package/dist/components/global-search/hotkey.d.ts.map +1 -0
- package/dist/components/global-search/hotkey.js +41 -0
- package/dist/components/global-search/hotkey.js.map +1 -0
- package/dist/components/global-search/index.d.ts +5 -0
- package/dist/components/global-search/index.d.ts.map +1 -0
- package/dist/components/iframe-preview/iframe-preview.d.ts +64 -0
- package/dist/components/iframe-preview/iframe-preview.d.ts.map +1 -0
- package/dist/components/iframe-preview/iframe-preview.js +257 -0
- package/dist/components/iframe-preview/iframe-preview.js.map +1 -0
- package/dist/components/iframe-preview/index.d.ts +3 -0
- package/dist/components/iframe-preview/index.d.ts.map +1 -0
- package/dist/components/image-viewer/image-viewer.d.ts +30 -0
- package/dist/components/image-viewer/image-viewer.d.ts.map +1 -0
- package/dist/components/image-viewer/image-viewer.js +226 -0
- package/dist/components/image-viewer/image-viewer.js.map +1 -0
- package/dist/components/image-viewer/index.d.ts +4 -0
- package/dist/components/image-viewer/index.d.ts.map +1 -0
- package/dist/components/image-viewer/progressive-image.d.ts +20 -0
- package/dist/components/image-viewer/progressive-image.d.ts.map +1 -0
- package/dist/components/image-viewer/progressive-image.js +62 -0
- package/dist/components/image-viewer/progressive-image.js.map +1 -0
- package/dist/components/image-viewer/viewable-image.d.ts +17 -0
- package/dist/components/image-viewer/viewable-image.d.ts.map +1 -0
- package/dist/components/image-viewer/viewable-image.js +38 -0
- package/dist/components/image-viewer/viewable-image.js.map +1 -0
- package/dist/components/input/index.d.ts +3 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/input/input.d.ts +15 -0
- package/dist/components/input/input.d.ts.map +1 -0
- package/dist/components/input/input.js +56 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/modal/index.d.ts +5 -0
- package/dist/components/modal/index.d.ts.map +1 -0
- package/dist/components/modal/modal-context.d.ts +37 -0
- package/dist/components/modal/modal-context.d.ts.map +1 -0
- package/dist/components/modal/modal-context.js +81 -0
- package/dist/components/modal/modal-context.js.map +1 -0
- package/dist/components/modal/modal.d.ts +28 -0
- package/dist/components/modal/modal.d.ts.map +1 -0
- package/dist/components/modal/modal.js +94 -0
- package/dist/components/modal/modal.js.map +1 -0
- package/dist/components/nav-2d/index.d.ts +3 -0
- package/dist/components/nav-2d/index.d.ts.map +1 -0
- package/dist/components/nav-2d/nav-2d.d.ts +59 -0
- package/dist/components/nav-2d/nav-2d.d.ts.map +1 -0
- package/dist/components/nav-2d/nav-2d.js +290 -0
- package/dist/components/nav-2d/nav-2d.js.map +1 -0
- package/dist/components/phone-preview/index.d.ts +3 -0
- package/dist/components/phone-preview/index.d.ts.map +1 -0
- package/dist/components/phone-preview/phone-preview.d.ts +45 -0
- package/dist/components/phone-preview/phone-preview.d.ts.map +1 -0
- package/dist/components/phone-preview/phone-preview.js +117 -0
- package/dist/components/phone-preview/phone-preview.js.map +1 -0
- package/dist/components/progressive-bash/index.d.ts +7 -0
- package/dist/components/progressive-bash/index.d.ts.map +1 -0
- package/dist/components/progressive-bash/parse.d.ts +88 -0
- package/dist/components/progressive-bash/parse.d.ts.map +1 -0
- package/dist/components/progressive-bash/parse.js +120 -0
- package/dist/components/progressive-bash/parse.js.map +1 -0
- package/dist/components/progressive-bash/playback.d.ts +50 -0
- package/dist/components/progressive-bash/playback.d.ts.map +1 -0
- package/dist/components/progressive-bash/playback.js +19 -0
- package/dist/components/progressive-bash/playback.js.map +1 -0
- package/dist/components/progressive-bash/progressive-bash.d.ts +97 -0
- package/dist/components/progressive-bash/progressive-bash.d.ts.map +1 -0
- package/dist/components/progressive-bash/progressive-bash.js +377 -0
- package/dist/components/progressive-bash/progressive-bash.js.map +1 -0
- package/dist/components/progressive-list/index.d.ts +3 -0
- package/dist/components/progressive-list/index.d.ts.map +1 -0
- package/dist/components/progressive-list/progressive-list.d.ts +55 -0
- package/dist/components/progressive-list/progressive-list.d.ts.map +1 -0
- package/dist/components/progressive-list/progressive-list.js +83 -0
- package/dist/components/progressive-list/progressive-list.js.map +1 -0
- package/dist/components/progressive-table/index.d.ts +3 -0
- package/dist/components/progressive-table/index.d.ts.map +1 -0
- package/dist/components/progressive-table/progressive-table.d.ts +58 -0
- package/dist/components/progressive-table/progressive-table.d.ts.map +1 -0
- package/dist/components/progressive-table/progressive-table.js +86 -0
- package/dist/components/progressive-table/progressive-table.js.map +1 -0
- package/dist/components/progressive-text/index.d.ts +3 -0
- package/dist/components/progressive-text/index.d.ts.map +1 -0
- package/dist/components/progressive-text/progressive-text.d.ts +54 -0
- package/dist/components/progressive-text/progressive-text.d.ts.map +1 -0
- package/dist/components/progressive-text/progressive-text.js +97 -0
- package/dist/components/progressive-text/progressive-text.js.map +1 -0
- package/dist/components/progressive-timeline/index.d.ts +3 -0
- package/dist/components/progressive-timeline/index.d.ts.map +1 -0
- package/dist/components/progressive-timeline/progressive-timeline.d.ts +46 -0
- package/dist/components/progressive-timeline/progressive-timeline.d.ts.map +1 -0
- package/dist/components/progressive-timeline/progressive-timeline.js +62 -0
- package/dist/components/progressive-timeline/progressive-timeline.js.map +1 -0
- package/dist/components/relative-time/index.d.ts +3 -0
- package/dist/components/relative-time/index.d.ts.map +1 -0
- package/dist/components/relative-time/relative-time.d.ts +14 -0
- package/dist/components/relative-time/relative-time.d.ts.map +1 -0
- package/dist/components/relative-time/relative-time.js +15 -0
- package/dist/components/relative-time/relative-time.js.map +1 -0
- package/dist/components/resizable-layout/index.d.ts +3 -0
- package/dist/components/resizable-layout/index.d.ts.map +1 -0
- package/dist/components/resizable-layout/resizable-layout.d.ts +113 -0
- package/dist/components/resizable-layout/resizable-layout.d.ts.map +1 -0
- package/dist/components/resizable-layout/resizable-layout.js +398 -0
- package/dist/components/resizable-layout/resizable-layout.js.map +1 -0
- package/dist/components/rich-input/compose.d.ts +13 -0
- package/dist/components/rich-input/compose.d.ts.map +1 -0
- package/dist/components/rich-input/compose.js +28 -0
- package/dist/components/rich-input/compose.js.map +1 -0
- package/dist/components/rich-input/index.d.ts +5 -0
- package/dist/components/rich-input/index.d.ts.map +1 -0
- package/dist/components/rich-input/parts.d.ts +53 -0
- package/dist/components/rich-input/parts.d.ts.map +1 -0
- package/dist/components/rich-input/parts.js +285 -0
- package/dist/components/rich-input/parts.js.map +1 -0
- package/dist/components/rich-input/rich-input.d.ts +64 -0
- package/dist/components/rich-input/rich-input.d.ts.map +1 -0
- package/dist/components/rich-input/rich-input.js +351 -0
- package/dist/components/rich-input/rich-input.js.map +1 -0
- package/dist/components/rich-input/types.d.ts +92 -0
- package/dist/components/rich-input/types.d.ts.map +1 -0
- package/dist/components/rich-input/use-draft.d.ts +9 -0
- package/dist/components/rich-input/use-draft.d.ts.map +1 -0
- package/dist/components/rich-input/use-draft.js +47 -0
- package/dist/components/rich-input/use-draft.js.map +1 -0
- package/dist/components/rich-input/use-file-upload.d.ts +18 -0
- package/dist/components/rich-input/use-file-upload.d.ts.map +1 -0
- package/dist/components/rich-input/use-file-upload.js +88 -0
- package/dist/components/rich-input/use-file-upload.js.map +1 -0
- package/dist/components/rich-input/use-guidelines.d.ts +16 -0
- package/dist/components/rich-input/use-guidelines.d.ts.map +1 -0
- package/dist/components/rich-input/use-guidelines.js +85 -0
- package/dist/components/rich-input/use-guidelines.js.map +1 -0
- package/dist/components/rich-input/use-input-history.d.ts +22 -0
- package/dist/components/rich-input/use-input-history.d.ts.map +1 -0
- package/dist/components/rich-input/use-input-history.js +61 -0
- package/dist/components/rich-input/use-input-history.js.map +1 -0
- package/dist/components/rich-input/use-mention.d.ts +24 -0
- package/dist/components/rich-input/use-mention.d.ts.map +1 -0
- package/dist/components/rich-input/use-mention.js +54 -0
- package/dist/components/rich-input/use-mention.js.map +1 -0
- package/dist/components/search-input/index.d.ts +3 -0
- package/dist/components/search-input/index.d.ts.map +1 -0
- package/dist/components/search-input/search-input.d.ts +14 -0
- package/dist/components/search-input/search-input.d.ts.map +1 -0
- package/dist/components/search-input/search-input.js +63 -0
- package/dist/components/search-input/search-input.js.map +1 -0
- package/dist/components/skeleton/index.d.ts +3 -0
- package/dist/components/skeleton/index.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +19 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.js +29 -0
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/spinner/index.d.ts +3 -0
- package/dist/components/spinner/index.d.ts.map +1 -0
- package/dist/components/spinner/spinner.d.ts +11 -0
- package/dist/components/spinner/spinner.d.ts.map +1 -0
- package/dist/components/spinner/spinner.js +32 -0
- package/dist/components/spinner/spinner.js.map +1 -0
- package/dist/components/status-badge/index.d.ts +3 -0
- package/dist/components/status-badge/index.d.ts.map +1 -0
- package/dist/components/status-badge/status-badge.d.ts +31 -0
- package/dist/components/status-badge/status-badge.d.ts.map +1 -0
- package/dist/components/status-badge/status-badge.js +53 -0
- package/dist/components/status-badge/status-badge.js.map +1 -0
- package/dist/components/theme/index.d.ts +5 -0
- package/dist/components/theme/index.d.ts.map +1 -0
- package/dist/components/theme/theme-toggle.d.ts +11 -0
- package/dist/components/theme/theme-toggle.d.ts.map +1 -0
- package/dist/components/theme/theme-toggle.js +57 -0
- package/dist/components/theme/theme-toggle.js.map +1 -0
- package/dist/components/theme/theme.d.ts +29 -0
- package/dist/components/theme/theme.d.ts.map +1 -0
- package/dist/components/theme/theme.js +70 -0
- package/dist/components/theme/theme.js.map +1 -0
- package/dist/components/toast/index.d.ts +3 -0
- package/dist/components/toast/index.d.ts.map +1 -0
- package/dist/components/toast/toast.d.ts +64 -0
- package/dist/components/toast/toast.d.ts.map +1 -0
- package/dist/components/toast/toast.js +155 -0
- package/dist/components/toast/toast.js.map +1 -0
- package/dist/components/virtual-list/index.d.ts +3 -0
- package/dist/components/virtual-list/index.d.ts.map +1 -0
- package/dist/components/virtual-list/virtual-list.d.ts +71 -0
- package/dist/components/virtual-list/virtual-list.d.ts.map +1 -0
- package/dist/components/virtual-list/virtual-list.js +65 -0
- package/dist/components/virtual-list/virtual-list.js.map +1 -0
- package/dist/hooks/index.d.ts +12 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts +26 -0
- package/dist/hooks/use-copy-to-clipboard.d.ts.map +1 -0
- package/dist/hooks/use-copy-to-clipboard.js +36 -0
- package/dist/hooks/use-copy-to-clipboard.js.map +1 -0
- package/dist/hooks/use-debounced-value.d.ts +23 -0
- package/dist/hooks/use-debounced-value.d.ts.map +1 -0
- package/dist/hooks/use-debounced-value.js +19 -0
- package/dist/hooks/use-debounced-value.js.map +1 -0
- package/dist/hooks/use-intersection.d.ts +25 -0
- package/dist/hooks/use-intersection.d.ts.map +1 -0
- package/dist/hooks/use-intersection.js +38 -0
- package/dist/hooks/use-intersection.js.map +1 -0
- package/dist/hooks/use-local-storage.d.ts +12 -0
- package/dist/hooks/use-local-storage.d.ts.map +1 -0
- package/dist/hooks/use-local-storage.js +43 -0
- package/dist/hooks/use-local-storage.js.map +1 -0
- package/dist/hooks/use-long-press.d.ts +37 -0
- package/dist/hooks/use-long-press.d.ts.map +1 -0
- package/dist/hooks/use-long-press.js +39 -0
- package/dist/hooks/use-long-press.js.map +1 -0
- package/dist/hooks/use-media-query.d.ts +17 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +37 -0
- package/dist/hooks/use-media-query.js.map +1 -0
- package/dist/hooks/use-overlay.d.ts +20 -0
- package/dist/hooks/use-overlay.d.ts.map +1 -0
- package/dist/hooks/use-overlay.js +42 -0
- package/dist/hooks/use-overlay.js.map +1 -0
- package/dist/image-viewer.css +152 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +161 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/format.d.ts +19 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +62 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/highlight.d.ts +15 -0
- package/dist/lib/highlight.d.ts.map +1 -0
- package/dist/lib/highlight.js +39 -0
- package/dist/lib/highlight.js.map +1 -0
- package/dist/lib/search.d.ts +40 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +91 -0
- package/dist/lib/search.js.map +1 -0
- package/dist/lib/utils.d.ts +4 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +9 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/overlay.css +78 -0
- package/dist/styles.css +6 -0
- package/dist/theme.css +81 -0
- package/dist/tooltip.css +53 -0
- package/dist/virtual-list.css +29 -0
- package/package.json +77 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export type CmdKind = 'program' | 'subcommand' | 'flag' | 'string' | 'operator' | 'path' | 'var' | 'number' | 'comment' | 'plain';
|
|
2
|
+
export interface CmdToken {
|
|
3
|
+
text: string;
|
|
4
|
+
kind: CmdKind;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Break a shell command into colorable tokens. The first bare word is the
|
|
8
|
+
* program; the next bare word (if it isn't a flag/path) is treated as its
|
|
9
|
+
* subcommand (`git commit`, `docker compose`, `make up`). Whitespace is kept as
|
|
10
|
+
* `plain` tokens so the reconstruction is loss-less.
|
|
11
|
+
*/
|
|
12
|
+
export declare function tokenizeCommand(command: string): CmdToken[];
|
|
13
|
+
export type LineKind = 'section' | 'error' | 'success' | 'warn' | 'info' | 'plain';
|
|
14
|
+
export interface OutputSpan {
|
|
15
|
+
text: string;
|
|
16
|
+
/** Inline accent, layered on top of the line's base color. */
|
|
17
|
+
accent?: 'path' | 'url' | 'number' | 'string' | 'flag' | 'hash';
|
|
18
|
+
}
|
|
19
|
+
export interface OutputLine {
|
|
20
|
+
kind: LineKind;
|
|
21
|
+
/** `true` for `===.*===` / `--- … ---` divider lines (rendered as a bar). */
|
|
22
|
+
divider: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Set when this line is an `echo "Title..[value]"` sub-part marker (see
|
|
25
|
+
* {@link parseEchoMarkers}). The raw echo line is swallowed and rendered as a
|
|
26
|
+
* titled step header instead of plain output.
|
|
27
|
+
*/
|
|
28
|
+
sub?: SubMarker;
|
|
29
|
+
spans: OutputSpan[];
|
|
30
|
+
raw: string;
|
|
31
|
+
}
|
|
32
|
+
/** A `Title..[value]` step marker echoed inside a compound command. */
|
|
33
|
+
export interface SubMarker {
|
|
34
|
+
/** The human title (text before `..[`). */
|
|
35
|
+
title: string;
|
|
36
|
+
/** The bracketed tag/value (text inside `[...]`), if any. */
|
|
37
|
+
value?: string;
|
|
38
|
+
/** The exact echoed string, used to match the marker line in the output. */
|
|
39
|
+
raw: string;
|
|
40
|
+
}
|
|
41
|
+
/** Parse `Title..[value]` from a bare echoed string, or `null` if it isn't one. */
|
|
42
|
+
export declare function parseMarkerText(text: string): SubMarker | null;
|
|
43
|
+
/** One step extracted from a compound `echo "Title..[value]" && cmd && …` chain. */
|
|
44
|
+
export interface SubCommand {
|
|
45
|
+
/** The human title (text before `..[`). */
|
|
46
|
+
title: string;
|
|
47
|
+
/** The bracketed tag/value (text inside `[...]`), if any. */
|
|
48
|
+
value?: string;
|
|
49
|
+
/** The real command that followed the marker (echo statement + connector stripped). */
|
|
50
|
+
command: string;
|
|
51
|
+
/** The step's output — the lines printed after its marker line, up to the next. */
|
|
52
|
+
output: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* [EXPERIMENTAL] Split a compound `echo "Title..[value]" && realcmd && …` chain
|
|
56
|
+
* into its individual steps, pairing each marker's real command with the output
|
|
57
|
+
* lines printed after that marker's echoed line. Returns `null` when the command
|
|
58
|
+
* has no `..[...]` echo markers (nothing to split).
|
|
59
|
+
*
|
|
60
|
+
* This is what lets `ProgressiveBash` expand one chained command into several
|
|
61
|
+
* separate, sequentially-typed command blocks — so a long agent one-liner
|
|
62
|
+
* animates as the individual commands it really ran, filling playback time
|
|
63
|
+
* while a genuinely long command elsewhere is still running.
|
|
64
|
+
*/
|
|
65
|
+
export declare function splitBySubparts(command: string, output: string): SubCommand[] | null;
|
|
66
|
+
/**
|
|
67
|
+
* [EXPERIMENTAL] Pull `echo "Title..[value]"` step markers out of a compound
|
|
68
|
+
* command. Agents often chain steps like
|
|
69
|
+
* `echo "Install..[deps]" && npm i && echo "Build..[vite]" && npm run build`;
|
|
70
|
+
* each specially-formatted echo prints a heading into the output that we can
|
|
71
|
+
* then hoist into a titled sub-part (see {@link splitOutput}'s `markers` arg).
|
|
72
|
+
* Only echoes using the `..[...]` syntax are treated as markers — ordinary
|
|
73
|
+
* `echo "hello"` lines are left untouched.
|
|
74
|
+
*/
|
|
75
|
+
export declare function parseEchoMarkers(command: string): SubMarker[];
|
|
76
|
+
/** Classify a single output line and produce its inline spans. */
|
|
77
|
+
export declare function classifyLine(line: string): OutputLine;
|
|
78
|
+
/**
|
|
79
|
+
* Split raw output into lines. Blocks delimited by `=== … ===` (or `--- … ---`)
|
|
80
|
+
* lines are kept as their own section markers — this mirrors how test runners
|
|
81
|
+
* (`=== RUN`, `--- PASS`) and check scripts group their output, and lets the
|
|
82
|
+
* player reveal one section at a time.
|
|
83
|
+
*
|
|
84
|
+
* Pass `markers` (from {@link parseEchoMarkers}) to hoist matching
|
|
85
|
+
* `echo "Title..[value]"` output lines into titled sub-part headers.
|
|
86
|
+
*/
|
|
87
|
+
export declare function splitOutput(output: string, markers?: SubMarker[]): OutputLine[];
|
|
88
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-bash/parse.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,OAAO,GACf,SAAS,GACT,YAAY,GACZ,MAAM,GACN,QAAQ,GACR,UAAU,GACV,MAAM,GACN,KAAK,GACL,QAAQ,GACR,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAcD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAsD3D;AAED,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAEnF,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC;CACjE;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,6EAA6E;IAC7E,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,uEAAuE;AACvE,MAAM,WAAW,SAAS;IACxB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC;CACb;AAMD,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAI9D;AAED,oFAAoF;AACpF,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;CAChB;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,GAAG,IAAI,CAoCpF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,CAU7D;AAiCD,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAYrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAY/E"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
const m = /^(\|\||&&|>>|<<|[|&;<>()])/, g = /^("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|`(?:[^`\\]|\\.)*`)/, b = /^\$\{?[A-Za-z_][A-Za-z0-9_]*\}?/, k = /^-{1,2}[A-Za-z0-9][A-Za-z0-9-]*/, w = /^\d+(?:\.\d+)?/, R = /^[^\s|&;<>()]+/, x = /^\s+/;
|
|
2
|
+
function p(t) {
|
|
3
|
+
return /[/~]/.test(t) && !/^-/.test(t);
|
|
4
|
+
}
|
|
5
|
+
function L(t) {
|
|
6
|
+
const n = [];
|
|
7
|
+
let s = t, e = !1, r = !1;
|
|
8
|
+
const l = t.search(/(^|\s)#/);
|
|
9
|
+
let c = "";
|
|
10
|
+
if (l >= 0) {
|
|
11
|
+
const i = t[l] === "#" ? l : l + 1;
|
|
12
|
+
c = t.slice(i), s = t.slice(0, i);
|
|
13
|
+
}
|
|
14
|
+
for (; s.length > 0; ) {
|
|
15
|
+
let i;
|
|
16
|
+
if (i = s.match(x))
|
|
17
|
+
n.push({ text: i[0], kind: "plain" });
|
|
18
|
+
else if (i = s.match(g))
|
|
19
|
+
n.push({ text: i[0], kind: "string" });
|
|
20
|
+
else if (i = s.match(m))
|
|
21
|
+
n.push({ text: i[0], kind: "operator" }), e = !1, r = !1;
|
|
22
|
+
else if (i = s.match(b))
|
|
23
|
+
n.push({ text: i[0], kind: "var" });
|
|
24
|
+
else if (i = s.match(k))
|
|
25
|
+
n.push({ text: i[0], kind: "flag" });
|
|
26
|
+
else if (i = s.match(R)) {
|
|
27
|
+
const a = i[0];
|
|
28
|
+
let o;
|
|
29
|
+
e ? !r && !p(a) && /^[a-z][a-z0-9:._-]*$/i.test(a) && !/[=]/.test(a) ? (o = "subcommand", r = !0) : p(a) ? o = "path" : w.test(a) ? o = "number" : o = "plain" : (o = "program", e = !0), n.push({ text: a, kind: o });
|
|
30
|
+
} else {
|
|
31
|
+
n.push({ text: s[0], kind: "plain" }), s = s.slice(1);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
s = s.slice(i[0].length);
|
|
35
|
+
}
|
|
36
|
+
return c && n.push({ text: c, kind: "comment" }), n;
|
|
37
|
+
}
|
|
38
|
+
const d = /\becho\s+(?:"([^"]*)"|'([^']*)'|([^\s|&;<>()]+))/g, E = /^(.*?)\.\.\[([^\]]*)\]\s*$/;
|
|
39
|
+
function A(t) {
|
|
40
|
+
const n = t.match(E);
|
|
41
|
+
return n ? { title: n[1].trim(), value: n[2].trim() || void 0, raw: t } : null;
|
|
42
|
+
}
|
|
43
|
+
const N = /^\s*(?:&&|\|\||;|&)\s*/, O = /\s*(?:&&|\|\||;|&)\s*$/;
|
|
44
|
+
function _(t) {
|
|
45
|
+
let n = 0, s = t.length;
|
|
46
|
+
for (; n < s && t[n].trim() === ""; ) n++;
|
|
47
|
+
for (; s > n && t[s - 1].trim() === ""; ) s--;
|
|
48
|
+
return t.slice(n, s);
|
|
49
|
+
}
|
|
50
|
+
function M(t, n) {
|
|
51
|
+
const s = [];
|
|
52
|
+
let e;
|
|
53
|
+
for (d.lastIndex = 0; e = d.exec(t); ) {
|
|
54
|
+
const i = e[1] ?? e[2] ?? e[3] ?? "", a = A(i);
|
|
55
|
+
a && s.push({ marker: a, start: e.index, end: e.index + e[0].length });
|
|
56
|
+
}
|
|
57
|
+
if (s.length === 0) return null;
|
|
58
|
+
const r = new Map(s.map((i, a) => [i.marker.raw, a])), l = s.map(() => []);
|
|
59
|
+
let c = -1;
|
|
60
|
+
for (const i of n.replace(/\r\n?/g, `
|
|
61
|
+
`).split(`
|
|
62
|
+
`)) {
|
|
63
|
+
const a = r.get(i.trim());
|
|
64
|
+
if (a !== void 0) {
|
|
65
|
+
c = a;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
c >= 0 && l[c].push(i);
|
|
69
|
+
}
|
|
70
|
+
return s.map((i, a) => {
|
|
71
|
+
var f;
|
|
72
|
+
let u = t.slice(i.end, ((f = s[a + 1]) == null ? void 0 : f.start) ?? t.length).replace(N, "").replace(O, "").trim();
|
|
73
|
+
return u || (u = i.marker.value ?? i.marker.title), {
|
|
74
|
+
title: i.marker.title,
|
|
75
|
+
value: i.marker.value,
|
|
76
|
+
command: u,
|
|
77
|
+
output: _(l[a]).join(`
|
|
78
|
+
`)
|
|
79
|
+
};
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
const v = /^\s*(={2,}|-{2,}|#{2,})\s*(.*?)\s*(={2,}|-{2,}|#{2,})?\s*$/, C = /(^|\b)(error|errors|fatal|fail(?:ed|ure|s)?|panic|denied|refused|exception|traceback|cannot|not found|no such|✗|✖|❌|✘)(\b|:)/i, T = /(^|\b)(ok|pass(?:ed|es)?|success(?:ful)?|done|complete[d]?|built|ready|up[- ]to[- ]date|installed|✓|✔|✅|√)(\b|:)/i, I = /(^|\b)(warn(?:ing|ings)?|deprecat(?:ed|ion)|skip(?:ped|ping)?|notice|caution|⚠)(\b|:)/i, S = /(^|\b)(=== RUN|=== CONT|info|note|debug|→|›|»|\$)(\b|\s|$)/, h = /(https?:\/\/[^\s'"]+)|("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')|(\b[0-9a-f]{7,40}\b)|((?:\.{0,2}\/|~\/)[\w./@-]+|\b[\w.-]+\/[\w./@-]+)|(-{1,2}[A-Za-z][\w-]*)|(\b\d+(?:\.\d+)?%?\b)/g;
|
|
83
|
+
function z(t) {
|
|
84
|
+
const n = [];
|
|
85
|
+
let s = 0, e;
|
|
86
|
+
for (h.lastIndex = 0; e = h.exec(t); ) {
|
|
87
|
+
e.index > s && n.push({ text: t.slice(s, e.index) });
|
|
88
|
+
let r;
|
|
89
|
+
e[1] ? r = "url" : e[2] ? r = "string" : e[3] ? r = "hash" : e[4] ? r = "path" : e[5] ? r = "flag" : e[6] && (r = "number"), n.push({ text: e[0], accent: r }), s = e.index + e[0].length;
|
|
90
|
+
}
|
|
91
|
+
return s < t.length && n.push({ text: t.slice(s) }), n.length ? n : [{ text: t }];
|
|
92
|
+
}
|
|
93
|
+
function $(t) {
|
|
94
|
+
var r;
|
|
95
|
+
const n = t.match(v);
|
|
96
|
+
if (!!n && (((r = n[2]) == null ? void 0 : r.length) ?? 0) >= 0 && /^\s*(={2,}|-{3,}|#{2,})/.test(t))
|
|
97
|
+
return { kind: "section", divider: !0, spans: [{ text: n[2] || t.trim() }], raw: t };
|
|
98
|
+
let e = "plain";
|
|
99
|
+
return C.test(t) ? e = "error" : I.test(t) ? e = "warn" : T.test(t) ? e = "success" : S.test(t) && (e = "info"), { kind: e, divider: !1, spans: z(t), raw: t };
|
|
100
|
+
}
|
|
101
|
+
function Z(t, n) {
|
|
102
|
+
const s = n && n.length ? new Map(n.map((e) => [e.raw, e])) : null;
|
|
103
|
+
return t.replace(/\r\n?/g, `
|
|
104
|
+
`).split(`
|
|
105
|
+
`).map((e) => {
|
|
106
|
+
if (s) {
|
|
107
|
+
const r = s.get(e.trim());
|
|
108
|
+
if (r) return { kind: "section", divider: !1, sub: r, spans: [{ text: e }], raw: e };
|
|
109
|
+
}
|
|
110
|
+
return $(e);
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
export {
|
|
114
|
+
$ as classifyLine,
|
|
115
|
+
A as parseMarkerText,
|
|
116
|
+
M as splitBySubparts,
|
|
117
|
+
Z as splitOutput,
|
|
118
|
+
L as tokenizeCommand
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=parse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.js","sources":["../../../src/components/progressive-bash/parse.ts"],"sourcesContent":["// Regex tokenizers that turn a raw shell command and its output into typed\n// spans, so the terminal can colorize them the way a real shell / pager would.\n// Everything here is pure and synchronous — the component colors the *already\n// revealed* substring, so highlighting composes with the typewriter reveal.\n\nexport type CmdKind =\n | 'program'\n | 'subcommand'\n | 'flag'\n | 'string'\n | 'operator'\n | 'path'\n | 'var'\n | 'number'\n | 'comment'\n | 'plain';\n\nexport interface CmdToken {\n text: string;\n kind: CmdKind;\n}\n\nconst OPERATOR = /^(\\|\\||&&|>>|<<|[|&;<>()])/;\nconst STRING = /^(\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|`(?:[^`\\\\]|\\\\.)*`)/;\nconst VAR = /^\\$\\{?[A-Za-z_][A-Za-z0-9_]*\\}?/;\nconst FLAG = /^-{1,2}[A-Za-z0-9][A-Za-z0-9-]*/;\nconst NUMBER = /^\\d+(?:\\.\\d+)?/;\nconst WORD = /^[^\\s|&;<>()]+/;\nconst WS = /^\\s+/;\n\nfunction looksLikePath(word: string): boolean {\n return /[/~]/.test(word) && !/^-/.test(word);\n}\n\n/**\n * Break a shell command into colorable tokens. The first bare word is the\n * program; the next bare word (if it isn't a flag/path) is treated as its\n * subcommand (`git commit`, `docker compose`, `make up`). Whitespace is kept as\n * `plain` tokens so the reconstruction is loss-less.\n */\nexport function tokenizeCommand(command: string): CmdToken[] {\n const tokens: CmdToken[] = [];\n let rest = command;\n let sawProgram = false;\n let sawSubcommand = false;\n // A `#` starting a token runs the rest of the line as a comment.\n const hashAt = command.search(/(^|\\s)#/);\n let commentTail = '';\n if (hashAt >= 0) {\n const idx = command[hashAt] === '#' ? hashAt : hashAt + 1;\n commentTail = command.slice(idx);\n rest = command.slice(0, idx);\n }\n\n while (rest.length > 0) {\n let m: RegExpMatchArray | null;\n if ((m = rest.match(WS))) {\n tokens.push({ text: m[0], kind: 'plain' });\n } else if ((m = rest.match(STRING))) {\n tokens.push({ text: m[0], kind: 'string' });\n } else if ((m = rest.match(OPERATOR))) {\n tokens.push({ text: m[0], kind: 'operator' });\n sawProgram = false; // a new pipeline stage restarts program detection\n sawSubcommand = false;\n } else if ((m = rest.match(VAR))) {\n tokens.push({ text: m[0], kind: 'var' });\n } else if ((m = rest.match(FLAG))) {\n tokens.push({ text: m[0], kind: 'flag' });\n } else if ((m = rest.match(WORD))) {\n const w = m[0];\n let kind: CmdKind;\n if (!sawProgram) {\n kind = 'program';\n sawProgram = true;\n } else if (!sawSubcommand && !looksLikePath(w) && /^[a-z][a-z0-9:._-]*$/i.test(w) && !/[=]/.test(w)) {\n kind = 'subcommand';\n sawSubcommand = true;\n } else if (looksLikePath(w)) {\n kind = 'path';\n } else if (NUMBER.test(w)) {\n kind = 'number';\n } else {\n kind = 'plain';\n }\n tokens.push({ text: w, kind });\n } else {\n tokens.push({ text: rest[0], kind: 'plain' });\n rest = rest.slice(1);\n continue;\n }\n rest = rest.slice(m[0].length);\n }\n if (commentTail) tokens.push({ text: commentTail, kind: 'comment' });\n return tokens;\n}\n\nexport type LineKind = 'section' | 'error' | 'success' | 'warn' | 'info' | 'plain';\n\nexport interface OutputSpan {\n text: string;\n /** Inline accent, layered on top of the line's base color. */\n accent?: 'path' | 'url' | 'number' | 'string' | 'flag' | 'hash';\n}\n\nexport interface OutputLine {\n kind: LineKind;\n /** `true` for `===.*===` / `--- … ---` divider lines (rendered as a bar). */\n divider: boolean;\n /**\n * Set when this line is an `echo \"Title..[value]\"` sub-part marker (see\n * {@link parseEchoMarkers}). The raw echo line is swallowed and rendered as a\n * titled step header instead of plain output.\n */\n sub?: SubMarker;\n spans: OutputSpan[];\n raw: string;\n}\n\n/** A `Title..[value]` step marker echoed inside a compound command. */\nexport interface SubMarker {\n /** The human title (text before `..[`). */\n title: string;\n /** The bracketed tag/value (text inside `[...]`), if any. */\n value?: string;\n /** The exact echoed string, used to match the marker line in the output. */\n raw: string;\n}\n\n// `echo \"Title..[value]\"` / `echo 'Title..[value]'` inside a command.\nconst ECHO_RE = /\\becho\\s+(?:\"([^\"]*)\"|'([^']*)'|([^\\s|&;<>()]+))/g;\nconst MARKER_RE = /^(.*?)\\.\\.\\[([^\\]]*)\\]\\s*$/;\n\n/** Parse `Title..[value]` from a bare echoed string, or `null` if it isn't one. */\nexport function parseMarkerText(text: string): SubMarker | null {\n const m = text.match(MARKER_RE);\n if (!m) return null;\n return { title: m[1].trim(), value: m[2].trim() || undefined, raw: text };\n}\n\n/** One step extracted from a compound `echo \"Title..[value]\" && cmd && …` chain. */\nexport interface SubCommand {\n /** The human title (text before `..[`). */\n title: string;\n /** The bracketed tag/value (text inside `[...]`), if any. */\n value?: string;\n /** The real command that followed the marker (echo statement + connector stripped). */\n command: string;\n /** The step's output — the lines printed after its marker line, up to the next. */\n output: string;\n}\n\n// A shell connector joining chained stages (`a && b`, `a ; b`, `a || b`).\nconst CONNECTOR_LEAD = /^\\s*(?:&&|\\|\\||;|&)\\s*/;\nconst CONNECTOR_TRAIL = /\\s*(?:&&|\\|\\||;|&)\\s*$/;\n\nfunction trimBlankEdges(lines: string[]): string[] {\n let a = 0;\n let b = lines.length;\n while (a < b && lines[a].trim() === '') a++;\n while (b > a && lines[b - 1].trim() === '') b--;\n return lines.slice(a, b);\n}\n\n/**\n * [EXPERIMENTAL] Split a compound `echo \"Title..[value]\" && realcmd && …` chain\n * into its individual steps, pairing each marker's real command with the output\n * lines printed after that marker's echoed line. Returns `null` when the command\n * has no `..[...]` echo markers (nothing to split).\n *\n * This is what lets `ProgressiveBash` expand one chained command into several\n * separate, sequentially-typed command blocks — so a long agent one-liner\n * animates as the individual commands it really ran, filling playback time\n * while a genuinely long command elsewhere is still running.\n */\nexport function splitBySubparts(command: string, output: string): SubCommand[] | null {\n const found: { marker: SubMarker; start: number; end: number }[] = [];\n let m: RegExpExecArray | null;\n ECHO_RE.lastIndex = 0;\n while ((m = ECHO_RE.exec(command))) {\n const text = m[1] ?? m[2] ?? m[3] ?? '';\n const marker = parseMarkerText(text);\n if (marker) found.push({ marker, start: m.index, end: m.index + m[0].length });\n }\n if (found.length === 0) return null;\n\n // Bucket the output: lines after marker i's echoed line (up to the next\n // marker's line) are step i's output; the marker lines themselves are swallowed.\n const rawToIdx = new Map(found.map((f, i) => [f.marker.raw, i]));\n const buckets: string[][] = found.map(() => []);\n let cur = -1;\n for (const line of output.replace(/\\r\\n?/g, '\\n').split('\\n')) {\n const hit = rawToIdx.get(line.trim());\n if (hit !== undefined) {\n cur = hit;\n continue;\n }\n if (cur >= 0) buckets[cur].push(line);\n }\n\n return found.map((f, i) => {\n const raw = command.slice(f.end, found[i + 1]?.start ?? command.length);\n let cmd = raw.replace(CONNECTOR_LEAD, '').replace(CONNECTOR_TRAIL, '').trim();\n if (!cmd) cmd = f.marker.value ?? f.marker.title;\n return {\n title: f.marker.title,\n value: f.marker.value,\n command: cmd,\n output: trimBlankEdges(buckets[i]).join('\\n'),\n };\n });\n}\n\n/**\n * [EXPERIMENTAL] Pull `echo \"Title..[value]\"` step markers out of a compound\n * command. Agents often chain steps like\n * `echo \"Install..[deps]\" && npm i && echo \"Build..[vite]\" && npm run build`;\n * each specially-formatted echo prints a heading into the output that we can\n * then hoist into a titled sub-part (see {@link splitOutput}'s `markers` arg).\n * Only echoes using the `..[...]` syntax are treated as markers — ordinary\n * `echo \"hello\"` lines are left untouched.\n */\nexport function parseEchoMarkers(command: string): SubMarker[] {\n const markers: SubMarker[] = [];\n let m: RegExpExecArray | null;\n ECHO_RE.lastIndex = 0;\n while ((m = ECHO_RE.exec(command))) {\n const text = m[1] ?? m[2] ?? m[3] ?? '';\n const marker = parseMarkerText(text);\n if (marker) markers.push(marker);\n }\n return markers;\n}\n\nconst SECTION_RE = /^\\s*(={2,}|-{2,}|#{2,})\\s*(.*?)\\s*(={2,}|-{2,}|#{2,})?\\s*$/;\nconst ERROR_RE = /(^|\\b)(error|errors|fatal|fail(?:ed|ure|s)?|panic|denied|refused|exception|traceback|cannot|not found|no such|✗|✖|❌|✘)(\\b|:)/i;\nconst SUCCESS_RE = /(^|\\b)(ok|pass(?:ed|es)?|success(?:ful)?|done|complete[d]?|built|ready|up[- ]to[- ]date|installed|✓|✔|✅|√)(\\b|:)/i;\nconst WARN_RE = /(^|\\b)(warn(?:ing|ings)?|deprecat(?:ed|ion)|skip(?:ped|ping)?|notice|caution|⚠)(\\b|:)/i;\nconst INFO_RE = /(^|\\b)(=== RUN|=== CONT|info|note|debug|→|›|»|\\$)(\\b|\\s|$)/;\n\nconst INLINE_RE =\n /(https?:\\/\\/[^\\s'\"]+)|(\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*')|(\\b[0-9a-f]{7,40}\\b)|((?:\\.{0,2}\\/|~\\/)[\\w./@-]+|\\b[\\w.-]+\\/[\\w./@-]+)|(-{1,2}[A-Za-z][\\w-]*)|(\\b\\d+(?:\\.\\d+)?%?\\b)/g;\n\n/** Split one output line into inline-highlighted spans (URLs, paths, …). */\nfunction inlineSpans(text: string): OutputSpan[] {\n const spans: OutputSpan[] = [];\n let last = 0;\n let m: RegExpExecArray | null;\n INLINE_RE.lastIndex = 0;\n while ((m = INLINE_RE.exec(text))) {\n if (m.index > last) spans.push({ text: text.slice(last, m.index) });\n let accent: OutputSpan['accent'];\n if (m[1]) accent = 'url';\n else if (m[2]) accent = 'string';\n else if (m[3]) accent = 'hash';\n else if (m[4]) accent = 'path';\n else if (m[5]) accent = 'flag';\n else if (m[6]) accent = 'number';\n spans.push({ text: m[0], accent });\n last = m.index + m[0].length;\n }\n if (last < text.length) spans.push({ text: text.slice(last) });\n return spans.length ? spans : [{ text }];\n}\n\n/** Classify a single output line and produce its inline spans. */\nexport function classifyLine(line: string): OutputLine {\n const sec = line.match(SECTION_RE);\n const divider = !!sec && (sec[2]?.length ?? 0) >= 0 && /^\\s*(={2,}|-{3,}|#{2,})/.test(line);\n if (divider) {\n return { kind: 'section', divider: true, spans: [{ text: sec![2] || line.trim() }], raw: line };\n }\n let kind: LineKind = 'plain';\n if (ERROR_RE.test(line)) kind = 'error';\n else if (WARN_RE.test(line)) kind = 'warn';\n else if (SUCCESS_RE.test(line)) kind = 'success';\n else if (INFO_RE.test(line)) kind = 'info';\n return { kind, divider: false, spans: inlineSpans(line), raw: line };\n}\n\n/**\n * Split raw output into lines. Blocks delimited by `=== … ===` (or `--- … ---`)\n * lines are kept as their own section markers — this mirrors how test runners\n * (`=== RUN`, `--- PASS`) and check scripts group their output, and lets the\n * player reveal one section at a time.\n *\n * Pass `markers` (from {@link parseEchoMarkers}) to hoist matching\n * `echo \"Title..[value]\"` output lines into titled sub-part headers.\n */\nexport function splitOutput(output: string, markers?: SubMarker[]): OutputLine[] {\n const byRaw = markers && markers.length ? new Map(markers.map((m) => [m.raw, m])) : null;\n return output\n .replace(/\\r\\n?/g, '\\n')\n .split('\\n')\n .map((line) => {\n if (byRaw) {\n const hit = byRaw.get(line.trim());\n if (hit) return { kind: 'section' as LineKind, divider: false, sub: hit, spans: [{ text: line }], raw: line };\n }\n return classifyLine(line);\n });\n}\n"],"names":["OPERATOR","STRING","VAR","FLAG","NUMBER","WORD","WS","looksLikePath","word","tokenizeCommand","command","tokens","rest","sawProgram","sawSubcommand","hashAt","commentTail","idx","m","w","kind","ECHO_RE","MARKER_RE","parseMarkerText","text","CONNECTOR_LEAD","CONNECTOR_TRAIL","trimBlankEdges","lines","a","b","splitBySubparts","output","found","marker","rawToIdx","f","i","buckets","cur","line","hit","_a","cmd","SECTION_RE","ERROR_RE","SUCCESS_RE","WARN_RE","INFO_RE","INLINE_RE","inlineSpans","spans","last","accent","classifyLine","sec","splitOutput","markers","byRaw"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface BashEntry {
|
|
2
|
+
/** Stable id — a growing `entries` array is diffed by id, so streaming in a
|
|
3
|
+
* new batch never re-animates what already played. */
|
|
4
|
+
id: string;
|
|
5
|
+
/** The command line that was typed (the input). */
|
|
6
|
+
command: string;
|
|
7
|
+
/** Combined stdout/stderr the command produced (the output). Optional. */
|
|
8
|
+
output?: string;
|
|
9
|
+
/** Short human note shown as a `# comment` above the command. */
|
|
10
|
+
description?: string;
|
|
11
|
+
/** Working directory / prompt shown before the command. */
|
|
12
|
+
cwd?: string;
|
|
13
|
+
/** Exit status, if known (non-zero paints the prompt red). */
|
|
14
|
+
exitCode?: number;
|
|
15
|
+
/** Marks the whole entry as failed (paints prompt + output red). */
|
|
16
|
+
isError?: boolean;
|
|
17
|
+
/** Wall-clock time (ms since epoch) the command ran — drives the gap timing. */
|
|
18
|
+
timestamp?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface PlaybackTuning {
|
|
21
|
+
/** Command typing rate, characters per second. */
|
|
22
|
+
typeSpeed: number;
|
|
23
|
+
/** Output reveal rate, lines per second. */
|
|
24
|
+
outputSpeed: number;
|
|
25
|
+
/** Fixed seconds between entries; overrides timestamp-derived gaps when set. */
|
|
26
|
+
fixedDelay?: number;
|
|
27
|
+
/** Floor for a computed inter-entry gap (ms). */
|
|
28
|
+
minGapMs: number;
|
|
29
|
+
/** Ceiling for a computed inter-entry gap (ms). */
|
|
30
|
+
maxGapMs: number;
|
|
31
|
+
/** Real-gap size (ms) that maps to ~76% of the way to `maxGapMs`. */
|
|
32
|
+
gapReferenceMs: number;
|
|
33
|
+
/** Beat between finishing the command and its output starting (ms). */
|
|
34
|
+
thinkMs: number;
|
|
35
|
+
}
|
|
36
|
+
export declare const DEFAULT_TUNING: PlaybackTuning;
|
|
37
|
+
/**
|
|
38
|
+
* Compress a real time-gap into a fixed, bounded playback delay.
|
|
39
|
+
*
|
|
40
|
+
* A batch of commands can span seconds or many minutes of wall-clock time;
|
|
41
|
+
* replaying those gaps verbatim would leave the terminal frozen. Instead we map
|
|
42
|
+
* the real gap through a saturating curve so the *ordering and relative pacing*
|
|
43
|
+
* of the timestamps is preserved (a long think reads as a longer pause) while
|
|
44
|
+
* the animation still plays continuously: every gap lands in
|
|
45
|
+
* `[minGapMs, maxGapMs]`, and `gapReferenceMs` sets how quickly it saturates.
|
|
46
|
+
*
|
|
47
|
+
* With no timestamps (or a `fixedDelay`) it returns a constant delay.
|
|
48
|
+
*/
|
|
49
|
+
export declare function computeGapMs(prevTs: number | undefined, ts: number | undefined, t: PlaybackTuning): number;
|
|
50
|
+
//# sourceMappingURL=playback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playback.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-bash/playback.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB;2DACuD;IACvD,EAAE,EAAE,MAAM,CAAC;IACX,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oEAAoE;IACpE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,gFAAgF;IAChF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,cAAc,EAAE,cAO5B,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,CAAC,EAAE,cAAc,GAChB,MAAM,CAOR"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const t = {
|
|
2
|
+
typeSpeed: 55,
|
|
3
|
+
outputSpeed: 24,
|
|
4
|
+
minGapMs: 220,
|
|
5
|
+
maxGapMs: 1400,
|
|
6
|
+
gapReferenceMs: 45e3,
|
|
7
|
+
thinkMs: 260
|
|
8
|
+
};
|
|
9
|
+
function s(e, n, a) {
|
|
10
|
+
if (a.fixedDelay != null) return Math.max(0, a.fixedDelay * 1e3);
|
|
11
|
+
if (e == null || n == null) return a.minGapMs;
|
|
12
|
+
const M = Math.max(0, n - e), p = Math.tanh(M / Math.max(1, a.gapReferenceMs));
|
|
13
|
+
return Math.round(a.minGapMs + (a.maxGapMs - a.minGapMs) * p);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
t as DEFAULT_TUNING,
|
|
17
|
+
s as computeGapMs
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=playback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playback.js","sources":["../../../src/components/progressive-bash/playback.ts"],"sourcesContent":["// Playback model for ProgressiveBash: the entry shape and the timestamp → delay\n// compression that turns a sparse, real-time batch of commands into a lively,\n// continuous animation.\n\nexport interface BashEntry {\n /** Stable id — a growing `entries` array is diffed by id, so streaming in a\n * new batch never re-animates what already played. */\n id: string;\n /** The command line that was typed (the input). */\n command: string;\n /** Combined stdout/stderr the command produced (the output). Optional. */\n output?: string;\n /** Short human note shown as a `# comment` above the command. */\n description?: string;\n /** Working directory / prompt shown before the command. */\n cwd?: string;\n /** Exit status, if known (non-zero paints the prompt red). */\n exitCode?: number;\n /** Marks the whole entry as failed (paints prompt + output red). */\n isError?: boolean;\n /** Wall-clock time (ms since epoch) the command ran — drives the gap timing. */\n timestamp?: number;\n}\n\nexport interface PlaybackTuning {\n /** Command typing rate, characters per second. */\n typeSpeed: number;\n /** Output reveal rate, lines per second. */\n outputSpeed: number;\n /** Fixed seconds between entries; overrides timestamp-derived gaps when set. */\n fixedDelay?: number;\n /** Floor for a computed inter-entry gap (ms). */\n minGapMs: number;\n /** Ceiling for a computed inter-entry gap (ms). */\n maxGapMs: number;\n /** Real-gap size (ms) that maps to ~76% of the way to `maxGapMs`. */\n gapReferenceMs: number;\n /** Beat between finishing the command and its output starting (ms). */\n thinkMs: number;\n}\n\nexport const DEFAULT_TUNING: PlaybackTuning = {\n typeSpeed: 55,\n outputSpeed: 24,\n minGapMs: 220,\n maxGapMs: 1400,\n gapReferenceMs: 45_000,\n thinkMs: 260,\n};\n\n/**\n * Compress a real time-gap into a fixed, bounded playback delay.\n *\n * A batch of commands can span seconds or many minutes of wall-clock time;\n * replaying those gaps verbatim would leave the terminal frozen. Instead we map\n * the real gap through a saturating curve so the *ordering and relative pacing*\n * of the timestamps is preserved (a long think reads as a longer pause) while\n * the animation still plays continuously: every gap lands in\n * `[minGapMs, maxGapMs]`, and `gapReferenceMs` sets how quickly it saturates.\n *\n * With no timestamps (or a `fixedDelay`) it returns a constant delay.\n */\nexport function computeGapMs(\n prevTs: number | undefined,\n ts: number | undefined,\n t: PlaybackTuning,\n): number {\n if (t.fixedDelay != null) return Math.max(0, t.fixedDelay * 1000);\n if (prevTs == null || ts == null) return t.minGapMs;\n const delta = Math.max(0, ts - prevTs);\n // tanh saturates: delta == gapReferenceMs → ~0.76 of the min→max span.\n const frac = Math.tanh(delta / Math.max(1, t.gapReferenceMs));\n return Math.round(t.minGapMs + (t.maxGapMs - t.minGapMs) * frac);\n}\n"],"names":["DEFAULT_TUNING","computeGapMs","prevTs","ts","t","delta","frac"],"mappings":"AAyCO,MAAMA,IAAiC;AAAA,EAC5C,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA,EACV,UAAU;AAAA,EACV,gBAAgB;AAAA,EAChB,SAAS;AACX;AAcO,SAASC,EACdC,GACAC,GACAC,GACQ;AACR,MAAIA,EAAE,cAAc,KAAM,QAAO,KAAK,IAAI,GAAGA,EAAE,aAAa,GAAI;AAChE,MAAIF,KAAU,QAAQC,KAAM,aAAaC,EAAE;AAC3C,QAAMC,IAAQ,KAAK,IAAI,GAAGF,IAAKD,CAAM,GAE/BI,IAAO,KAAK,KAAKD,IAAQ,KAAK,IAAI,GAAGD,EAAE,cAAc,CAAC;AAC5D,SAAO,KAAK,MAAMA,EAAE,YAAYA,EAAE,WAAWA,EAAE,YAAYE,CAAI;AACjE;"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { CSSProperties, Ref } from 'react';
|
|
2
|
+
import { BashEntry } from './playback';
|
|
3
|
+
export type { BashEntry, PlaybackTuning } from './playback';
|
|
4
|
+
/** Imperative handle for feeding entries and driving the terminal. */
|
|
5
|
+
export interface ProgressiveBashHandle {
|
|
6
|
+
/** Append one or more entries (deduped by id). Plays continuously. */
|
|
7
|
+
push: (entry: BashEntry | BashEntry[]) => void;
|
|
8
|
+
/** Remove everything and reset the playhead. */
|
|
9
|
+
clear: () => void;
|
|
10
|
+
/** Reveal every entry instantly (skip the animation). */
|
|
11
|
+
skipToEnd: () => void;
|
|
12
|
+
/** Force the scroll view to the latest line. */
|
|
13
|
+
scrollToBottom: () => void;
|
|
14
|
+
}
|
|
15
|
+
export interface ProgressiveBashProps {
|
|
16
|
+
/**
|
|
17
|
+
* The command/output series to play, oldest → newest. Growing this array (a
|
|
18
|
+
* fresh batch streamed in) appends to the queue; already-played entries are
|
|
19
|
+
* never re-animated. You can also feed entries imperatively via
|
|
20
|
+
* {@link ProgressiveBashHandle.push} — both merge, deduped by `id`.
|
|
21
|
+
*/
|
|
22
|
+
entries?: BashEntry[];
|
|
23
|
+
/** Command typing rate, chars/sec. @default 55 */
|
|
24
|
+
typeSpeed?: number;
|
|
25
|
+
/** Output reveal rate, lines/sec. @default 24 */
|
|
26
|
+
outputSpeed?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Fixed seconds between entries. When omitted, gaps are derived from each
|
|
29
|
+
* entry's `timestamp` and compressed into a lively, bounded, continuous
|
|
30
|
+
* playback (see {@link computeGapMs}).
|
|
31
|
+
*/
|
|
32
|
+
delay?: number;
|
|
33
|
+
/** Floor / ceiling / saturation for timestamp-derived gaps (ms). */
|
|
34
|
+
minGap?: number;
|
|
35
|
+
maxGap?: number;
|
|
36
|
+
gapReference?: number;
|
|
37
|
+
/** Pause between a typed command and its output (ms). @default 260 */
|
|
38
|
+
think?: number;
|
|
39
|
+
/** Reveal everything immediately (or honors `prefers-reduced-motion`). */
|
|
40
|
+
instant?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* "Join in progress" — when the terminal mounts, every entry whose
|
|
43
|
+
* `timestamp` is already in the past relative to this reference is rendered
|
|
44
|
+
* fully-written (no replay), and live typing resumes at the first entry
|
|
45
|
+
* at/after it. Pass a wall-clock ms reference, or `true` for `Date.now()`.
|
|
46
|
+
* This is what stops a page reload from re-typing a whole finished session.
|
|
47
|
+
*/
|
|
48
|
+
catchUp?: number | boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Pin each command's prompt line to the top of the scroll viewport, so while
|
|
51
|
+
* a long output scrolls by you can still see which command produced it (the
|
|
52
|
+
* next command's prompt pushes the previous one up, like sticky table
|
|
53
|
+
* headers). @default false
|
|
54
|
+
*/
|
|
55
|
+
stickyPrompt?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* [EXPERIMENTAL] Split a chained `echo "Title..[value]" && cmd && …` command
|
|
58
|
+
* (see {@link splitBySubparts}) into one separate command block per step, each
|
|
59
|
+
* pairing the real command with the output printed after its marker — so the
|
|
60
|
+
* terminal types several sequential commands instead of one long chain. Useful
|
|
61
|
+
* to keep the terminal visually busy (and buy time) while a genuinely long
|
|
62
|
+
* command elsewhere is still running. @default false
|
|
63
|
+
*/
|
|
64
|
+
experimentalSubparts?: boolean;
|
|
65
|
+
/** Prompt glyph shown before each command. @default '❯' */
|
|
66
|
+
prompt?: string;
|
|
67
|
+
/** Show each entry's `description` as a `# comment` line. @default true */
|
|
68
|
+
showDescriptions?: boolean;
|
|
69
|
+
/** Fired when the playhead catches up to the last known entry. */
|
|
70
|
+
onIdle?: () => void;
|
|
71
|
+
className?: string;
|
|
72
|
+
bodyClassName?: string;
|
|
73
|
+
/** Override any of the terminal color CSS vars (`--tb-*`). */
|
|
74
|
+
style?: CSSProperties;
|
|
75
|
+
apiRef?: Ref<ProgressiveBashHandle>;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* An animated terminal that "types" a series of shell commands and reveals each
|
|
79
|
+
* command's output line-by-line — turning an intermittent batch of
|
|
80
|
+
* command/output records into a continuously-playing terminal. Commands and
|
|
81
|
+
* output are regex-tokenized and colorized like a real shell + pager (programs,
|
|
82
|
+
* flags, paths, URLs, pass/fail lines, `=== section ===` dividers).
|
|
83
|
+
*
|
|
84
|
+
* Feed it via the `entries` prop (append to stream more) or imperatively via
|
|
85
|
+
* `apiRef.push(...)`. Timestamps on entries are compressed into a lively,
|
|
86
|
+
* bounded inter-command delay so replay stays continuous no matter how sparse
|
|
87
|
+
* the real timing was. The view auto-scrolls to the newest line but releases
|
|
88
|
+
* that lock the moment you scroll up (like a chat log).
|
|
89
|
+
*
|
|
90
|
+
* Extras: `catchUp` renders already-past entries fully-written on mount (a
|
|
91
|
+
* reload doesn't re-type a finished session); `stickyPrompt` pins each
|
|
92
|
+
* command's prompt line to the top while its output scrolls; and
|
|
93
|
+
* `experimentalSubparts` splits a chained `echo "Title..[value]" && cmd` command
|
|
94
|
+
* into several separate, sequentially-typed command blocks.
|
|
95
|
+
*/
|
|
96
|
+
export declare function ProgressiveBash({ entries, typeSpeed, outputSpeed, delay, minGap, maxGap, gapReference, think, instant, catchUp, stickyPrompt, experimentalSubparts, prompt, showDescriptions, onIdle, className, bodyClassName, style, apiRef, }: ProgressiveBashProps): import("react").JSX.Element;
|
|
97
|
+
//# sourceMappingURL=progressive-bash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progressive-bash.d.ts","sourceRoot":"","sources":["../../../src/components/progressive-bash/progressive-bash.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAWf,OAAO,EAAgC,KAAK,SAAS,EAAuB,MAAM,YAAY,CAAC;AAE/F,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5D,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACpC,sEAAsE;IACtE,IAAI,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C,gDAAgD;IAChD,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,yDAAyD;IACzD,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,gDAAgD;IAChD,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iDAAiD;IACjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0EAA0E;IAC1E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,MAAM,CAAC,EAAE,GAAG,CAAC,qBAAqB,CAAC,CAAC;CACrC;AA8HD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,OAAO,EACP,SAAoC,EACpC,WAAwC,EACxC,KAAK,EACL,MAAgC,EAChC,MAAgC,EAChC,YAA4C,EAC5C,KAA8B,EAC9B,OAAe,EACf,OAAO,EACP,YAAoB,EACpB,oBAA4B,EAC5B,MAAY,EACZ,gBAAuB,EACvB,MAAM,EACN,SAAS,EACT,aAAa,EACb,KAAK,EACL,MAAM,GACP,EAAE,oBAAoB,+BAmUtB"}
|