chore: import upstream snapshot with attribution
publish / version_or_publish (push) Has been cancelled
storybook-build / changes (push) Has been cancelled
storybook-build / :storybook-build (push) Has been cancelled
Sync Gradio Skills to Hugging Face / sync-skills (push) Has been cancelled
functional / changes (push) Has been cancelled
functional / build-frontend (push) Has been cancelled
functional / functional-test-SSR=false (push) Has been cancelled
functional / functional-reload (push) Has been cancelled
js / changes (push) Has been cancelled
js / js-test (push) Has been cancelled
docs-build / changes (push) Has been cancelled
docs-build / docs-build (push) Has been cancelled
docs-build / website-build (push) Has been cancelled
functional / functional-test-SSR=true (push) Has been cancelled
hygiene / hygiene-test (push) Has been cancelled
python / changes (push) Has been cancelled
python / build (push) Has been cancelled
python / test-ubuntu-latest-flaky (push) Has been cancelled
python / test-ubuntu-latest-not-flaky (push) Has been cancelled
python / test-windows-latest-flaky (push) Has been cancelled
python / test-windows-latest-not-flaky (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 13:17:32 +08:00
commit adf0d17497
3085 changed files with 456962 additions and 0 deletions
+345
View File
@@ -0,0 +1,345 @@
<script lang="ts">
import { onMount } from "svelte";
import {
EditorView,
ViewUpdate,
keymap,
placeholder as placeholderExt,
lineNumbers
} from "@codemirror/view";
import { StateEffect, EditorState, type Extension } from "@codemirror/state";
import { indentWithTab } from "@codemirror/commands";
import { autocompletion, acceptCompletion } from "@codemirror/autocomplete";
import { basicDark } from "cm6-theme-basic-dark";
import { basicLight } from "cm6-theme-basic-light";
import { basicSetup } from "./extensions";
import { getLanguageExtension } from "./language";
interface Props {
class_names?: string;
value?: string;
dark_mode: boolean;
basic?: boolean;
language: string;
lines?: number;
max_lines?: number | null;
extensions?: Extension[];
use_tab?: boolean;
readonly?: boolean;
placeholder?: string | HTMLElement | null | undefined;
wrap_lines?: boolean;
show_line_numbers?: boolean;
autocomplete?: boolean;
onchange?: (value: string) => void;
onblur?: () => void;
onfocus?: () => void;
oninput?: () => void;
}
let {
class_names = "",
value = $bindable(),
dark_mode,
basic = true,
language,
lines = 5,
max_lines = null,
extensions = [],
use_tab = true,
readonly = false,
placeholder = undefined,
wrap_lines = false,
show_line_numbers = true,
autocomplete = false,
onchange,
onblur,
onfocus,
oninput
}: Props = $props();
let lang_extension: Extension | undefined = $state();
let element: HTMLDivElement;
let view: EditorView;
async function get_lang(val: string): Promise<void> {
const ext = await getLanguageExtension(val);
lang_extension = ext;
}
$effect(() => {
get_lang(language);
});
$effect(() => {
lang_extension;
readonly;
reconfigure();
});
$effect(() => {
set_doc(value ?? "");
});
update_lines();
function set_doc(new_doc: string): void {
if (view && new_doc !== view.state.doc.toString()) {
view.dispatch({
changes: {
from: 0,
to: view.state.doc.length,
insert: new_doc
}
});
}
}
function update_lines(): void {
if (view) {
view.requestMeasure({ read: resize });
}
}
function create_editor_view(): EditorView {
const editorView = new EditorView({
parent: element,
state: create_editor_state(value)
});
editorView.dom.addEventListener("focus", handle_focus, true);
editorView.dom.addEventListener("blur", handle_blur, true);
return editorView;
}
function handle_focus(): void {
onfocus?.();
}
function handle_blur(): void {
onblur?.();
}
function getGutterLineHeight(_view: EditorView): string | null {
let elements = _view.dom.querySelectorAll<HTMLElement>(".cm-gutterElement");
if (elements.length === 0) {
return null;
}
for (var i = 0; i < elements.length; i++) {
let node = elements[i];
let height = getComputedStyle(node)?.height ?? "0px";
if (height != "0px") {
return height;
}
}
return null;
}
function resize(_view: EditorView): any {
let scroller = _view.dom.querySelector<HTMLElement>(".cm-scroller");
if (!scroller) {
return null;
}
const lineHeight = getGutterLineHeight(_view);
if (!lineHeight) {
return null;
}
const minLines = lines == 1 ? 1 : lines + 1;
scroller.style.minHeight = `calc(${lineHeight} * ${minLines})`;
if (max_lines)
scroller.style.maxHeight = `calc(${lineHeight} * ${max_lines + 1})`;
}
import { Transaction } from "@codemirror/state";
function is_user_input(update: ViewUpdate): boolean {
return update.transactions.some(
(tr) => tr.annotation(Transaction.userEvent) != null
);
}
function handle_change(vu: ViewUpdate): void {
if (!vu.docChanged) return;
const doc = vu.state.doc;
const text = doc.toString();
value = text;
const user_change = is_user_input(vu);
if (user_change) {
onchange?.(text);
oninput?.();
} else {
onchange?.(text);
}
view.requestMeasure({ read: resize });
}
function get_extensions(): Extension[] {
const stateExtensions = [
...get_base_extensions(
basic,
use_tab,
placeholder,
readonly,
lang_extension,
show_line_numbers
),
FontTheme,
...get_theme(),
...extensions
];
return stateExtensions;
}
const FontTheme = EditorView.theme({
"&": {
fontSize: "var(--text-sm)",
backgroundColor: "var(--border-color-secondary)"
},
".cm-content": {
paddingTop: "5px",
paddingBottom: "5px",
color: "var(--body-text-color)",
fontFamily: "var(--font-mono)",
minHeight: "100%"
},
".cm-gutterElement": {
marginRight: "var(--spacing-xs)"
},
".cm-gutters": {
marginRight: "1px",
borderRight: "1px solid var(--border-color-primary)",
backgroundColor: "var(--block-background-fill);",
color: "var(--body-text-color-subdued)"
},
".cm-focused": {
outline: "none"
},
".cm-scroller": {
height: "auto"
},
".cm-cursor": {
borderLeftColor: "var(--body-text-color)"
}
});
const AutocompleteTheme = EditorView.theme({
".cm-tooltip-autocomplete": {
"& > ul": {
backgroundColor: "var(--background-fill-primary)",
color: "var(--body-text-color)"
},
"& > ul > li[aria-selected]": {
backgroundColor: "var(--color-accent-soft)",
color: "var(--body-text-color)"
}
}
});
function create_editor_state(_value: string | null | undefined): EditorState {
return EditorState.create({
doc: _value ?? undefined,
extensions: get_extensions()
});
}
function get_base_extensions(
basic: boolean,
use_tab: boolean,
placeholder: string | HTMLElement | null | undefined,
readonly: boolean,
lang: Extension | null | undefined,
show_line_numbers: boolean
): Extension[] {
const extensions: Extension[] = [
EditorView.editable.of(!readonly),
EditorState.readOnly.of(readonly),
EditorView.contentAttributes.of({ "aria-label": "Code input container" })
];
if (basic) {
extensions.push(basicSetup);
}
if (use_tab) {
extensions.push(
keymap.of([{ key: "Tab", run: acceptCompletion }, indentWithTab])
);
}
if (placeholder) {
extensions.push(placeholderExt(placeholder));
}
if (lang) {
extensions.push(lang);
}
if (show_line_numbers) {
extensions.push(lineNumbers());
}
if (autocomplete) {
extensions.push(autocompletion());
extensions.push(AutocompleteTheme);
}
extensions.push(EditorView.updateListener.of(handle_change));
if (wrap_lines) {
extensions.push(EditorView.lineWrapping);
}
return extensions;
}
function get_theme(): Extension[] {
const extensions: Extension[] = [];
if (dark_mode) {
extensions.push(basicDark);
} else {
extensions.push(basicLight);
}
return extensions;
}
function reconfigure(): void {
view?.dispatch({
effects: StateEffect.reconfigure.of(get_extensions())
});
}
onMount(() => {
view = create_editor_view();
return () => view?.destroy();
});
</script>
<div class="wrap">
<div class="codemirror-wrapper {class_names}" bind:this={element} />
</div>
<style>
.wrap {
display: flex;
flex-direction: column;
flex-grow: 1;
margin: 0;
padding: 0;
height: 100%;
}
.codemirror-wrapper {
flex-grow: 1;
overflow: auto;
}
:global(.cm-editor) {
height: 100%;
}
/* Dunno why this doesn't work through the theme API -- don't remove*/
:global(.cm-selectionBackground) {
background-color: #b9d2ff30 !important;
}
:global(.cm-focused) {
outline: none !important;
}
</style>
+35
View File
@@ -0,0 +1,35 @@
<script lang="ts">
import { onDestroy } from "svelte";
import { Copy, Check } from "@gradio/icons";
import { IconButton } from "@gradio/atoms";
interface Props {
value: string;
}
let { value }: Props = $props();
let copied = $state(false);
let timer: NodeJS.Timeout;
function copy_feedback(): void {
copied = true;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
copied = false;
}, 2000);
}
async function handle_copy(): Promise<void> {
if ("clipboard" in navigator) {
await navigator.clipboard.writeText(value);
copy_feedback();
}
}
onDestroy(() => {
if (timer) clearTimeout(timer);
});
</script>
<IconButton Icon={copied ? Check : Copy} label="Copy" onclick={handle_copy} />
+67
View File
@@ -0,0 +1,67 @@
<script lang="ts">
import { onDestroy } from "svelte";
import { Download, Check } from "@gradio/icons";
import { DownloadLink } from "@gradio/atoms";
import { IconButton } from "@gradio/atoms";
interface Props {
value: string;
language: string;
}
let { value, language }: Props = $props();
let ext = $derived(get_ext_for_type(language));
function get_ext_for_type(type: string): string {
const exts: Record<string, string> = {
py: "py",
python: "py",
md: "md",
markdown: "md",
json: "json",
html: "html",
css: "css",
js: "js",
javascript: "js",
ts: "ts",
typescript: "ts",
yaml: "yaml",
yml: "yml",
dockerfile: "dockerfile",
sh: "sh",
shell: "sh",
r: "r",
c: "c",
cpp: "cpp",
latex: "tex"
};
return exts[type] || "txt";
}
let copied = $state(false);
let timer: NodeJS.Timeout;
function copy_feedback(): void {
copied = true;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
copied = false;
}, 2000);
}
let download_value = $derived(URL.createObjectURL(new Blob([value])));
onDestroy(() => {
if (timer) clearTimeout(timer);
});
</script>
<DownloadLink
download="file.{ext}"
href={download_value}
onclick={copy_feedback}
>
<IconButton Icon={copied ? Check : Download} label="Download" />
</DownloadLink>
+29
View File
@@ -0,0 +1,29 @@
<script lang="ts">
import Copy from "./Copy.svelte";
import Download from "./Download.svelte";
import { IconButtonWrapper } from "@gradio/atoms";
import type { CustomButton as CustomButtonType } from "@gradio/utils";
interface Props {
value: string;
language: string;
buttons?: (string | CustomButtonType)[] | null;
on_custom_button_click?: ((id: number) => void) | null;
}
let {
value,
language,
buttons = null,
on_custom_button_click = null
}: Props = $props();
</script>
<IconButtonWrapper {buttons} {on_custom_button_click}>
{#if buttons?.some((btn) => typeof btn === "string" && btn === "download")}
<Download {value} {language} />
{/if}
{#if buttons?.some((btn) => typeof btn === "string" && btn === "copy")}
<Copy {value} />
{/if}
</IconButtonWrapper>
+47
View File
@@ -0,0 +1,47 @@
import type { Extension } from "@codemirror/state";
import {
lineNumbers,
highlightSpecialChars,
drawSelection,
rectangularSelection,
crosshairCursor,
keymap
} from "@codemirror/view";
export { EditorView } from "@codemirror/view";
import { EditorState } from "@codemirror/state";
import {
foldGutter,
indentOnInput,
syntaxHighlighting,
defaultHighlightStyle,
foldKeymap
} from "@codemirror/language";
import { history, defaultKeymap, historyKeymap } from "@codemirror/commands";
import {
closeBrackets,
closeBracketsKeymap,
completionKeymap
} from "@codemirror/autocomplete";
import { lintKeymap } from "@codemirror/lint";
export const basicSetup: Extension = /*@__PURE__*/ ((): Extension[] => [
highlightSpecialChars(),
history(),
foldGutter(),
drawSelection(),
EditorState.allowMultipleSelections.of(true),
indentOnInput(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
closeBrackets(),
rectangularSelection(),
crosshairCursor(),
keymap.of([
...closeBracketsKeymap,
...defaultKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
...lintKeymap
])
])();
+61
View File
@@ -0,0 +1,61 @@
import type {
Element,
MarkdownExtension,
BlockContext,
Line
} from "@lezer/markdown";
import { parseMixed } from "@lezer/common";
import { yaml } from "@codemirror/legacy-modes/mode/yaml";
import { foldInside, foldNodeProp, StreamLanguage } from "@codemirror/language";
import { styleTags, tags } from "@lezer/highlight";
const frontMatterFence = /^---\s*$/m;
export const frontmatter: MarkdownExtension = {
defineNodes: [{ name: "Frontmatter", block: true }, "FrontmatterMark"],
props: [
styleTags({
Frontmatter: [tags.documentMeta, tags.monospace],
FrontmatterMark: tags.processingInstruction
}),
foldNodeProp.add({
Frontmatter: foldInside,
FrontmatterMark: () => null
})
],
wrap: parseMixed((node) => {
const { parser } = StreamLanguage.define(yaml);
if (node.type.name === "Frontmatter") {
return {
parser,
overlay: [{ from: node.from + 4, to: node.to - 4 }]
};
}
return null;
}),
parseBlock: [
{
name: "Frontmatter",
before: "HorizontalRule",
parse: (cx: BlockContext, line: Line): boolean => {
let end: number | undefined = undefined;
const children = new Array<Element>();
if (cx.lineStart === 0 && frontMatterFence.test(line.text)) {
children.push(cx.elt("FrontmatterMark", 0, 4));
while (cx.nextLine()) {
if (frontMatterFence.test(line.text)) {
end = cx.lineStart + 4;
break;
}
}
if (end !== undefined) {
children.push(cx.elt("FrontmatterMark", end - 4, end));
cx.addElement(cx.elt("Frontmatter", 0, end, children));
}
return true;
}
return false;
}
}
]
};
+102
View File
@@ -0,0 +1,102 @@
import type { Extension } from "@codemirror/state";
import { StreamLanguage } from "@codemirror/language";
import { _ } from "svelte-i18n";
const sql_dialects = [
"standardSQL",
"msSQL",
"mySQL",
"mariaDB",
"sqlite",
"cassandra",
"plSQL",
"hive",
"pgSQL",
"gql",
"gpSQL",
"sparkSQL",
"esper"
] as const;
const lang_map: Record<string, (() => Promise<Extension>) | undefined> = {
python: () => import("@codemirror/lang-python").then((m) => m.python()),
c: () =>
import("@codemirror/legacy-modes/mode/clike").then((m) =>
StreamLanguage.define(m.c)
),
cpp: () =>
import("@codemirror/legacy-modes/mode/clike").then((m) =>
StreamLanguage.define(m.cpp)
),
markdown: async () => {
const [md, frontmatter] = await Promise.all([
import("@codemirror/lang-markdown"),
import("./frontmatter")
]);
return md.markdown({ extensions: [frontmatter.frontmatter] });
},
latex: () =>
import("@codemirror/legacy-modes/mode/stex").then((m) =>
StreamLanguage.define(m.stex)
),
json: () => import("@codemirror/lang-json").then((m) => m.json()),
html: () => import("@codemirror/lang-html").then((m) => m.html()),
css: () => import("@codemirror/lang-css").then((m) => m.css()),
javascript: () =>
import("@codemirror/lang-javascript").then((m) => m.javascript()),
jinja2: () =>
import("@codemirror/legacy-modes/mode/jinja2").then((m) =>
StreamLanguage.define(m.jinja2)
),
typescript: () =>
import("@codemirror/lang-javascript").then((m) =>
m.javascript({ typescript: true })
),
yaml: () =>
import("@codemirror/legacy-modes/mode/yaml").then((m) =>
StreamLanguage.define(m.yaml)
),
dockerfile: () =>
import("@codemirror/legacy-modes/mode/dockerfile").then((m) =>
StreamLanguage.define(m.dockerFile)
),
shell: () =>
import("@codemirror/legacy-modes/mode/shell").then((m) =>
StreamLanguage.define(m.shell)
),
r: () =>
import("@codemirror/legacy-modes/mode/r").then((m) =>
StreamLanguage.define(m.r)
),
sql: () =>
import("@codemirror/legacy-modes/mode/sql").then((m) =>
StreamLanguage.define(m.standardSQL)
),
...Object.fromEntries(
sql_dialects.map((dialect) => [
"sql-" + dialect,
() =>
import("@codemirror/legacy-modes/mode/sql").then((m) =>
StreamLanguage.define(m[dialect])
)
])
)
} as const;
const alias_map: Record<string, string> = {
py: "python",
md: "markdown",
js: "javascript",
ts: "typescript",
sh: "shell"
};
export async function getLanguageExtension(
lang: string
): Promise<Extension | undefined> {
const _lang = lang_map[lang] || lang_map[alias_map[lang]] || undefined;
if (_lang) {
return _lang();
}
return undefined;
}