Markdown documentation for HTTP requests (#145)

This commit is contained in:
Gregory Schier
2024-12-19 05:57:40 -08:00
committed by GitHub
parent 42d350ef27
commit 833dc7d3f7
30 changed files with 2274 additions and 251 deletions

View File

@@ -1,7 +1,7 @@
import classNames from 'classnames';
interface Props {
count: number;
count: number | true;
className?: string;
}
@@ -12,10 +12,11 @@ export function CountBadge({ count, className }: Props) {
aria-hidden
className={classNames(
className,
'flex items-center',
'opacity-70 border border-border-subtle text-4xs rounded mb-0.5 px-1 ml-1 h-4 font-mono',
)}
>
{count}
{count === true ? <div aria-hidden className="rounded-full h-1 w-1 bg-text-subtle" /> : count}
</div>
);
}

View File

@@ -21,7 +21,7 @@
.cm-line {
@apply w-full;
/* Important! Ensure it spans the entire width */
@apply w-full text-text pl-1 pr-1.5;
@apply w-full text-text px-0;
}
.cm-placeholder {
@@ -51,7 +51,7 @@
/* Style gutters */
.cm-gutters {
@apply border-0 text-text-subtlest bg-surface;
@apply border-0 text-text-subtlest bg-surface pr-1.5;
/* Not sure why, but there's a tiny gap left of the gutter that you can see text
through. Move left slightly to fix that. */
@apply -left-[1px];
@@ -114,12 +114,6 @@
.cm-scroller {
@apply font-mono text-editor;
/*
* Round corners or they'll stick out of the editor bounds of editor is rounded.
* Could potentially be pushed up from the editor like we do with bg color but this
* is probably fine.
*/
@apply rounded-lg;
}
}
}

View File

@@ -8,12 +8,12 @@ import classNames from 'classnames';
import { EditorView } from 'codemirror';
import type { MutableRefObject, ReactNode } from 'react';
import {
useEffect,
Children,
cloneElement,
forwardRef,
isValidElement,
useCallback,
useEffect,
useImperativeHandle,
useMemo,
useRef,
@@ -45,7 +45,16 @@ export interface EditorProps {
type?: 'text' | 'password';
className?: string;
heightMode?: 'auto' | 'full';
language?: 'javascript' | 'json' | 'html' | 'xml' | 'graphql' | 'url' | 'pairs' | 'text';
language?:
| 'javascript'
| 'json'
| 'html'
| 'xml'
| 'graphql'
| 'url'
| 'pairs'
| 'text'
| 'markdown';
forceUpdateKey?: string | number;
autoFocus?: boolean;
autoSelect?: boolean;
@@ -66,6 +75,7 @@ export interface EditorProps {
autocompleteVariables?: boolean;
extraExtensions?: Extension[];
actions?: ReactNode;
hideGutter?: boolean;
}
const emptyVariables: EnvironmentVariable[] = [];
@@ -96,6 +106,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
autocompleteVariables,
actions,
wrapLines,
hideGutter,
}: EditorProps,
ref,
) {
@@ -310,6 +321,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
container,
readOnly,
singleLine,
hideGutter,
onChange: handleChange,
onPaste: handlePaste,
onPasteOverwrite: handlePasteOverwrite,
@@ -374,7 +386,7 @@ export const Editor = forwardRef<EditorView | undefined, EditorProps>(function E
const decoratedActions = useMemo(() => {
const results = [];
const actionClassName = classNames(
'bg-surface transition-opacity opacity-0 group-hover:opacity-100 hover:!opacity-100 shadow',
'bg-surface transition-opacity transform-gpu opacity-0 group-hover:opacity-100 hover:!opacity-100 shadow',
);
if (format) {
@@ -455,13 +467,14 @@ function getExtensions({
container,
readOnly,
singleLine,
hideGutter,
onChange,
onPaste,
onPasteOverwrite,
onFocus,
onBlur,
onKeyDown,
}: Pick<EditorProps, 'singleLine' | 'readOnly'> & {
}: Pick<EditorProps, 'singleLine' | 'readOnly' | 'hideGutter'> & {
container: HTMLDivElement | null;
onChange: MutableRefObject<EditorProps['onChange']>;
onPaste: MutableRefObject<EditorProps['onPaste']>;
@@ -499,7 +512,7 @@ function getExtensions({
tooltips({ parent }),
keymap.of(singleLine ? defaultKeymap.filter((k) => k.key !== 'Enter') : defaultKeymap),
...(singleLine ? [singleLineExt()] : []),
...(!singleLine ? [multiLineExtensions] : []),
...(!singleLine ? [multiLineExtensions({ hideGutter })] : []),
...(readOnly
? [EditorState.readOnly.of(true), EditorView.contentAttributes.of({ tabindex: '-1' })]
: []),

View File

@@ -6,6 +6,7 @@ import {
} from '@codemirror/autocomplete';
import { history, historyKeymap, indentWithTab } from '@codemirror/commands';
import { javascript } from '@codemirror/lang-javascript';
import { markdown } from '@codemirror/lang-markdown';
import { json } from '@codemirror/lang-json';
import { xml } from '@codemirror/lang-xml';
import type { LanguageSupport } from '@codemirror/language';
@@ -79,6 +80,7 @@ const syntaxExtensions: Record<NonNullable<EditorProps['language']>, LanguageSup
url: url(),
pairs: pairs(),
text: text(),
markdown: markdown(),
};
export function getLanguageExtension({
@@ -138,21 +140,25 @@ export const baseExtensions = [
keymap.of([...historyKeymap, ...completionKeymap]),
];
export const multiLineExtensions = [
lineNumbers(),
foldGutter({
markerDOM: (open) => {
const el = document.createElement('div');
el.classList.add('fold-gutter-icon');
el.tabIndex = -1;
if (open) {
el.setAttribute('data-open', '');
}
return el;
},
}),
export const multiLineExtensions = ({ hideGutter }: { hideGutter?: boolean }) => [
hideGutter
? []
: [
lineNumbers(),
foldGutter({
markerDOM: (open) => {
const el = document.createElement('div');
el.classList.add('fold-gutter-icon');
el.tabIndex = -1;
if (open) {
el.setAttribute('data-open', '');
}
return el;
},
}),
],
codeFolding({
placeholderDOM(view, onclick, prepared) {
placeholderDOM(_view, onclick, prepared) {
const el = document.createElement('span');
el.onclick = onclick;
el.className = 'cm-foldPlaceholder';

View File

@@ -30,6 +30,7 @@ const icons = {
circle_alert: lucide.CircleAlertIcon,
clock: lucide.ClockIcon,
code: lucide.CodeIcon,
columns_2: lucide.Columns2Icon,
cookie: lucide.CookieIcon,
copy: lucide.CopyIcon,
copy_check: lucide.CopyCheck,

View File

@@ -1,4 +1,4 @@
import useResizeObserver from '@react-hook/resize-observer';
import useSize from '@react-hook/size';
import classNames from 'classnames';
import type { CSSProperties, MouseEvent as ReactMouseEvent, ReactNode } from 'react';
import React, { useCallback, useMemo, useRef, useState } from 'react';
@@ -43,7 +43,6 @@ export function SplitLayout({
}: Props) {
const containerRef = useRef<HTMLDivElement>(null);
const activeWorkspace = useActiveWorkspace();
const [verticalBasedOnSize, setVerticalBasedOnSize] = useState<boolean>(false);
const [widthRaw, setWidth] = useLocalStorage<number>(
`${name}_width::${activeWorkspace?.id ?? 'n/a'}`,
);
@@ -62,10 +61,7 @@ export function SplitLayout({
minHeightPx = 0;
}
useResizeObserver(containerRef.current, ({ contentRect }) => {
setVerticalBasedOnSize(contentRect.width < STACK_VERTICAL_WIDTH);
});
const verticalBasedOnSize = useSize(containerRef.current)[0] < STACK_VERTICAL_WIDTH;
const vertical = layout !== 'horizontal' && (layout === 'vertical' || verticalBasedOnSize);
const styles = useMemo<CSSProperties>(() => {

View File

@@ -40,6 +40,8 @@ export function Tabs({
}: Props) {
const ref = useRef<HTMLDivElement | null>(null);
value = value ?? tabs[0]?.value;
// Update tabs when value changes
useEffect(() => {
const tabs = ref.current?.querySelectorAll<HTMLDivElement>(`[data-tab]`);
@@ -61,7 +63,7 @@ export function Tabs({
return (
<div
ref={ref}
className={classNames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1')}
className={classNames(className, 'h-full grid grid-rows-[auto_minmax(0,1fr)] grid-cols-1 overflow-x-hidden')}
>
<div
aria-label={label}