From 3d1182705e3f81dfe2d6cb914ce806931f637c0b Mon Sep 17 00:00:00 2001 From: Jwaegebaert <38426621+Jwaegebaert@users.noreply.github.com> Date: Thu, 12 Mar 2026 22:14:46 +0100 Subject: [PATCH 1/2] Removes Asciinema players with custom CommandPlayer. Closes #7130 --- docs/docs/index.mdx | 11 +- .../user-guide/connecting-microsoft-365.mdx | 5 +- docs/docs/user-guide/installing-cli.mdx | 6 - docs/docs/user-guide/using-cli.mdx | 9 +- docs/docusaurus.config.ts | 13 +- docs/package-lock.json | 108 +--- docs/package.json | 2 +- docs/src/components/AsciinemaPlayer.tsx | 53 -- docs/src/components/CommandPlayer.tsx | 527 ++++++++++++++++++ docs/src/components/responses/help-spo.txt | 47 ++ .../components/responses/spo-cdn-get-help.txt | 31 ++ docs/src/remark/commandPlayer.ts | 315 +++++++++++ docs/src/scss/CommandPlayer.module.scss | 244 ++++++++ docs/static/casts/commandHelp.cast | 59 -- docs/static/casts/home.cast | 62 --- docs/static/casts/install.cast | 99 ---- docs/static/casts/listCommands.cast | 91 --- docs/static/casts/logout.cast | 57 -- docs/static/casts/usingCli.cast | 68 --- 19 files changed, 1198 insertions(+), 609 deletions(-) delete mode 100644 docs/src/components/AsciinemaPlayer.tsx create mode 100644 docs/src/components/CommandPlayer.tsx create mode 100644 docs/src/components/responses/help-spo.txt create mode 100644 docs/src/components/responses/spo-cdn-get-help.txt create mode 100644 docs/src/remark/commandPlayer.ts create mode 100644 docs/src/scss/CommandPlayer.module.scss delete mode 100644 docs/static/casts/commandHelp.cast delete mode 100644 docs/static/casts/home.cast delete mode 100644 docs/static/casts/install.cast delete mode 100644 docs/static/casts/listCommands.cast delete mode 100644 docs/static/casts/logout.cast delete mode 100644 docs/static/casts/usingCli.cast diff --git a/docs/docs/index.mdx b/docs/docs/index.mdx index ca9724a00b5..4cb6d677a2f 100644 --- a/docs/docs/index.mdx +++ b/docs/docs/index.mdx @@ -1,11 +1,16 @@ -import AsciinemaPlayer from '@site/src/components/AsciinemaPlayer'; -import 'asciinema-player/dist/bundle/asciinema-player.css'; +import CommandPlayer from '@site/src/components/CommandPlayer'; # CLI for Microsoft 365 Using the CLI for Microsoft 365, you can manage your Microsoft 365 tenant and SharePoint Framework projects on any platform. No matter if you are on Windows, macOS or Linux, using Bash, Cmder or PowerShell, using the CLI for Microsoft 365 you can configure Microsoft 365, manage SharePoint Framework projects and build automation scripts. - + ## Installation diff --git a/docs/docs/user-guide/connecting-microsoft-365.mdx b/docs/docs/user-guide/connecting-microsoft-365.mdx index a7d7f5f4836..fd8d1ae8c60 100644 --- a/docs/docs/user-guide/connecting-microsoft-365.mdx +++ b/docs/docs/user-guide/connecting-microsoft-365.mdx @@ -3,8 +3,7 @@ title: Log in to Microsoft 365 sidebar_position: 3 --- -import AsciinemaPlayer from '@site/src/components/AsciinemaPlayer'; -import 'asciinema-player/dist/bundle/asciinema-player.css'; +import CommandPlayer from '@site/src/components/CommandPlayer'; # Log in to Microsoft 365 @@ -188,7 +187,7 @@ If you're logged in to Microsoft 365 using a certificate, the `status` command w To log out from Microsoft 365, use the `logout` command. Executing the `logout` command removes all connection information such as user name, refresh or access tokens stored on your computer. - + ### Working with SharePoint Online diff --git a/docs/docs/user-guide/installing-cli.mdx b/docs/docs/user-guide/installing-cli.mdx index 5cb0581813e..f14d31e8a5f 100644 --- a/docs/docs/user-guide/installing-cli.mdx +++ b/docs/docs/user-guide/installing-cli.mdx @@ -3,8 +3,6 @@ title: Install the CLI sidebar_position: 1 --- -import AsciinemaPlayer from '@site/src/components/AsciinemaPlayer'; -import 'asciinema-player/dist/bundle/asciinema-player.css'; # Install the CLI for Microsoft 365 @@ -26,10 +24,6 @@ To install the CLI for Microsoft 365, in the command line execute: npm install -g @pnp/cli-microsoft365 ``` - - -
- If you're using Yarn, you can install the CLI for Microsoft 365 by executing: ```sh diff --git a/docs/docs/user-guide/using-cli.mdx b/docs/docs/user-guide/using-cli.mdx index 8af7d4d9437..b0b2fe2d990 100644 --- a/docs/docs/user-guide/using-cli.mdx +++ b/docs/docs/user-guide/using-cli.mdx @@ -3,8 +3,7 @@ title: Use the CLI sidebar_position: 2 --- -import AsciinemaPlayer from '@site/src/components/AsciinemaPlayer'; -import 'asciinema-player/dist/bundle/asciinema-player.css'; +import CommandPlayer from '@site/src/components/CommandPlayer'; # Use the CLI for Microsoft 365 @@ -14,7 +13,7 @@ Information in this section will help you understand how the CLI for Microsoft 3 To use CLI for Microsoft 365, execute specific commands directly from the command line. - +
@@ -32,7 +31,7 @@ To list commands available with the CLI for Microsoft 365 type `help` in the CLI Commands in the CLI for Microsoft 365 are combined into groups. You can list the commands available in the particular group by typing `help `, for example `help spo` to list all commands related to SharePoint Online, or `m365 help spo` directly in your shell. - + ## Get command help @@ -40,7 +39,7 @@ Each command in the CLI for Microsoft 365 comes with help describing the command To get the complete help information including background information, examples and links to related information, use the `--help` option, for example `m365 spo cdn get --help`. This ability is also useful if you've already typed some options and don't want to lose your input but want to access the help, for example: `m365 spo cdn get --type Private --help`. - + ## Required and optional command options diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 26f6d96206f..7ce0d8d7ecb 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -5,6 +5,7 @@ import { existsSync, readFileSync } from 'node:fs'; import LightCodeTheme from './src/config/lightCodeTheme'; import DarkCodeTheme from './src/config/darkCodeTheme'; import definitionList from './src/remark/definitionLists'; +import commandPlayer from './src/remark/commandPlayer'; const hasStableVersion = existsSync('versions.json'); const stableVersion = hasStableVersion @@ -24,6 +25,14 @@ const config: Config = { organizationName: 'pnp', projectName: 'cli-microsoft365', + headTags: [ + { + tagName: 'script', + attributes: { type: 'text/javascript' }, + innerHTML: 'window.gtag=window.gtag||function(){(window.dataLayer=window.dataLayer||[]).push(arguments)};' + } + ], + i18n: { defaultLocale: 'en', locales: ['en'] @@ -77,7 +86,7 @@ const config: Config = { editUrl: ({ docPath }) => `https://github.com/pnp/cli-microsoft365/blob/main/docs/docs/${docPath}`, showLastUpdateTime: true, - remarkPlugins: [definitionList], + remarkPlugins: [definitionList, commandPlayer], ...hasStableVersion && { lastVersion: stableVersion, versions: { @@ -95,7 +104,7 @@ const config: Config = { }, blog: false, theme: { - customCss: ['./src/scss/Global.module.scss'] + customCss: ['./src/scss/Global.module.scss', './src/scss/CommandPlayer.module.scss'] }, gtag: { trackingID: 'G-DH3T88LK5K', diff --git a/docs/package-lock.json b/docs/package-lock.json index fa05711d35c..9fefee97ef5 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -26,7 +26,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "asciinema-player": "^3.15.1", + "baseline-browser-mapping": "^2.10.8", "typescript": "^5.9.3" }, "engines": { @@ -5187,39 +5187,6 @@ "micromark-util-symbol": "^1.0.1" } }, - "node_modules/@solid-primitives/refs": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@solid-primitives/refs/-/refs-1.1.2.tgz", - "integrity": "sha512-K7tf2thy7L+YJjdqXspXOg5xvNEOH8tgEWsp0+1mQk3obHBRD6hEjYZk7p7FlJphSZImS35je3UfmWuD7MhDfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@solid-primitives/utils": "^6.3.2" - }, - "peerDependencies": { - "solid-js": "^1.6.12" - } - }, - "node_modules/@solid-primitives/transition-group": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.1.2.tgz", - "integrity": "sha512-gnHS0OmcdjeoHN9n7Khu8KNrOlRc8a2weETDt2YT6o1zeW/XtUC6Db3Q9pkMU/9cCKdEmN4b0a/41MKAHRhzWA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "solid-js": "^1.6.12" - } - }, - "node_modules/@solid-primitives/utils": { - "version": "6.3.2", - "resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.3.2.tgz", - "integrity": "sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "solid-js": "^1.6.12" - } - }, "node_modules/@standard-schema/spec": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", @@ -7033,18 +7000,6 @@ "node": ">=8" } }, - "node_modules/asciinema-player": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/asciinema-player/-/asciinema-player-3.15.1.tgz", - "integrity": "sha512-agVYeNlPxthLyAb92l9AS7ypW0uhesqOuQzyR58Q4Sj+MvesQztZBgx86lHqNJkB8rQ6EP0LeA9czGytQUBpYw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@babel/runtime": "^7.21.0", - "solid-js": "^1.3.0", - "solid-transition-group": "^0.2.3" - } - }, "node_modules/astring": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", @@ -7182,12 +7137,15 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.23", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.23.tgz", - "integrity": "sha512-616V5YX4bepJFzNyOfce5Fa8fDJMfoxzOIzDCZwaGL8MKVpFrXqfNUoIpRn9YMI5pXf/VKgzjB4htFMsFKKdiQ==", + "version": "2.10.8", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", + "integrity": "sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==", "license": "Apache-2.0", "bin": { - "baseline-browser-mapping": "dist/cli.js" + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/batch": { @@ -18351,27 +18309,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/seroval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/seroval/-/seroval-1.1.1.tgz", - "integrity": "sha512-rqEO6FZk8mv7Hyv4UCj3FD3b6Waqft605TLfsCe/BiaylRpyyMC0b+uA5TJKawX3KzMrdi3wsLbCaLplrQmBvQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/seroval-plugins": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/seroval-plugins/-/seroval-plugins-1.1.1.tgz", - "integrity": "sha512-qNSy1+nUj7hsCOon7AO4wdAIo9P0jrzAMp18XhiOzA6/uO5TKtP7ScozVJ8T293oRIvi5wyCHSM4TrJo/c/GJA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "seroval": "^1.0" - } - }, "node_modules/serve-handler": { "version": "6.1.6", "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", @@ -18729,35 +18666,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/solid-js": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.9.3.tgz", - "integrity": "sha512-5ba3taPoZGt9GY3YlsCB24kCg0Lv/rie/HTD4kG6h4daZZz7+yK02xn8Vx8dLYBc9i6Ps5JwAbEiqjmKaLB3Ag==", - "dev": true, - "dependencies": { - "csstype": "^3.1.0", - "seroval": "^1.1.0", - "seroval-plugins": "^1.1.0" - } - }, - "node_modules/solid-transition-group": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/solid-transition-group/-/solid-transition-group-0.2.3.tgz", - "integrity": "sha512-iB72c9N5Kz9ykRqIXl0lQohOau4t0dhel9kjwFvx81UZJbVwaChMuBuyhiZmK24b8aKEK0w3uFM96ZxzcyZGdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@solid-primitives/refs": "^1.0.5", - "@solid-primitives/transition-group": "^1.0.2" - }, - "engines": { - "node": ">=18.0.0", - "pnpm": ">=8.6.0" - }, - "peerDependencies": { - "solid-js": "^1.6.12" - } - }, "node_modules/sort-css-media-queries": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", diff --git a/docs/package.json b/docs/package.json index 1a63f304431..e5b5d504b95 100644 --- a/docs/package.json +++ b/docs/package.json @@ -33,7 +33,7 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "asciinema-player": "^3.15.1", + "baseline-browser-mapping": "^2.10.8", "typescript": "^5.9.3" }, "browserslist": { diff --git a/docs/src/components/AsciinemaPlayer.tsx b/docs/src/components/AsciinemaPlayer.tsx deleted file mode 100644 index 8df64b88431..00000000000 --- a/docs/src/components/AsciinemaPlayer.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import BrowserOnly from '@docusaurus/BrowserOnly'; -import useBaseUrl from '@docusaurus/useBaseUrl'; - -type AsciinemaPlayerProps = { - src: string; - // START asciinemaOptions - cols: string; - rows: string; - autoPlay: boolean; - preload: boolean; - loop: boolean | number; - startAt: number | string; - speed: number; - idleTimeLimit: number; - theme: string; - poster: string; - fit: string; - fontSize: string; - // END asciinemaOptions -}; - -const AsciinemaPlayerComponent: React.FC = ({ - src, - ...asciinemaOptions -}) => { - const ref = useRef(null); - const [isMounted, setIsMounted] = useState(false); - const resolvedSrc = useBaseUrl(src); - - useEffect(() => { - setIsMounted(true); - }, []); - - useEffect(() => { - const loadAsciinemaPlayer = async () => { - if (ref.current && isMounted) { - const AsciinemaPlayerLibrary = await import('asciinema-player'); - AsciinemaPlayerLibrary.create(resolvedSrc, ref.current, asciinemaOptions); - } - }; - - loadAsciinemaPlayer(); - }, [resolvedSrc, asciinemaOptions, isMounted]); - - return ( - }> - {() =>
} - - ); -}; - -export default AsciinemaPlayerComponent; \ No newline at end of file diff --git a/docs/src/components/CommandPlayer.tsx b/docs/src/components/CommandPlayer.tsx new file mode 100644 index 00000000000..0a76da8029c --- /dev/null +++ b/docs/src/components/CommandPlayer.tsx @@ -0,0 +1,527 @@ +import React, { useEffect, useRef, useState, useCallback, useMemo } from 'react'; + +type CommandStep = { + command: string; + response?: string; + responseFrom?: string; +}; + +type CommandPlayerProps = { + command?: string; + response?: string; + commands?: CommandStep[]; + typingSpeed?: number; + responseDelay?: number; + loopDelay?: number; +}; + +function highlightJson(json: string): React.ReactNode[] { + const nodes: React.ReactNode[] = []; + const tokenRegex = /("(?:[^"\\]|\\.)*")\s*(?=:)|("(?:[^"\\]|\\.)*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)\b|(true|false)\b|(null)\b|([{}[\]:,])/g; + + let lastIndex = 0; + let match: RegExpExecArray | null; + + while ((match = tokenRegex.exec(json)) !== null) { + if (match.index > lastIndex) { + nodes.push({json.slice(lastIndex, match.index)}); + } + const [full, key, str, num, bool, nul, punct] = match; + if (key !== undefined) nodes.push({key}); + else if (str !== undefined) nodes.push({str}); + else if (num !== undefined) nodes.push({num}); + else if (bool !== undefined) nodes.push({bool}); + else if (nul !== undefined) nodes.push({nul}); + else if (punct !== undefined) nodes.push({punct}); + lastIndex = match.index + full.length; + } + if (lastIndex < json.length) { + nodes.push({json.slice(lastIndex)}); + } + return nodes; +} + +function prefersReducedMotion(): boolean { + return typeof window !== 'undefined' + && window.matchMedia('(prefers-reduced-motion: reduce)').matches; +} + +function naturalDelay(base: number, char: string, prev: string): number { + let delay = base * (0.3 + Math.random() * 1.5); + + if (char === ' ') delay += base * (0.3 + Math.random() * 1.2); + else if (char === '-' && prev === '-') delay += base * (0.1 + Math.random() * 0.4); + else if (char === '-' && prev === ' ') delay += base * (0.5 + Math.random() * 1.5); + else if (char === '/' || char === '\\') delay += base * (0.2 + Math.random() * 0.5); + else if (prev && prev === prev.toUpperCase() && prev !== prev.toLowerCase()) delay += base * 0.15; + + if (Math.random() < 0.10) delay += base * (1.5 + Math.random() * 4); + if (Math.random() < 0.18) delay *= 0.25; + if (Math.random() < 0.05) return Math.max(12, base * 0.15); + + return Math.max(delay, 12); +} + +function isScrolledToBottom(el: HTMLElement): boolean { + return el.scrollHeight - el.scrollTop - el.clientHeight < 5; +} + +type Phase = 'idle' | 'typing-command' | 'showing-response' | 'typing-clear' | 'clearing'; + +const BETWEEN_STEP_MIN = 1500; +const BETWEEN_STEP_JITTER = 2500; +const SCROLL_DETECT_TIMEOUT = 200; +const RING_RADIUS = 9; +const CLEAR_EXECUTE_DELAY = 300; +const CLEAR_PAUSE_BEFORE_EXECUTE = 200; + +function betweenStepDelay(): number { + return BETWEEN_STEP_MIN + Math.random() * BETWEEN_STEP_JITTER; +} + +function randomResponseDelay(base: number): number { + if (Math.random() < 0.2) return base * (0.15 + Math.random() * 0.25); + if (Math.random() < 0.15) return base * (1.5 + Math.random() * 1.5); + return base * (0.5 + Math.random() * 1.0); +} + +function initialPause(isFirstStep: boolean): number { + if (isFirstStep) return 300 + Math.random() * 500; + return 200 + Math.random() * 400; +} + +const AUTO_RESUME_DELAY = 30_000; + +const PauseIcon: React.FC = () => ( + + + + +); + +const PlayIcon: React.FC = () => ( + + + +); + +const CommandPlayer: React.FC = ({ + command, + response, + commands, + typingSpeed = 45, + responseDelay = 500, + loopDelay = 4 +}) => { + const containerRef = useRef(null); + const bodyRef = useRef(null); + const [mounted, setMounted] = useState(false); + const cancelRef = useRef({ cancelled: false }); + + const pausedRef = useRef(false); + const [isPaused, setIsPaused] = useState(false); + const manualPauseRef = useRef(false); + const scrollPauseRef = useRef(false); + const autoResumeTimerRef = useRef | null>(null); + const ringAnimFrameRef = useRef(null); + const ringRef = useRef(null); + const ringStartTimeRef = useRef(0); + const [scrollPauseActive, setScrollPauseActive] = useState(false); + + const steps = useMemo(() => { + if (commands && commands.length > 0) return commands; + if (command) return [{ command, response }]; + return []; + }, [commands, command, response]); + + const formattedResponses = useMemo(() => { + return steps.map(step => { + if (!step.response) return ''; + try { return JSON.stringify(JSON.parse(step.response), null, 2); } + catch { return step.response.replace(/\\n/g, '\n'); } + }); + }, [steps]); + + const [displayedSteps, setDisplayedSteps] = useState(0); + const [typedCommand, setTypedCommand] = useState(''); + const [showCurrentResponse, setShowCurrentResponse] = useState(false); + const [typedClear, setTypedClear] = useState(''); + const [showClearPrompt, setShowClearPrompt] = useState(false); + const [phase, setPhase] = useState('idle'); + + useEffect(() => { setMounted(true); }, []); + + const ringCircumference = 2 * Math.PI * RING_RADIUS; + + const clearAutoResumeTimer = useCallback(() => { + if (autoResumeTimerRef.current) { + clearTimeout(autoResumeTimerRef.current); + autoResumeTimerRef.current = null; + } + if (ringAnimFrameRef.current) { + cancelAnimationFrame(ringAnimFrameRef.current); + ringAnimFrameRef.current = null; + } + setScrollPauseActive(false); + }, []); + + useEffect(() => { + if (!scrollPauseActive) return; + const startTime = ringStartTimeRef.current; + const animate = (): void => { + const elapsed = Date.now() - startTime; + const progress = Math.min(1, elapsed / AUTO_RESUME_DELAY); + if (ringRef.current) { + ringRef.current.style.strokeDashoffset = String(ringCircumference * (1 - progress)); + } + if (progress < 1 && pausedRef.current) { + ringAnimFrameRef.current = requestAnimationFrame(animate); + } + }; + ringAnimFrameRef.current = requestAnimationFrame(animate); + return () => { + if (ringAnimFrameRef.current) { + cancelAnimationFrame(ringAnimFrameRef.current); + ringAnimFrameRef.current = null; + } + }; + }, [scrollPauseActive, ringCircumference]); + + const doPause = useCallback((source: 'manual' | 'scroll') => { + if (source === 'manual') manualPauseRef.current = true; + if (source === 'scroll') scrollPauseRef.current = true; + pausedRef.current = true; + setIsPaused(true); + clearAutoResumeTimer(); + + if (source === 'scroll') { + ringStartTimeRef.current = Date.now(); + setScrollPauseActive(true); + autoResumeTimerRef.current = setTimeout(() => { + scrollPauseRef.current = false; + pausedRef.current = false; + setIsPaused(false); + setScrollPauseActive(false); + }, AUTO_RESUME_DELAY); + } + }, [clearAutoResumeTimer]); + + const doResume = useCallback(() => { + manualPauseRef.current = false; + scrollPauseRef.current = false; + pausedRef.current = false; + setIsPaused(false); + clearAutoResumeTimer(); + }, [clearAutoResumeTimer]); + + const togglePause = useCallback(() => { + if (pausedRef.current) { + doResume(); + } else { + doPause('manual'); + } + }, [doPause, doResume]); + + useEffect(() => { + const el = bodyRef.current; + if (!el || !mounted) return; + + let userScrolling = false; + let scrollTimeout: ReturnType | null = null; + + const handleScroll = (): void => { + if (!userScrolling) return; + + if (isScrolledToBottom(el)) { + if (scrollPauseRef.current && !manualPauseRef.current) { + doResume(); + } + } else { + if (!pausedRef.current) { + doPause('scroll'); + } + } + }; + + const handleWheel = (): void => { + userScrolling = true; + if (scrollTimeout) clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(() => { userScrolling = false; }, SCROLL_DETECT_TIMEOUT); + }; + + const handleTouchMove = (): void => { + userScrolling = true; + if (scrollTimeout) clearTimeout(scrollTimeout); + scrollTimeout = setTimeout(() => { userScrolling = false; }, SCROLL_DETECT_TIMEOUT); + }; + + el.addEventListener('scroll', handleScroll, { passive: true }); + el.addEventListener('wheel', handleWheel, { passive: true }); + el.addEventListener('touchmove', handleTouchMove, { passive: true }); + + return () => { + el.removeEventListener('scroll', handleScroll); + el.removeEventListener('wheel', handleWheel); + el.removeEventListener('touchmove', handleTouchMove); + if (scrollTimeout) clearTimeout(scrollTimeout); + }; + }, [mounted, doPause, doResume]); + + useEffect(() => { + const el = bodyRef.current; + if (el && !pausedRef.current) el.scrollTop = el.scrollHeight; + }, [displayedSteps, typedCommand, showCurrentResponse, typedClear, showClearPrompt]); + + const pauseAwareTimeout = useCallback((fn: () => void, ms: number): void => { + const token = cancelRef.current; + let remaining = ms; + let start = Date.now(); + + const check = (): void => { + if (token.cancelled) return; + + if (pausedRef.current) { + setTimeout(check, 50); + start = Date.now(); + return; + } + + remaining -= (Date.now() - start); + if (remaining <= 0) { + fn(); + } else { + start = Date.now(); + setTimeout(check, Math.min(remaining, 50)); + } + }; + + setTimeout(check, Math.min(ms, 50)); + }, []); + + const runAnimation = useCallback(() => { + const token = cancelRef.current; + + if (prefersReducedMotion()) { + setDisplayedSteps(steps.length); + setTypedCommand(''); + setShowCurrentResponse(false); + setShowClearPrompt(false); + setTypedClear(''); + setPhase('showing-response'); + return; + } + + setDisplayedSteps(0); + setTypedCommand(''); + setShowCurrentResponse(false); + setShowClearPrompt(false); + setTypedClear(''); + + const startClearTyping = (): void => { + if (token.cancelled) return; + setPhase('typing-clear'); + + let clearIdx = 0; + const clearText = 'clear'; + + const typeClear = (): void => { + if (token.cancelled) return; + if (clearIdx < clearText.length) { + clearIdx++; + setTypedClear(clearText.slice(0, clearIdx)); + pauseAwareTimeout(typeClear, naturalDelay(typingSpeed, clearText[clearIdx - 1], clearIdx > 1 ? clearText[clearIdx - 2] : '')); + } else { + pauseAwareTimeout(() => { + if (token.cancelled) return; + setPhase('clearing'); + pauseAwareTimeout(() => { + if (token.cancelled) return; + runAnimation(); + }, CLEAR_EXECUTE_DELAY); + }, CLEAR_PAUSE_BEFORE_EXECUTE); + } + }; + + pauseAwareTimeout(() => { if (!token.cancelled) typeClear(); }, initialPause(false)); + }; + + const animateStep = (stepIdx: number, skipInitialPause = false): void => { + if (token.cancelled) return; + + if (stepIdx >= steps.length) { + startClearTyping(); + return; + } + + setTypedCommand(''); + setShowCurrentResponse(false); + setPhase('typing-command'); + + let charIdx = 0; + const cmd = steps[stepIdx].command; + + const typeCommand = (): void => { + if (token.cancelled) return; + if (charIdx < cmd.length) { + charIdx++; + setTypedCommand(cmd.slice(0, charIdx)); + pauseAwareTimeout(typeCommand, naturalDelay(typingSpeed, cmd[charIdx - 1], charIdx > 1 ? cmd[charIdx - 2] : '')); + } else { + pauseAwareTimeout(() => { + if (token.cancelled) return; + setShowCurrentResponse(true); + setPhase('showing-response'); + + const isLast = stepIdx === steps.length - 1; + + if (isLast) { + setDisplayedSteps(stepIdx + 1); + setShowClearPrompt(true); + pauseAwareTimeout(() => { + if (token.cancelled) return; + animateStep(stepIdx + 1); + }, loopDelay * 1000); + } else { + setDisplayedSteps(stepIdx + 1); + setTypedCommand(''); + setShowCurrentResponse(false); + setPhase('typing-command'); + pauseAwareTimeout(() => { + if (token.cancelled) return; + animateStep(stepIdx + 1, true); + }, betweenStepDelay()); + } + }, randomResponseDelay(responseDelay)); + } + }; + + if (skipInitialPause) { + typeCommand(); + } else { + pauseAwareTimeout(() => { + if (!token.cancelled) typeCommand(); + }, initialPause(stepIdx === 0)); + } + }; + + animateStep(0); + }, [steps, formattedResponses, typingSpeed, responseDelay, loopDelay, pauseAwareTimeout]); + + useEffect(() => { + return () => { + cancelRef.current.cancelled = true; + clearAutoResumeTimer(); + }; + }, [clearAutoResumeTimer]); + + useEffect(() => { + if (!mounted || phase !== 'idle') return; + const el = containerRef.current; + if (!el) return; + + if (prefersReducedMotion()) { runAnimation(); return; } + + const observer = new IntersectionObserver( + (entries) => { + for (const entry of entries) { + if (entry.isIntersecting) { + observer.disconnect(); + runAnimation(); + break; + } + } + }, + { threshold: 0, rootMargin: '0px 0px -30px 0px' } + ); + + observer.observe(el); + return () => { observer.disconnect(); }; + }, [mounted, phase, runAnimation]); + + const currentStepIdx = displayedSteps; + + return ( +
+
+ + + + + + Terminal +
+ +
+ {steps.slice(0, mounted ? displayedSteps : steps.length).map((step, i) => ( +
+
0 ? ' cp-prompt--next' : ''}`}> + > + {step.command} +
+ {formattedResponses[i] && ( +
+ {highlightJson(formattedResponses[i])} +
+ )} +
+ ))} + + {mounted && currentStepIdx < steps.length && ( +
+
0 ? ' cp-prompt--next' : ''}`}> + > + + {typedCommand} + {phase === 'typing-command' && } + +
+ {showCurrentResponse && formattedResponses[currentStepIdx] && ( +
+ {highlightJson(formattedResponses[currentStepIdx])} +
+ )} +
+ )} + + {showClearPrompt && ( +
+ > + + {typedClear} + {phase === 'typing-clear' && } + +
+ )} +
+ + {mounted && phase !== 'idle' && ( + + )} +
+ ); +}; + +export default CommandPlayer; diff --git a/docs/src/components/responses/help-spo.txt b/docs/src/components/responses/help-spo.txt new file mode 100644 index 00000000000..cbaf77bc45e --- /dev/null +++ b/docs/src/components/responses/help-spo.txt @@ -0,0 +1,47 @@ +Commands: + + spo get [options] Gets the context URL for the root SharePoint site collection and SharePoint tenant admin site + spo search [options] Executes a search query + spo set [options] Sets the URL of the root SharePoint site collection for use in SPO commands + +Commands groups: + + spo app * 11 commands + spo applicationcustomizer * 5 commands + spo apppage * 2 commands + spo cdn * 7 commands + spo commandset * 5 commands + spo contenttype * 9 commands + spo contenttypehub * 1 command + spo customaction * 6 commands + spo eventreceiver * 3 commands + spo externaluser * 1 command + spo feature * 3 commands + spo field * 5 commands + spo file * 29 commands + spo folder * 19 commands + spo group * 8 commands + spo hidedefaultthemes * 2 commands + spo homesite * 5 commands + spo hubsite * 10 commands + spo knowledgehub * 3 commands + spo list * 35 commands + spo listitem * 24 commands + spo navigation * 5 commands + spo orgassetslibrary * 3 commands + spo orgnewssite * 3 commands + spo page * 21 commands + spo propertybag * 4 commands + spo report * 9 commands + spo roledefinition * 4 commands + spo serviceprincipal * 7 commands + spo site * 35 commands + spo sitedesign * 14 commands + spo sitescript * 5 commands + spo storageentity * 4 commands + spo tenant * 17 commands + spo term * 9 commands + spo theme * 5 commands + spo user * 4 commands + spo userprofile * 2 commands + spo web * 15 commands \ No newline at end of file diff --git a/docs/src/components/responses/spo-cdn-get-help.txt b/docs/src/components/responses/spo-cdn-get-help.txt new file mode 100644 index 00000000000..7b70a62603c --- /dev/null +++ b/docs/src/components/responses/spo-cdn-get-help.txt @@ -0,0 +1,31 @@ +SPO CDN GET +=========== + +View current status of the specified Microsoft 365 CDN + + +USAGE + + m365 spo cdn get [options] + + + +OPTIONS + + -t, --type [type] + Type of CDN to manage. Allowed values are: Public, Private. Default Public. + + -h, --help [help] + Output usage information. Optionally, specify which section of command's help you want to see. Allowed values are options, examples, remarks, permissions, response, full. Default is options. + + --query [query] + JMESPath query string. See http://jmespath.org/ for more information and examples. + + -o, --output [output] + Output type. json, text, csv, md, none. Default json. + + --verbose + Runs command with verbose logging. + + --debug + Runs command with debug logging. \ No newline at end of file diff --git a/docs/src/remark/commandPlayer.ts b/docs/src/remark/commandPlayer.ts new file mode 100644 index 00000000000..b877acc4ee4 --- /dev/null +++ b/docs/src/remark/commandPlayer.ts @@ -0,0 +1,315 @@ +import { visit } from 'unist-util-visit'; +import { Node, Parent } from 'unist'; +import * as fs from 'fs'; +import * as path from 'path'; + +// eslint-disable-next-line @typescript-eslint/no-require-imports +const acorn = require('acorn'); + +const COMPONENT_NAME = 'CommandPlayer'; +const ATTR_RESPONSE = 'response'; +const ATTR_COMMANDS = 'commands'; +const ATTR_RESPONSE_FROM = 'responseFrom'; +const ELEMENT_TYPE = 'mdxJsxAttribute'; +const PARSER_OPTIONS = { ecmaVersion: 2024, sourceType: 'module' } as const; + +interface MdxJsxAttribute { + type: 'mdxJsxAttribute'; + name: string; + value: string | MdxJsxAttributeValueExpression | null; +} + +interface MdxJsxAttributeValueExpression { + type: 'mdxJsxAttributeValueExpression'; + value: string; + data?: Record; +} + +interface MdxJsxFlowElement extends Node { + type: 'mdxJsxFlowElement'; + name: string | null; + attributes: MdxJsxAttribute[]; + children: Node[]; +} + +interface CodeNode extends Node { + type: 'code'; + lang?: string; + value: string; +} + +interface HeadingNode extends Node { + type: 'heading'; + depth: number; + children: Node[]; +} + +interface TextNode extends Node { + type: 'text'; + value: string; +} + +const plugin = (): ((root: Node, file?: { history?: string[] }) => void) => { + return (root: Node, file?: { history?: string[] }): void => { + const currentFilePath = file?.history?.[0]; + const jsonResponse = findFirstJsonInResponseSection(root); + + visit(root, 'mdxJsxFlowElement', (node: MdxJsxFlowElement) => { + if (node.name !== COMPONENT_NAME) { + return; + } + + const hasResponse = hasAttribute(node, ATTR_RESPONSE); + const hasCommands = hasAttribute(node, ATTR_COMMANDS); + const hasResponseFrom = hasAttribute(node, ATTR_RESPONSE_FROM); + + if (!hasResponse && !hasCommands && hasResponseFrom) { + const responseFromAttr = node.attributes.find( + (a) => a.type === ELEMENT_TYPE && a.name === ATTR_RESPONSE_FROM + ); + const refPath = typeof responseFromAttr?.value === 'string' ? responseFromAttr.value : null; + + if (refPath) { + const json = readResponseFromFile(refPath, currentFilePath); + + if (json) { + node.attributes = node.attributes.filter( + (a) => !(a.type === ELEMENT_TYPE && a.name === ATTR_RESPONSE_FROM) + ); + node.attributes.push({ + type: ELEMENT_TYPE, + name: ATTR_RESPONSE, + value: json + }); + } + else { + console.warn(`[commandPlayer] Could not resolve responseFrom: ${refPath}`); + } + } + } + + if (!hasResponse && !hasCommands && !hasResponseFrom && jsonResponse) { + node.attributes.push({ + type: ELEMENT_TYPE, + name: ATTR_RESPONSE, + value: jsonResponse + }); + } + + if (hasCommands) { + resolveCommandsAttribute(node, currentFilePath); + } + }); + }; +}; + +function hasAttribute(node: MdxJsxFlowElement, name: string): boolean { + return node.attributes.some( + (attr) => attr.type === ELEMENT_TYPE && attr.name === name + ); +} + +function resolveCommandsAttribute(node: MdxJsxFlowElement, currentFilePath?: string): void { + const attr = node.attributes.find( + (a) => a.type === ELEMENT_TYPE && a.name === ATTR_COMMANDS + ); + + if (!attr?.value || typeof attr.value !== 'object' || attr.value.type !== 'mdxJsxAttributeValueExpression') { + return; + } + + const expr = attr.value as MdxJsxAttributeValueExpression; + const resolved = replaceResponseFromReferences(expr.value, currentFilePath); + + if (resolved === expr.value) { + return; + } + + expr.value = resolved; + + try { + const newEstree = acorn.parse(`(${resolved})`, PARSER_OPTIONS); + + if (!expr.data) { + expr.data = {}; + } + + expr.data.estree = newEstree; + } + catch (err) { + console.warn('[commandPlayer] Failed to re-parse commands expression:', err); + } +} + +function replaceResponseFromReferences(expression: string, currentFilePath?: string): string { + const regex = /responseFrom:\s*(['"])((?:(?!\1).)*)\1/g; + let result = expression; + + const matches: Array<{ full: string; refPath: string }> = []; + let match: RegExpExecArray | null; + + while ((match = regex.exec(expression)) !== null) { + matches.push({ full: match[0], refPath: match[2] }); + } + + for (const { full, refPath } of matches) { + const json = readResponseFromFile(refPath, currentFilePath); + + if (json) { + const escaped = json + .replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(/\n/g, '\\n') + .replace(/\r/g, ''); + result = result.replace(full, `${ATTR_RESPONSE}: '${escaped}'`); + } + else { + console.warn(`[commandPlayer] Could not resolve responseFrom: ${refPath}`); + } + } + + return result; +} + +function readResponseFromFile(refPath: string, currentFilePath?: string): string | null { + const cleanRef = refPath.replace(/^\.\//, ''); + const docsRoot = path.resolve(__dirname, '../../docs'); + const srcRoot = path.resolve(__dirname, '..'); + const candidates: string[] = []; + + if (currentFilePath) { + candidates.push(path.resolve(path.dirname(currentFilePath), refPath)); + } + + candidates.push(path.resolve(docsRoot, cleanRef)); + candidates.push(path.resolve(docsRoot, 'cmd', cleanRef)); + candidates.push(path.resolve(srcRoot, cleanRef)); + + for (const candidate of candidates) { + if (fs.existsSync(candidate)) { + if (candidate.endsWith('.txt')) { + try { + return fs.readFileSync(candidate, 'utf-8'); + } + catch (err) { + console.warn(`[commandPlayer] Error reading file: ${candidate}`, err); + return null; + } + } + + return extractJsonFromResponseSection(candidate); + } + } + + return null; +} + +function extractJsonFromResponseSection(filePath: string): string | null { + try { + const content = fs.readFileSync(filePath, 'utf-8'); + const lines = content.split(/\r?\n/); + let inResponse = false; + let inJsonBlock = false; + const jsonLines: string[] = []; + + for (const line of lines) { + if (/^#{2}\s+Response\b/i.test(line)) { + inResponse = true; + continue; + } + + if (inResponse && !inJsonBlock && /^#{1,2}\s+/.test(line) && !/Response/i.test(line)) { + break; + } + + if (inResponse && !inJsonBlock && /^\s*```json/.test(line)) { + inJsonBlock = true; + continue; + } + + if (inJsonBlock && /^\s*```\s*$/.test(line)) { + break; + } + + if (inJsonBlock) { + jsonLines.push(line); + } + } + + return jsonLines.length > 0 ? jsonLines.join('\n') : null; + } + catch (err) { + console.warn(`[commandPlayer] Error reading file: ${filePath}`, err); + return null; + } +} + +function findFirstJsonInResponseSection(root: Node): string | null { + const children = (root as Parent).children; + + if (!children) { + return null; + } + + let inResponseSection = false; + + for (const child of children) { + if (isHeading(child)) { + if (child.depth === 2 && getHeadingText(child).toLowerCase() === 'response') { + inResponseSection = true; + continue; + } + + if (inResponseSection && child.depth <= 2) { + break; + } + } + + if (inResponseSection) { + const jsonValue = findJsonCodeBlock(child); + + if (jsonValue !== null) { + return jsonValue; + } + } + } + + return null; +} + +function findJsonCodeBlock(node: Node): string | null { + if (isCodeNode(node) && node.lang === 'json') { + return node.value; + } + + const children = (node as Parent).children; + + if (children) { + for (const child of children) { + const result = findJsonCodeBlock(child); + + if (result !== null) { + return result; + } + } + } + + return null; +} + +function isHeading(node: Node): node is HeadingNode { + return node.type === 'heading'; +} + +function isCodeNode(node: Node): node is CodeNode { + return node.type === 'code'; +} + +function getHeadingText(heading: HeadingNode): string { + return heading.children + .filter((c): c is TextNode => c.type === 'text') + .map((c) => c.value) + .join(''); +} + +export default plugin; diff --git a/docs/src/scss/CommandPlayer.module.scss b/docs/src/scss/CommandPlayer.module.scss new file mode 100644 index 00000000000..45cfde2b705 --- /dev/null +++ b/docs/src/scss/CommandPlayer.module.scss @@ -0,0 +1,244 @@ +:global { + + :root { + --cp-bg: var(--ifm-background-surface-color); + --cp-titlebar-bg: var(--ifm-color-emphasis-100); + --cp-titlebar-color: var(--ifm-color-emphasis-700); + --cp-titlebar-icon: var(--ifm-color-emphasis-600); + --cp-body-color: var(--ifm-font-color-base); + --cp-border: var(--ifm-color-emphasis-200); + --cp-prompt-color: var(--ifm-color-primary); + --cp-command-color: var(--ifm-font-color-base); + --cp-cursor-bg: var(--ifm-font-color-base); + --cp-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); + --cp-tok-key: #124994; + --cp-tok-str: #A31515; + --cp-tok-num: #098658; + --cp-tok-bool: #0000FF; + --cp-tok-null: #0000FF; + --cp-tok-punct: #000000; + --cp-scrollbar-thumb: var(--ifm-color-emphasis-300); + --cp-scrollbar-track: transparent; + --cp-pause-bg: rgba(0, 0, 0, 0.06); + --cp-pause-hover-bg: rgba(0, 0, 0, 0.12); + --cp-pause-color: var(--ifm-color-emphasis-600); + --cp-pause-ring: var(--ifm-color-primary); + } + + [data-theme='dark'] { + --cp-bg: var(--ifm-background-surface-color); + --cp-titlebar-bg: var(--ifm-color-emphasis-100); + --cp-titlebar-color: var(--ifm-color-emphasis-400); + --cp-titlebar-icon: var(--ifm-color-emphasis-500); + --cp-body-color: var(--ifm-font-color-base); + --cp-border: var(--ifm-color-emphasis-200); + --cp-prompt-color: var(--ifm-color-primary-light); + --cp-command-color: var(--ifm-font-color-base); + --cp-cursor-bg: var(--ifm-font-color-base); + --cp-shadow: 0 2px 12px rgba(0, 0, 0, 0.3); + --cp-tok-key: #84BDDA; + --cp-tok-str: #CE9178; + --cp-tok-num: #B5CEA8; + --cp-tok-bool: #569CD6; + --cp-tok-null: #569CD6; + --cp-tok-punct: #D4D4D4; + --cp-scrollbar-thumb: var(--ifm-color-emphasis-400); + --cp-scrollbar-track: transparent; + --cp-pause-bg: rgba(255, 255, 255, 0.08); + --cp-pause-hover-bg: rgba(255, 255, 255, 0.16); + --cp-pause-color: var(--ifm-color-emphasis-400); + --cp-pause-ring: var(--ifm-color-primary-light); + } + + .cp-container { + position: relative; + border-radius: 8px; + overflow: hidden; + margin: 1.5rem 0; + box-shadow: var(--cp-shadow); + font-family: var(--ifm-font-family-monospace); + background: var(--cp-bg); + border: 1px solid var(--cp-border); + max-width: 100%; + } + + .cp-titlebar { + display: flex; + align-items: center; + gap: 8px; + padding: 6px 12px; + background: var(--cp-titlebar-bg); + user-select: none; + border-bottom: 1px solid var(--cp-border); + min-height: 32px; + } + + .cp-titlebar-icon { + display: flex; + align-items: center; + color: var(--cp-titlebar-icon); + flex-shrink: 0; + } + + .cp-titlebar-text { + font-size: 12px; + font-weight: 400; + color: var(--cp-titlebar-color); + letter-spacing: 0.02em; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + } + + .cp-body { + padding: 16px; + font-size: var(--ifm-code-font-size, 13px); + line-height: 1.6; + color: var(--cp-body-color); + height: 280px; + overflow-y: auto; + overflow-x: hidden; + -webkit-overflow-scrolling: touch; + + &::-webkit-scrollbar { + width: 6px; + } + &::-webkit-scrollbar-track { + background: var(--cp-scrollbar-track); + } + &::-webkit-scrollbar-thumb { + background: var(--cp-scrollbar-thumb); + border-radius: 3px; + } + scrollbar-width: thin; + scrollbar-color: var(--cp-scrollbar-thumb) var(--cp-scrollbar-track); + } + + .cp-prompt { + display: flex; + align-items: flex-start; + white-space: normal; + word-break: break-all; + } + + .cp-prompt--next, + .cp-prompt--clear { + margin-top: 12px; + } + + .cp-prompt-symbol { + color: var(--cp-prompt-color); + margin-right: 8px; + flex-shrink: 0; + font-weight: 600; + } + + .cp-command { + color: var(--cp-command-color); + white-space: pre-wrap; + word-break: break-all; + } + + .cp-cursor { + display: inline-block; + width: 8px; + height: 1.15em; + background: var(--cp-cursor-bg); + vertical-align: text-bottom; + animation: cpBlink 1s step-end infinite; + } + + @keyframes cpBlink { + 0%, 100% { opacity: 1; } + 50% { opacity: 0; } + } + + .cp-response { + margin-top: 12px; + white-space: pre-wrap; + word-break: break-all; + line-height: 1.5; + } + + .cp-response--visible { + animation: cpFadeIn 0.4s ease-out; + } + + @keyframes cpFadeIn { + from { opacity: 0; transform: translateY(4px); } + to { opacity: 1; transform: translateY(0); } + } + + .cp-tok-key { color: var(--cp-tok-key); } + .cp-tok-str { color: var(--cp-tok-str); } + .cp-tok-num { color: var(--cp-tok-num); } + .cp-tok-bool { color: var(--cp-tok-bool); } + .cp-tok-null { color: var(--cp-tok-null); } + .cp-tok-punct { color: var(--cp-tok-punct); } + + .cp-pause-btn { + position: absolute; + bottom: 10px; + right: 10px; + display: flex; + align-items: center; + justify-content: center; + width: 28px; + height: 28px; + border: none; + border-radius: 6px; + background: var(--cp-pause-bg); + color: var(--cp-pause-color); + cursor: pointer; + opacity: 0; + transition: opacity 0.2s ease, background 0.15s ease; + z-index: 2; + + .cp-container:hover &, + &--paused { + opacity: 1; + } + + &:hover { + background: var(--cp-pause-hover-bg); + } + + &:focus-visible { + outline: 2px solid var(--ifm-color-primary); + outline-offset: 2px; + } + } + + .cp-pause-ring { + position: absolute; + inset: 0; + pointer-events: none; + color: var(--cp-pause-ring); + } + + @media (max-width: 600px) { + .cp-body { + padding: 12px; + font-size: 11px; + height: 220px; + } + + .cp-titlebar { + padding: 5px 10px; + min-height: 28px; + } + + .cp-pause-btn { + opacity: 1; + } + } + + @media (prefers-reduced-motion: reduce) { + .cp-cursor { + animation: none; + opacity: 1; + } + + .cp-response--visible { + animation: none; + } + } +} diff --git a/docs/static/casts/commandHelp.cast b/docs/static/casts/commandHelp.cast deleted file mode 100644 index f1a0f51bf9d..00000000000 --- a/docs/static/casts/commandHelp.cast +++ /dev/null @@ -1,59 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635588371, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005581, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[1.263005, "o", "m"] -[1.647042, "o", "3"] -[1.998946, "o", "6"] -[2.062793, "o", "5"] -[2.270957, "o", " "] -[2.8071, "o", "s"] -[2.93493, "o", "p"] -[3.118955, "o", "o"] -[3.262872, "o", " "] -[3.478921, "o", "c"] -[3.622771, "o", "d"] -[3.766881, "o", "n"] -[3.910839, "o", " "] -[4.030823, "o", "g"] -[4.134884, "o", "e"] -[4.23085, "o", "t"] -[4.286829, "o", " "] -[4.494863, "o", "-"] -[4.670989, "o", "-"] -[4.902968, "o", "h"] -[5.038794, "o", "e"] -[5.158795, "o", "l"] -[5.326935, "o", "p"] -[5.614985, "o", "\r\n"] -[6.052398, "o", "\r\n"] -[7.002873, "o", "\u001b[37mspo cdn get\u001b[39m\r\n\r\nView current status of the specified Microsoft 365 CDN\r\n\r\n\u001b[37mUsage\u001b[39m\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get \u001b[38;5;102m[\u001b[39m\u001b[38;5;103moptions\u001b[38;5;102m]\u001b[39m\u001b[38;5;103m\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\n\u001b[37mOptions\u001b[39m\r\n\r\n\u001b[36m-t, --type [type]\u001b[39m\r\n Type of CDN to manage. \u001b[36mPublic,Private\u001b[39m. Default \u001b[36mPublic\u001b[39m \r\n\r\n\u001b[36m-h, --help\u001b[39m\r\n output usage information \r\n\r\n\u001b[36m--query [query]\u001b[39m\r\n JMESPath query string. See http://jmespath.org/ for more information and examples \r\n\r\n\u001b[36m-o, --output [output]\u001b[39m\r\n Output type. \u001b["] -[7.00305, "o", "36mjson,text\u001b[39m. Default \u001b[36mtext\u001b[39m \r\n\r\n\u001b[36m--verbose\u001b[39m\r\n Runs command with verbose logging \r\n\r\n\u001b[36m--debug\u001b[39m\r\n Runs command with debug logging \r\n\r\n\u001b[48;5;197m\u001b[1m \u001b[22m\u001b[49m\u001b[48;5;16m\u001b[37m Important \u001b[39m\u001b[49m\u001b[48;5;197m\u001b[1m \u001b[22m\u001b[49m\r\n To use this command you have to have permissions to access the tenant admin site.\r\n\r\n\u001b[37mRemarks\u001b[39m\r\n\r\nUsing the \u001b[36m-t, --type\u001b[39m option you can choose whether you want to manage the settings of the Public (default) or Private CDN. If you don't use the option, the command will use the Public CDN.\r\n\r\n\u001b[37mExamples\u001b[39m\r\n\r\nShow if the Public CDN is currently enabled or not\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m "] -[7.003147, "o", " \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\nShow if the Private CDN is currently enabled or not\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get --type Private\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\n\u001b[37mMore information\u001b[39m\r\n\r\n- General availability of Microsoft 365 CDN: https://dev.office.com/blogs/general-availability-of-office-365-cdn\r\n"] -[7.009051, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[8.327013, "o", "m"] -[8.566857, "o", "3"] -[8.934857, "o", "6"] -[9.00689, "o", "5"] -[9.246973, "o", " "] -[10.023023, "o", "h"] -[10.126761, "o", "e"] -[10.206926, "o", "l"] -[10.390776, "o", "p"] -[10.550896, "o", " "] -[10.702825, "o", "s"] -[10.814807, "o", "p"] -[10.990776, "o", "o"] -[11.134881, "o", " "] -[11.950999, "o", "c"] -[12.118778, "o", "d"] -[12.230816, "o", "n"] -[12.390844, "o", " "] -[12.550821, "o", "g"] -[12.65482, "o", "e"] -[12.758793, "o", "t"] -[12.95889, "o", "\r\n"] -[13.405237, "o", "\r\n"] -[14.035489, "o", "\u001b[37mspo cdn get\u001b[39m\r\n\r\nView current status of the specified Microsoft 365 CDN\r\n\r\n\u001b[37mUsage\u001b[39m\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get \u001b[38;5;102m[\u001b[39m\u001b[38;5;103moptions\u001b[38;5;102m]\u001b[39m\u001b[38;5;103m\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\n\u001b[37mOptions\u001b[39m\r\n\r\n\u001b[36m-t, --type [type]\u001b[39m\r\n Type of CDN to manage. \u001b[36mPublic,Private\u001b[39m. Default \u001b[36mPublic\u001b[39m \r\n\r\n\u001b[36m-h, --help\u001b[39m\r\n output usage information \r\n\r\n\u001b[36m--query [query]\u001b[39m\r\n JMESPath query string. See http://jmespath.org/ for more information and examples \r\n\r\n\u001b[36m-o, --output [output]\u001b[39m\r\n Output type. \u001b["] -[14.035704, "o", "36mjson,text\u001b[39m. Default \u001b[36mtext\u001b[39m \r\n\r\n\u001b[36m--verbose\u001b[39m\r\n Runs command with verbose logging \r\n\r\n\u001b[36m--debug\u001b[39m\r\n Runs command with debug logging \r\n\r\n\u001b[48;5;197m\u001b[1m \u001b[22m\u001b[49m\u001b[48;5;16m\u001b[37m Important \u001b[39m\u001b[49m\u001b[48;5;197m\u001b[1m \u001b[22m\u001b[49m\r\n To use this command you have to have permissions to access the tenant admin site.\r\n\r\n\u001b[37mRemarks\u001b[39m\r\n\r\nUsing the \u001b[36m-t, --type\u001b[39m option you can choose whether you want to manage the settings of the Public (default) or Private CDN. If you don't use the option, the command will use the Public CDN.\r\n\r\n\u001b[37mExamples\u001b[39m\r\n\r\nShow if the Public CDN is currently enabled or not\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m "] -[14.035865, "o", " \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\nShow if the Private CDN is currently enabled or not\r\n\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103mm365 spo cdn get --type Private\u001b[39m\u001b[49m\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\u001b[48;5;230m\u001b[38;5;103m \u001b[39m\u001b[49m\r\n\r\n\u001b[37mMore information\u001b[39m\r\n\r\n- General availability of Microsoft 365 CDN: https://dev.office.com/blogs/general-availability-of-office-365-cdn\r\n"] -[14.041707, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[16.094892, "o", "exit\r\n"] diff --git a/docs/static/casts/home.cast b/docs/static/casts/home.cast deleted file mode 100644 index 62c0b8b3cde..00000000000 --- a/docs/static/casts/home.cast +++ /dev/null @@ -1,62 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635587824, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005576, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[1.10731, "o", "m"] -[1.451298, "o", "3"] -[1.723263, "o", "6"] -[1.787183, "o", "5"] -[1.891131, "o", " "] -[2.027241, "o", "l"] -[2.211216, "o", "o"] -[2.283149, "o", "g"] -[2.43511, "o", "i"] -[2.52314, "o", "n"] -[2.74739, "o", "\r\n"] -[3.765533, "o", "\"To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code DSQ73T6BS to authenticate.\"\r\n"] -[14.618395, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[15.70723, "o", "m"] -[15.963249, "o", "3"] -[16.339259, "o", "6"] -[16.379164, "o", "5"] -[16.523239, "o", " "] -[17.05922, "o", "s"] -[17.219157, "o", "p"] -[17.403233, "o", "o"] -[17.58713, "o", " "] -[18.611273, "o", "c"] -[18.827161, "o", "d"] -[18.94715, "o", "n"] -[19.123236, "o", " "] -[19.235137, "o", "g"] -[19.339129, "o", "e"] -[19.435127, "o", "t"] -[19.579169, "o", "\r\n"] -[22.037077, "o", "\u001b[33mtrue\u001b[39m\r\n"] -[22.039564, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[23.32328, "o", "m"] -[23.755189, "o", "3"] -[24.10721, "o", "6"] -[24.16313, "o", "5"] -[24.307162, "o", " "] -[25.099239, "o", "s"] -[25.243099, "o", "p"] -[25.427257, "o", "o"] -[25.56314, "o", " "] -[25.771181, "o", "c"] -[26.011213, "o", "d"] -[26.123064, "o", "n"] -[26.275253, "o", " "] -[26.915238, "o", "o"] -[27.083135, "o", "r"] -[27.219084, "o", "i"] -[27.331025, "o", "g"] -[27.403063, "o", "i"] -[27.49104, "o", "n"] -[27.835269, "o", " "] -[27.971116, "o", "l"] -[28.139084, "o", "i"] -[28.171128, "o", "s"] -[28.315048, "o", "t"] -[28.523114, "o", "\r\n"] -[29.326273, "o", "[\r\n \"*/MASTERPAGE\",\r\n \"*/STYLE LIBRARY\",\r\n \"*/CLIENTSIDEASSETS\"\r\n]\r\n"] -[29.328663, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[31.22712, "o", "exit\r\n"] diff --git a/docs/static/casts/install.cast b/docs/static/casts/install.cast deleted file mode 100644 index a9553f827fe..00000000000 --- a/docs/static/casts/install.cast +++ /dev/null @@ -1,99 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635588742, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005804, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[0.631689, "o", "n"] -[0.735592, "o", "p"] -[0.887637, "o", "m"] -[1.015595, "o", " "] -[1.399712, "o", "i"] -[1.535532, "o", "n"] -[1.623626, "o", "s"] -[1.73553, "o", "t"] -[1.847596, "o", "a"] -[1.895932, "o", "l"] -[2.04756, "o", "l"] -[2.191566, "o", " "] -[2.335636, "o", "-"] -[2.503698, "o", "g"] -[2.679731, "o", " "] -[3.039783, "o", "@"] -[3.335614, "o", "p"] -[3.471679, "o", "n"] -[3.591498, "o", "p"] -[3.919619, "o", "/"] -[4.127678, "o", "c"] -[4.199671, "o", "l"] -[4.359574, "o", "i"] -[4.551624, "o", "-"] -[4.783578, "o", "m"] -[4.919614, "o", "i"] -[4.959535, "o", "c"] -[5.199586, "o", "r"] -[5.247507, "o", "o"] -[5.399681, "o", "s"] -[5.447502, "o", "o"] -[5.535547, "o", "f"] -[5.703572, "o", "t"] -[6.255673, "o", "3"] -[6.567648, "o", "6"] -[6.647571, "o", "5"] -[7.38385, "o", "\r\n"] -[7.888282, "o", "\u001b[?25l"] -[7.890354, "o", "[\u001b[90m..................\u001b[0m] / rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[7.938109, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[7.996314, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.045769, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.098361, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.18107, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.29522, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.368743, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.472768, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.526361, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.578868, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.639298, "o", "[\u001b[90m..................\u001b[0m] \\ rollbackFailedOptional: \u001b[34;40mverb\u001b[0m \u001b[35mnpm-session\u001b[0m e0a623e8ed8db9fb\u001b[0m\u001b[K\r"] -[8.835842, "o", "[\u001b[90m..................\u001b[0m] | loadIdealTree:loadAllDepsIntoIdealTree: \u001b[7msill\u001b[0m \u001b[35minstall\u001b[0m loadIdealTree\u001b[0m\u001b[K\r"] -[9.015297, "o", "[\u001b[90m..................\u001b[0m] / loadDep:xmldom: \u001b[7msill\u001b[0m \u001b[35mremoveObsoleteDep\u001b[0m removing xmldom@0.6.0 from the tree as its been replaced by a new\u001b[0m\u001b[K\r"] -[9.065862, "o", "[\u001b[7m \u001b[27m\u001b[90m.................\u001b[0m] / loadDep:semver: \u001b[7msill\u001b[0m \u001b[35mremoveObsoleteDep\u001b[0m removing xmldom@0.6.0 from the tree as its been replaced by a new\u001b[0m\u001b[K\r"] -[9.11539, "o", "[\u001b[7m \u001b[27m\u001b[90m................\u001b[0m] / loadDep:uuid: \u001b[7msill\u001b[0m \u001b[35mremoveObsoleteDep\u001b[0m removing xmldom@0.6.0 from the tree as its been replaced by a newer\u001b[0m\u001b[K\r"] -[9.283675, "o", "[\u001b[7m \u001b[27m\u001b[90m............\u001b[0m] - diffTrees: \u001b[7msill\u001b[0m \u001b[35minstall\u001b[0m generateActionsToTake\u001b[0m\u001b[K\r"] -[9.333529, "o", "[\u001b[7m \u001b[27m\u001b[90m...........\u001b[0m] - extract:@pnp/cli-microsoft365: \u001b[34;40mverb\u001b[0m \u001b[35mlock\u001b[0m using /root/.npm/_locks/staging-3a08f0df5026584d.lock for /usr/\u001b[0m\u001b[K\r"] -[9.382873, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.432838, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.482891, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.532813, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.582939, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.632851, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.68299, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.73462, "o", "[\u001b[7m \u001b[27m\u001b[90m.........\u001b[0m] \\ extract:fsevents: \u001b[7msill\u001b[0m \u001b[35mextract\u001b[0m fsevents@2.3.2 extracted to /usr/local/lib/node_modules/.staging/fsevents\u001b[0m\u001b[K\r"] -[9.784109, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] - unbuild:@pnp/cli-microsoft365: \u001b[7msill\u001b[0m \u001b[35mdoReverseSerial\u001b[0m unbuild 18\u001b[0m\u001b[K\r"] -[9.83948, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] \\ remove:@pnp/cli-microsoft365: \u001b[7msill\u001b[0m \u001b[35mdoSerial\u001b[0m remove 18\u001b[0m\u001b[K\r"] -[9.895036, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] \\ remove:@pnp/cli-microsoft365: \u001b[7msill\u001b[0m \u001b[35mdoSerial\u001b[0m remove 18\u001b[0m\u001b[K\r"] -[9.944927, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] \\ remove:@pnp/cli-microsoft365: \u001b[7msill\u001b[0m \u001b[35mdoSerial\u001b[0m remove 18\u001b[0m\u001b[K\r"] -[10.005072, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] \\ remove:@pnp/cli-microsoft365: \u001b[7msill\u001b[0m \u001b[35mdoSerial\u001b[0m remove 18\u001b[0m\u001b[K\r"] -[10.058733, "o", "[\u001b[7m \u001b[27m\u001b[90m......\u001b[0m] | finalize:fsevents: \u001b[7msill\u001b[0m \u001b[35mfinalize\u001b[0m /usr/local/lib/node_modules/@pnp/cli-microsoft365/node_modules/fsevents\u001b[0m\u001b[K\r"] -[10.095795, "o", "\r\u001b[K\u001b[?25h"] -[10.096133, "o", "/usr/local/bin/microsoft365 -> /usr/local/lib/node_modules/@pnp/cli-microsoft365/dist/index.js\r\n"] -[10.096358, "o", "/usr/local/bin/m365 -> /usr/local/lib/node_modules/@pnp/cli-microsoft365/dist/index.js\r\n"] -[10.096521, "o", "/usr/local/bin/m365_comp -> /usr/local/lib/node_modules/@pnp/cli-microsoft365/dist/autocomplete.js\r\n"] -[10.10095, "o", "\u001b[37;40mnpm\u001b[0m"] -[10.101059, "o", " \u001b[0m\u001b[30;43mWARN\u001b[0m \u001b[0m\u001b[35moptional\u001b[0m"] -[10.101196, "o", " SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules/@pnp/cli-microsoft365/node_modules/fsevents):\r\n\u001b[0m\u001b[37;40mnpm\u001b[0m \u001b[0m"] -[10.101322, "o", "\u001b[30;43mWARN\u001b[0m \u001b[0m\u001b[35mnotsup\u001b[0m SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})\r\n\u001b[0m"] -[10.101416, "o", "\r\n"] -[10.10188, "o", "+ @pnp/cli-microsoft365@11.4.0\r\nupdated 1 package in 2.218s\r\n"] -[10.117177, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[11.135752, "o", "m"] -[11.375696, "o", "3"] -[11.703772, "o", "6"] -[11.791739, "o", "5"] -[11.95987, "o", " "] -[12.303631, "o", "v"] -[12.519707, "o", "e"] -[12.575579, "o", "r"] -[12.727582, "o", "s"] -[12.871525, "o", "i"] -[12.911537, "o", "o"] -[12.975658, "o", "n"] -[13.543867, "o", "\r\n"] -[13.994199, "o", "\"v11.4.0\"\r\n"] -[14.010274, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[16.143622, "o", "exit\r\n"] diff --git a/docs/static/casts/listCommands.cast b/docs/static/casts/listCommands.cast deleted file mode 100644 index 84812f31f10..00000000000 --- a/docs/static/casts/listCommands.cast +++ /dev/null @@ -1,91 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635588235, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005396, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[0.727111, "o", "m"] -[0.894994, "o", "3"] -[1.214968, "o", "6"] -[1.270908, "o", "5"] -[1.446998, "o", " "] -[1.879011, "o", "h"] -[1.97487, "o", "e"] -[2.03898, "o", "l"] -[2.191095, "o", "p"] -[2.487111, "o", "\r\n"] -[3.440291, "o", "\r\n"] -[3.440466, "o", "CLI for Microsoft 365 v11.4.0\r\nManage Microsoft 365 and SharePoint Framework projects on any platform\r\n\r\n"] -[3.441042, "o", "Commands:\r\n\r\n"] -[3.441151, "o", " login [options] Log in to Microsoft 365\r\n logout [options] Log out from Microsoft 365\r\n"] -[3.441238, "o", " status [options] Shows Microsoft 365 login status\r\n version [options] Shows CLI for Microsoft 365 version\r\n"] -[3.441351, "o", "\r\nCommands groups:\r\n"] -[3.441469, "o", "\r\n"] -[3.441699, "o", " adaptivecard * 1 command\r\n app * 4 commands\r\n booking * 2 commands\r\n"] -[3.441787, "o", " cli * 14 commands\r\n connection * 4 commands\r\n context * 5 commands\r\n"] -[3.441909, "o", " entra * 117 commands\r\n exo * 1 command\r\n external * 8 commands\r\n"] -[3.441971, "o", " file * 5 commands\r\n flow * 19 commands\r\n graph * 16 commands\r\n"] -[3.442088, "o", " onedrive * 8 commands\r\n onenote * 3 commands\r\n outlook * 21 commands\r\n"] -[3.442189, "o", " pa * 13 commands\r\n planner * 31 commands\r\n pp * 28 commands\r\n"] -[3.442308, "o", " purview * 21 commands\r\n search * 5 commands\r\n spe * 13 commands\r\n"] -[3.442435, "o", " spfx * 9 commands\r\n spo * 373 commands\r\n spp * 6 commands\r\n"] -[3.442550, "o", " teams * 71 commands\r\n tenant * 24 commands\r\n todo * 10 commands\r\n"] -[3.442650, "o", " util * 1 command\r\n viva * 29 commands\r\n\r\n"] -[3.448316, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[4.479056, "o", "m"] -[4.719021, "o", "3"] -[5.039032, "o", "6"] -[5.10295, "o", "5"] -[5.567055, "o", " "] -[5.79096, "o", "h"] -[5.910875, "o", "e"] -[5.990985, "o", "l"] -[6.158902, "o", "p"] -[6.278941, "o", " "] -[6.366907, "o", "e"] -[6.534859, "o", "n"] -[6.600000, "o", "t"] -[6.650000, "o", "r"] -[6.703011, "o", "a"] -[7.623097, "o", "\r\n"] -[8.560166, "o", "\r\n"] -[8.560351, "o", "CLI for Microsoft 365 v11.4.0\r\n"] -[8.560474, "o", "Manage Microsoft 365 and SharePoint Framework projects on any platform\r\n\r\n"] -[8.56091, "o", "Commands groups:\r\n\r\n"] -[8.561235, "o", " entra administrativeunit * 9 commands\r\n entra app * 11 commands\r\n entra approleassignment * 3 commands\r\n"] -[8.561362, "o", " entra enterpriseapp * 4 commands\r\n entra group * 9 commands\r\n entra groupsetting * 5 commands\r\n"] -[8.561451, "o", " entra groupsettingtemplate * 2 commands\r\n entra license * 1 command\r\n entra m365group * 22 commands\r\n"] -[8.561513, "o", " entra multitenant * 4 commands\r\n entra oauth2grant * 4 commands\r\n entra organization * 2 commands\r\n"] -[8.561570, "o", " entra pim * 5 commands\r\n entra policy * 1 command\r\n entra resourcenamespace * 1 command\r\n"] -[8.561630, "o", " entra roleassignment * 1 command\r\n entra roledefinition * 5 commands\r\n entra rolepermission * 1 command\r\n"] -[8.561690, "o", " entra siteclassification * 4 commands\r\n entra sp * 4 commands\r\n entra user * 19 commands\r\n"] -[8.561646, "o", "\r\n"] -[8.567701, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[9.311097, "o", "m"] -[9.57494, "o", "3"] -[9.919013, "o", "6"] -[9.982948, "o", "5"] -[10.223176, "o", " "] -[10.487052, "o", "h"] -[10.62282, "o", "e"] -[10.710866, "o", "l"] -[10.870979, "o", "p"] -[11.031008, "o", " "] -[11.111036, "o", "s"] -[11.230922, "o", "p"] -[11.422961, "o", "o"] -[11.558965, "o", " "] -[11.662961, "o", "a"] -[11.799014, "o", "p"] -[11.950998, "o", "p"] -[12.294976, "o", "\r\n"] -[13.290006, "o", "\r\n"] -[13.29021, "o", "CLI for Microsoft 365 v11.4.0\r\n"] -[13.290306, "o", "Manage Microsoft 365 and SharePoint Framework projects on any platform\r\n\r\n"] -[13.29079, "o", "Commands:\r\n\r\n"] -[13.29092, "o", " spo app add [options] Adds an app to the specified SharePoint Online app catalog\r\n"] -[13.290985, "o", " spo app deploy [options] Deploys the specified app in the specified app catalog\r\n"] -[13.291015, "o", " spo app get [options] Gets information about the specific app from the specified app catalog\r\n"] -[13.291128, "o", " spo app install [options] Installs an app from the specified app catalog in the site\r\n"] -[13.291242, "o", " spo app list [options] Lists apps from the specified app catalog\r\n spo app remove [options] Removes the specified app from the specified app catalog\r\n spo app retract [options] Retracts the specified app from the specified app catalog\r\n"] -[13.291346, "o", " spo app uninstall [options] Uninstalls an app from the site\r\n spo app upgrade [options] Upgrades app in the specified site\r\n\r\n"] -[13.291463, "o", "Commands groups:\r\n\r\n"] -[13.291545, "o", " spo app instance * 1 command\r\n\r\n"] -[13.297675, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[15.486908, "o", "exit\r\n"] diff --git a/docs/static/casts/logout.cast b/docs/static/casts/logout.cast deleted file mode 100644 index 9cf6bd3db40..00000000000 --- a/docs/static/casts/logout.cast +++ /dev/null @@ -1,57 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635588544, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005479, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[1.303701, "o", "m"] -[1.55164, "o", "3"] -[1.879652, "o", "6"] -[1.943561, "o", "5"] -[2.047462, "o", " "] -[2.207604, "o", "l"] -[2.37543, "o", "o"] -[2.447616, "o", "g"] -[2.58349, "o", "i"] -[2.647647, "o", "n"] -[2.903618, "o", "\r\n"] -[3.982555, "o", "\"To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code DSG7DLEZC to authenticate.\"\r\n"] -[14.897708, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[15.471591, "o", "m"] -[15.815711, "o", "3"] -[16.127629, "o", "6"] -[16.199473, "o", "5"] -[16.263486, "o", " "] -[16.503451, "o", "s"] -[16.639395, "o", "t"] -[16.743492, "o", "a"] -[16.831442, "o", "t"] -[16.959393, "o", "u"] -[17.039335, "o", "s"] -[17.207495, "o", "\r\n"] -[17.646188, "o", "{\r\n \"connectionName\": \"77ca3cea-f1d3-4417-aac4-47de8e56972f\",\r\n \"connectedAs\": \"admin@contoso.onmicrosoft.com\",\r\n \"authType\": \"deviceCode\",\r\n \"appId\": \"a38e181c-614c-4277-af6c-86d41707d065\",\r\n \"appTenant\": \"e429b7f8-9826-4b3f-a3f1-5444b19a347f\",\r\n \"cloudType\": \"Public\"\r\n}\r\n"] -[17.648651, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[18.447609, "o", "m"] -[18.671517, "o", "3"] -[19.023581, "o", "6"] -[19.071479, "o", "5"] -[19.19949, "o", " "] -[19.463484, "o", "l"] -[19.655463, "o", "o"] -[19.927567, "o", "g"] -[20.143395, "o", "o"] -[20.27152, "o", "u"] -[20.375398, "o", "t"] -[20.591522, "o", "\r\n"] -[21.055713, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[21.623535, "o", "m"] -[21.863465, "o", "3"] -[22.191503, "o", "6"] -[22.255465, "o", "5"] -[22.367501, "o", " "] -[22.51947, "o", "s"] -[22.663444, "o", "t"] -[22.783474, "o", "a"] -[22.895389, "o", "t"] -[23.015618, "o", "u"] -[23.127574, "o", "s"] -[23.312268, "o", "\r\n"] -[23.752441, "o", "\"Logged out\"\r\n"] -[23.755038, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[25.02348, "o", "exit\r\n"] diff --git a/docs/static/casts/usingCli.cast b/docs/static/casts/usingCli.cast deleted file mode 100644 index 9b0a857cedc..00000000000 --- a/docs/static/casts/usingCli.cast +++ /dev/null @@ -1,68 +0,0 @@ -{"version": 2, "width": 128, "height": 27, "timestamp": 1635588091, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}} -[0.005675, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[0.693726, "o", "m"] -[0.949646, "o", "3"] -[1.253594, "o", "6"] -[1.325587, "o", "5"] -[1.45352, "o", " "] -[1.605572, "o", "s"] -[1.741634, "o", "t"] -[1.869525, "o", "a"] -[1.965665, "o", "t"] -[2.101543, "o", "u"] -[2.221641, "o", "s"] -[2.701611, "o", "\r\n"] -[3.136258, "o", "{\r\n \"connectionName\": \"77ca3cea-f1d3-4417-aac4-47de8e56972f\",\r\n \"connectedAs\": \"admin@contoso.onmicrosoft.com\",\r\n \"authType\": \"deviceCode\",\r\n \"appId\": \"a38e181c-614c-4277-af6c-86d41707d065\",\r\n \"appTenant\": \"e429b7f8-9826-4b3f-a3f1-5444b19a347f\",\r\n \"cloudType\": \"Public\"\r\n}\r\n"] -[3.153568, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[3.685774, "o", "m"] -[4.053679, "o", "3"] -[4.365604, "o", "6"] -[4.429631, "o", "5"] -[4.549603, "o", " "] -[4.7256, "o", "s"] -[4.853493, "o", "p"] -[5.021552, "o", "o"] -[5.18961, "o", " "] -[5.27764, "o", "a"] -[5.437531, "o", "p"] -[5.597568, "o", "p"] -[5.725549, "o", " "] -[5.877633, "o", "l"] -[6.037537, "o", "i"] -[6.077524, "o", "s"] -[6.245497, "o", "t"] -[6.413645, "o", "\r\n"] -[7.27474, "o", "[\r\n {\r\n \"AadAppId\": \"00000000-0000-0000-0000-000000000000\",\r\n \"AadPermissions\": null,\r\n \"AppCatalogVersion\": \"1.0.0.0\",\r\n \"CanUpgrade\": false,\r\n \"CDNLocation\": \"SharePoint Online\",\r\n \"ContainsTenantWideExtension\": true,\r\n \"CurrentVersionDeployed\": true,\r\n \"Deployed\": true,\r\n \"ErrorMessage\": \"No errors.\",\r\n \"ID\": \"e6b6c025-afd1-4a5c-b49e-9b1a2a974c78\",\r\n \"InstalledVersion\": \"\",\r\n \"IsClientSideSolution\": true,\r\n \"IsEnabled\": true,\r\n \"IsPackageDefaultSkipFeatureDeployment\": false,\r\n \"IsValidAppPackage\": true,\r\n \"ProductId\": \"6b378295-1076-4c3c-a626-13bfb882c907\",\r\n \"ShortDescription\": \"\",\r\n \"SkipDeploymentFeature\": false,\r\n \"ThumbnailUrl\": \"\",\r\n \"Title\": \"first-web-part-client-side-solution\"\r\n }\r\n]\r\n"] -[7.277237, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[8.133724, "o", "m"] -[8.36555, "o", "3"] -[8.71759, "o", "6"] -[8.789657, "o", "5"] -[9.085644, "o", " "] -[9.509612, "o", "s"] -[9.629467, "o", "p"] -[9.813637, "o", "o"] -[9.933552, "o", " "] -[10.18164, "o", "c"] -[10.333507, "o", "d"] -[10.469465, "o", "n"] -[10.621609, "o", " "] -[10.741661, "o", "g"] -[10.853591, "o", "e"] -[10.949505, "o", "t"] -[11.021485, "o", " "] -[11.229625, "o", "-"] -[11.413535, "o", "-"] -[11.613595, "o", "v"] -[11.741515, "o", "e"] -[11.821528, "o", "r"] -[12.069542, "o", "b"] -[12.181521, "o", "o"] -[12.26152, "o", "s"] -[12.405474, "o", "e"] -[12.77367, "o", "\r\n"] -[13.3928, "o", "Retrieving status of Public CDN...\r\n"] -[13.559112, "o", "Public CDN at https://contoso-admin.sharepoint.com is enabled\r\n"] -[13.561219, "o", "\u001b[32mDONE\u001b[39m\r\n"] -[13.563615, "o", "\u001b]0;root@DESKTOP-5PARO7S: ~\u0007root@DESKTOP-5PARO7S:~# "] -[15.197647, "o", "exit\r\n"] From e88aacd7df54a678deb2a6a59cbebdb63f21b932 Mon Sep 17 00:00:00 2001 From: Jwaegebaert <38426621+Jwaegebaert@users.noreply.github.com> Date: Thu, 19 Mar 2026 12:06:15 +0100 Subject: [PATCH 2/2] Implemented Copilot suggestions --- docs/docusaurus.config.ts | 8 --- docs/package-lock.json | 64 +++++++++++++-------- docs/package.json | 2 +- docs/src/components/CommandPlayer.tsx | 37 +++++++----- docs/src/remark/commandPlayer.ts | 75 ++++++++++++++++++------- docs/src/scss/CommandPlayer.module.scss | 4 +- 6 files changed, 122 insertions(+), 68 deletions(-) diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts index 7ce0d8d7ecb..3e22de86fab 100644 --- a/docs/docusaurus.config.ts +++ b/docs/docusaurus.config.ts @@ -25,14 +25,6 @@ const config: Config = { organizationName: 'pnp', projectName: 'cli-microsoft365', - headTags: [ - { - tagName: 'script', - attributes: { type: 'text/javascript' }, - innerHTML: 'window.gtag=window.gtag||function(){(window.dataLayer=window.dataLayer||[]).push(arguments)};' - } - ], - i18n: { defaultLocale: 'en', locales: ['en'] diff --git a/docs/package-lock.json b/docs/package-lock.json index 9fefee97ef5..7fab1bb2ea8 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -15,6 +15,7 @@ "@docusaurus/theme-mermaid": "^3.9.2", "@docusaurus/types": "^3.9.2", "@mdx-js/react": "^3.1.1", + "acorn": "^8.14.0", "clsx": "^2.1.1", "docusaurus-plugin-sass": "^0.2.6", "mdast-util-from-markdown": "^2.0.3", @@ -26,7 +27,6 @@ "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "baseline-browser-mapping": "^2.10.8", "typescript": "^5.9.3" }, "engines": { @@ -239,6 +239,7 @@ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.42.0.tgz", "integrity": "sha512-NZR7yyHj2WzK6D5X8gn+/KOxPdzYEXOqVdSaK/biU8QfYUpUuEA0sCWg/XlO05tPVEcJelF/oLrrNY3UjRbOww==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/client-common": "5.42.0", "@algolia/requester-browser-xhr": "5.42.0", @@ -399,6 +400,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.4.tgz", "integrity": "sha512-bXYxrXFubeYdvB0NhD/NBB3Qi6aZeV20GOWVI47t2dkecCEoneR4NPVcb7abpXDEvejgrUfFtG6vG/zxAKmg+g==", "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -2220,6 +2222,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" }, @@ -2242,6 +2245,7 @@ } ], "license": "MIT", + "peer": true, "engines": { "node": ">=18" } @@ -2351,6 +2355,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -2772,6 +2777,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -3466,6 +3472,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/babel": "3.9.2", "@docusaurus/bundler": "3.9.2", @@ -3542,6 +3549,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/faster/-/faster-3.9.2.tgz", "integrity": "sha512-DEVIwhbrZZ4ir31X+qQNEQqDWkgCJUV6kiPPAd2MGTY8n5/n0c4B8qA5k1ipF2izwH00JEf0h6Daaut71zzkyw==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/types": "3.9.2", "@rspack/core": "^1.5.0", @@ -3694,6 +3702,7 @@ "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", "license": "MIT", + "peer": true, "dependencies": { "@docusaurus/core": "3.9.2", "@docusaurus/logger": "3.9.2", @@ -4486,6 +4495,7 @@ "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", "license": "MIT", + "peer": true, "dependencies": { "@types/mdx": "^2.0.0" }, @@ -4622,7 +4632,6 @@ "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==", "hasInstallScript": true, "optional": true, - "peer": true, "dependencies": { "detect-libc": "^1.0.3", "is-glob": "^4.0.3", @@ -4663,7 +4672,6 @@ "os": [ "android" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4683,7 +4691,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4703,7 +4710,6 @@ "os": [ "darwin" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4723,7 +4729,6 @@ "os": [ "freebsd" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4743,7 +4748,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4763,7 +4767,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4783,7 +4786,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4803,7 +4805,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4823,7 +4824,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4843,7 +4843,6 @@ "os": [ "linux" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4863,7 +4862,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4883,7 +4881,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -4903,7 +4900,6 @@ "os": [ "win32" ], - "peer": true, "engines": { "node": ">= 10.0.0" }, @@ -5352,6 +5348,7 @@ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/core": "^7.21.3", "@svgr/babel-preset": "8.1.0", @@ -5456,6 +5453,7 @@ "integrity": "sha512-mAby9aUnKRjMEA7v8cVZS9Ah4duoRBnX7X6r5qrhTxErx+68MoY1TPrVwj/66/SWN3Bl+jijqAqoB8Qx0QE34A==", "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.21" @@ -6382,6 +6380,7 @@ "version": "18.3.16", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.16.tgz", "integrity": "sha512-oh8AMIC4Y2ciKufU8hnKgs+ufgbA/dhPTACaZPM86AbwX9QwnFtSoPWEeRUj8fge+v6kFt78BXcDhAU1SrrAsw==", + "peer": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -6719,6 +6718,7 @@ "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -6792,6 +6792,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -6837,6 +6838,7 @@ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.42.0.tgz", "integrity": "sha512-X5+PtWc9EJIPafT/cj8ZG+6IU3cjRRnlHGtqMHK/9gsiupQbAyYlH5y7qt/FtsAhfX5AICHffZy69ZAsVrxWkQ==", "license": "MIT", + "peer": true, "dependencies": { "@algolia/abtesting": "1.8.0", "@algolia/client-abtesting": "5.42.0", @@ -7312,6 +7314,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.8.19", "caniuse-lite": "^1.0.30001751", @@ -7607,6 +7610,7 @@ "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-11.0.3.tgz", "integrity": "sha512-ci2iJH6LeIkvP9eJW6gpueU8cnZhv85ELY8w8WiFtNjMHA5ad6pQLaJo9mEly/9qUyCpvqX8/POVUTf18/HFdw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@chevrotain/cst-dts-gen": "11.0.3", "@chevrotain/gast": "11.0.3", @@ -8296,6 +8300,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8613,6 +8618,7 @@ "resolved": "https://registry.npmjs.org/cytoscape/-/cytoscape-3.32.0.tgz", "integrity": "sha512-5JHBC9n75kz5851jeklCPmZWcg3hUe6sjqJvyk3+hVqFaKcHwHgxsjeN1yLmggoUc6STbtm9/NQyabQehfjvWQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10" } @@ -9022,6 +9028,7 @@ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "license": "ISC", + "peer": true, "engines": { "node": ">=12" } @@ -9323,7 +9330,6 @@ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", "optional": true, - "peer": true, "bin": { "detect-libc": "bin/detect-libc.js" }, @@ -10206,6 +10212,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -11306,8 +11313,7 @@ "node_modules/immutable": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", - "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "peer": true + "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==" }, "node_modules/import-fresh": { "version": "3.3.1", @@ -14869,8 +14875,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", - "optional": true, - "peer": true + "optional": true }, "node_modules/node-emoji": { "version": "2.2.0", @@ -14985,6 +14990,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -15539,6 +15545,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -16442,6 +16449,7 @@ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz", "integrity": "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==", "license": "MIT", + "peer": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -17259,6 +17267,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -17268,6 +17277,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -17321,6 +17331,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/@docusaurus/react-loadable/-/react-loadable-6.0.0.tgz", "integrity": "sha512-YMMxTUQV/QFSnbgrP3tjDzLHRg7vsbMn8e9HAa8o/1iXoiomo48b7sk/kkmWEuWNDPJVlKSJRB6Y2fHqdJk+SQ==", + "peer": true, "dependencies": { "@types/react": "*" }, @@ -17348,6 +17359,7 @@ "version": "5.3.4", "resolved": "https://registry.npmjs.org/react-router/-/react-router-5.3.4.tgz", "integrity": "sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==", + "peer": true, "dependencies": { "@babel/runtime": "^7.12.13", "history": "^4.9.0", @@ -18058,7 +18070,6 @@ "version": "1.82.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.82.0.tgz", "integrity": "sha512-j4GMCTa8elGyN9A7x7bEglx0VgSpNUG4W4wNedQ33wSMdnkqQCT8HTwOaVSV4e6yQovcu/3Oc4coJP/l0xhL2Q==", - "peer": true, "dependencies": { "chokidar": "^4.0.0", "immutable": "^5.0.2", @@ -18117,7 +18128,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "peer": true, "dependencies": { "readdirp": "^4.0.1" }, @@ -18132,7 +18142,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "peer": true, "engines": { "node": ">= 14.16.0" }, @@ -19098,6 +19107,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -19307,7 +19317,8 @@ "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "peer": true }, "node_modules/type-fest": { "version": "2.19.0", @@ -19370,6 +19381,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -19711,6 +19723,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -19968,6 +19981,7 @@ "version": "5.97.1", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.6", @@ -20237,6 +20251,7 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -20592,6 +20607,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/docs/package.json b/docs/package.json index e5b5d504b95..af4b25dc3bc 100644 --- a/docs/package.json +++ b/docs/package.json @@ -28,12 +28,12 @@ "prism-react-renderer": "^2.4.1", "react": "^19.2.4", "react-dom": "^19.2.4", + "acorn": "^8.14.0", "unist-util-visit": "^5.1.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "^3.9.2", "@docusaurus/tsconfig": "^3.9.2", - "baseline-browser-mapping": "^2.10.8", "typescript": "^5.9.3" }, "browserslist": { diff --git a/docs/src/components/CommandPlayer.tsx b/docs/src/components/CommandPlayer.tsx index 0a76da8029c..7f340d070b8 100644 --- a/docs/src/components/CommandPlayer.tsx +++ b/docs/src/components/CommandPlayer.tsx @@ -243,26 +243,30 @@ const CommandPlayer: React.FC = ({ } }; - const handleWheel = (): void => { + const markUserScrolling = (): void => { userScrolling = true; if (scrollTimeout) clearTimeout(scrollTimeout); scrollTimeout = setTimeout(() => { userScrolling = false; }, SCROLL_DETECT_TIMEOUT); }; - const handleTouchMove = (): void => { - userScrolling = true; - if (scrollTimeout) clearTimeout(scrollTimeout); - scrollTimeout = setTimeout(() => { userScrolling = false; }, SCROLL_DETECT_TIMEOUT); + const handleKeyDown = (e: KeyboardEvent): void => { + if (['ArrowUp', 'ArrowDown', 'PageUp', 'PageDown', 'Home', 'End', ' '].includes(e.key)) { + markUserScrolling(); + } }; el.addEventListener('scroll', handleScroll, { passive: true }); - el.addEventListener('wheel', handleWheel, { passive: true }); - el.addEventListener('touchmove', handleTouchMove, { passive: true }); + el.addEventListener('wheel', markUserScrolling, { passive: true }); + el.addEventListener('touchmove', markUserScrolling, { passive: true }); + el.addEventListener('pointerdown', markUserScrolling, { passive: true }); + el.addEventListener('keydown', handleKeyDown); return () => { el.removeEventListener('scroll', handleScroll); - el.removeEventListener('wheel', handleWheel); - el.removeEventListener('touchmove', handleTouchMove); + el.removeEventListener('wheel', markUserScrolling); + el.removeEventListener('touchmove', markUserScrolling); + el.removeEventListener('pointerdown', markUserScrolling); + el.removeEventListener('keydown', handleKeyDown); if (scrollTimeout) clearTimeout(scrollTimeout); }; }, [mounted, doPause, doResume]); @@ -440,6 +444,11 @@ const CommandPlayer: React.FC = ({ const currentStepIdx = displayedSteps; + const highlightedResponses = useMemo( + () => formattedResponses.map((response) => (response ? highlightJson(response) : null)), + [formattedResponses] + ); + return (
@@ -458,9 +467,9 @@ const CommandPlayer: React.FC = ({ > {step.command}
- {formattedResponses[i] && ( + {highlightedResponses[i] && (
- {highlightJson(formattedResponses[i])} + {highlightedResponses[i]}
)}
@@ -475,9 +484,9 @@ const CommandPlayer: React.FC = ({ {phase === 'typing-command' && }
- {showCurrentResponse && formattedResponses[currentStepIdx] && ( + {showCurrentResponse && highlightedResponses[currentStepIdx] && (
- {highlightJson(formattedResponses[currentStepIdx])} + {highlightedResponses[currentStepIdx]}
)} @@ -494,7 +503,7 @@ const CommandPlayer: React.FC = ({ )} - {mounted && phase !== 'idle' && ( + {mounted && !prefersReducedMotion() && phase !== 'idle' && (