feature: vor und nachteile

This commit is contained in:
Hikyu
2026-05-31 13:54:31 +02:00
parent 552a947a1c
commit e3dad17446
23270 changed files with 3024794 additions and 200 deletions
@@ -0,0 +1,17 @@
import { b as TwoslashTypesCache } from './shared/vitepress-twoslash.D0M9n6iV.mjs';
import '@shikijs/twoslash/core';
import 'twoslash';
import 'twoslash-vue';
import '@shikijs/twoslash';
interface FileSystemTypeResultCacheOptions {
/**
* The directory to store the cache files.
*
* @default '.vitepress/cache/twoslash'
*/
dir?: string;
}
declare function createFileSystemTypesCache(options?: FileSystemTypeResultCacheOptions): TwoslashTypesCache;
export { type FileSystemTypeResultCacheOptions, createFileSystemTypesCache };
@@ -0,0 +1,17 @@
import { b as TwoslashTypesCache } from './shared/vitepress-twoslash.D0M9n6iV.js';
import '@shikijs/twoslash/core';
import 'twoslash';
import 'twoslash-vue';
import '@shikijs/twoslash';
interface FileSystemTypeResultCacheOptions {
/**
* The directory to store the cache files.
*
* @default '.vitepress/cache/twoslash'
*/
dir?: string;
}
declare function createFileSystemTypesCache(options?: FileSystemTypeResultCacheOptions): TwoslashTypesCache;
export { type FileSystemTypeResultCacheOptions, createFileSystemTypesCache };
@@ -0,0 +1,29 @@
import { createHash } from 'node:crypto';
import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
import { resolve, join } from 'node:path';
import process from 'node:process';
function createFileSystemTypesCache(options = {}) {
const dir = resolve(process.cwd(), options.dir ?? ".vitepress/cache/twoslash");
return {
init() {
mkdirSync(dir, { recursive: true });
},
read(code) {
const hash = createHash("SHA256").update(code).digest("hex").slice(0, 12);
const filePath = join(dir, `${hash}.json`);
if (!existsSync(filePath)) {
return null;
}
return JSON.parse(readFileSync(filePath, { encoding: "utf-8" }));
},
write(code, data) {
const hash = createHash("SHA256").update(code).digest("hex").slice(0, 12);
const filePath = join(dir, `${hash}.json`);
const json = JSON.stringify(data);
writeFileSync(filePath, json, { encoding: "utf-8" });
}
};
}
export { createFileSystemTypesCache };
@@ -0,0 +1,14 @@
import { App } from 'vue';
import FloatingVue from 'floating-vue';
type FloatingVueConfig = Parameters<(typeof FloatingVue)['install']>[1];
/**
* Vue plugin to install FloatingVue with styles.
*
* Import this function in `.vitepress/theme/index.ts` and use `app.use(TwoslashFloatingVue)` inside the `enhanceApp` hook.
*/
declare const TwoslashFloatingVue: {
install: (app: App, options?: FloatingVueConfig) => void;
};
export { type FloatingVueConfig, TwoslashFloatingVue as default };
@@ -0,0 +1,14 @@
import { App } from 'vue';
import FloatingVue from 'floating-vue';
type FloatingVueConfig = Parameters<(typeof FloatingVue)['install']>[1];
/**
* Vue plugin to install FloatingVue with styles.
*
* Import this function in `.vitepress/theme/index.ts` and use `app.use(TwoslashFloatingVue)` inside the `enhanceApp` hook.
*/
declare const TwoslashFloatingVue: {
install: (app: App, options?: FloatingVueConfig) => void;
};
export { type FloatingVueConfig, TwoslashFloatingVue as default };
+50
View File
@@ -0,0 +1,50 @@
import FloatingVue, { recomputeAllPoppers } from 'floating-vue';
const isMobile = typeof navigator !== "undefined" && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
const TwoslashFloatingVue = {
install: (app, options = {}) => {
if (typeof window !== "undefined") {
window.addEventListener("click", (e) => {
const path = e.composedPath();
if (path.some((el) => el?.classList?.contains?.("vp-code-group") || el?.classList?.contains?.("tabs")))
recomputeAllPoppers();
}, { passive: true });
}
app.use(FloatingVue, {
...options,
themes: {
"twoslash": {
$extend: "dropdown",
triggers: isMobile ? ["touch"] : ["hover", "touch"],
popperTriggers: isMobile ? ["touch"] : ["hover", "touch"],
placement: "bottom-start",
overflowPadding: 10,
delay: 0,
handleResize: false,
autoHide: true,
instantMove: true,
flip: false,
arrowPadding: 8,
autoBoundaryMaxSize: true
},
"twoslash-query": {
$extend: "twoslash",
triggers: ["click"],
popperTriggers: ["click"],
autoHide: false
},
"twoslash-completion": {
$extend: "twoslash-query",
triggers: ["click"],
popperTriggers: ["click"],
autoHide: false,
distance: 0,
arrowOverflow: true
},
...options.theme
}
});
}
};
export { TwoslashFloatingVue as default };
@@ -0,0 +1,16 @@
import { ShikiTransformer } from 'shiki';
import { V as VitePressPluginTwoslashOptions } from './shared/vitepress-twoslash.D0M9n6iV.mjs';
export { T as TwoslashFloatingVueOptions, a as TwoslashFloatingVueRendererOptions, b as TwoslashTypesCache, r as rendererFloatingVue } from './shared/vitepress-twoslash.D0M9n6iV.mjs';
export { defaultHoverInfoProcessor } from '@shikijs/twoslash';
import '@shikijs/twoslash/core';
import 'twoslash';
import 'twoslash-vue';
/**
* Create a Shiki transformer for VitePress to enable twoslash integration
*
* Add this to `markdown.codeTransformers` in `.vitepress/config.ts`
*/
declare function transformerTwoslash(options?: VitePressPluginTwoslashOptions): ShikiTransformer;
export { VitePressPluginTwoslashOptions, transformerTwoslash };
+16
View File
@@ -0,0 +1,16 @@
import { ShikiTransformer } from 'shiki';
import { V as VitePressPluginTwoslashOptions } from './shared/vitepress-twoslash.D0M9n6iV.js';
export { T as TwoslashFloatingVueOptions, a as TwoslashFloatingVueRendererOptions, b as TwoslashTypesCache, r as rendererFloatingVue } from './shared/vitepress-twoslash.D0M9n6iV.js';
export { defaultHoverInfoProcessor } from '@shikijs/twoslash';
import '@shikijs/twoslash/core';
import 'twoslash';
import 'twoslash-vue';
/**
* Create a Shiki transformer for VitePress to enable twoslash integration
*
* Add this to `markdown.codeTransformers` in `.vitepress/config.ts`
*/
declare function transformerTwoslash(options?: VitePressPluginTwoslashOptions): ShikiTransformer;
export { VitePressPluginTwoslashOptions, transformerTwoslash };
+235
View File
@@ -0,0 +1,235 @@
import { createTransformerFactory } from '@shikijs/twoslash/core';
import { removeTwoslashNotations } from 'twoslash';
import { createTwoslasher } from 'twoslash-vue';
import { rendererRich } from '@shikijs/twoslash';
export { defaultHoverInfoProcessor } from '@shikijs/twoslash';
import { fromMarkdown } from 'mdast-util-from-markdown';
import { gfmFromMarkdown } from 'mdast-util-gfm';
import { toHast, defaultHandlers } from 'mdast-util-to-hast';
function rendererFloatingVue(options = {}) {
const {
classCopyIgnore = "vp-copy-ignore",
classFloatingPanel = "twoslash-floating",
classCode = "vp-code",
classMarkdown = "vp-doc",
floatingVueTheme = "twoslash",
floatingVueThemeQuery = "twoslash-query",
floatingVueThemeCompletion = "twoslash-completion"
} = options.floatingVue || {};
const {
errorRendering = "line"
} = options;
const hoverBasicProps = {
"class": "twoslash-hover",
"popper-class": ["shiki", classFloatingPanel, classCopyIgnore, classCode].join(" "),
"theme": floatingVueTheme
};
const rich = rendererRich({
classExtra: classCopyIgnore,
...options,
renderMarkdown,
renderMarkdownInline,
hast: {
hoverToken: {
tagName: "v-menu",
properties: hoverBasicProps
},
hoverCompose: compose,
queryToken: {
tagName: "v-menu",
properties: {
...hoverBasicProps,
":shown": "true",
"theme": floatingVueThemeQuery
}
},
queryCompose: compose,
popupDocs: {
class: `twoslash-popup-docs ${classMarkdown}`
},
popupDocsTags: {
class: `twoslash-popup-docs twoslash-popup-docs-tags ${classMarkdown}`
},
popupError: {
class: `twoslash-popup-error ${classMarkdown}`
},
errorToken: errorRendering === "line" ? undefined : {
tagName: "v-menu",
properties: {
...hoverBasicProps,
class: "twoslash-error twoslash-error-hover"
}
},
errorCompose: compose,
completionCompose({ popup, cursor }) {
return [
{
type: "element",
tagName: "v-menu",
properties: {
"popper-class": ["shiki twoslash-completion", classCopyIgnore, classFloatingPanel],
"theme": floatingVueThemeCompletion,
":shown": "true"
},
children: [
cursor,
{
type: "element",
tagName: "template",
properties: {
"v-slot:popper": "{}"
},
content: {
type: "root",
children: [vPre(popup)]
}
}
]
}
];
}
}
});
return rich;
}
function vPre(el) {
if (el.type === "element") {
el.properties = el.properties || {};
el.properties["v-pre"] = "";
}
return el;
}
function renderMarkdown(md) {
const mdast = fromMarkdown(
md.replace(/\{@link ([^}]*)\}/g, "$1"),
// replace jsdoc links
{ mdastExtensions: [gfmFromMarkdown()] }
);
return toHast(
mdast,
{
handlers: {
code: (state, node) => {
const lang = node.lang || "";
if (lang) {
return {
type: "element",
tagName: "code",
properties: {},
children: this.codeToHast(
node.value,
{
...this.options,
transformers: [],
lang,
structure: node.value.trim().includes("\n") ? "classic" : "inline"
}
).children
};
}
return defaultHandlers.code(state, node);
}
}
}
).children;
}
function renderMarkdownInline(md, context) {
if (context === "tag:param")
md = md.replace(/^([\w$-]+)/, "`$1` ");
const children = renderMarkdown.call(this, md);
if (children.length === 1 && children[0].type === "element" && children[0].tagName === "p")
return children[0].children;
return children;
}
function compose(parts) {
return [
{
type: "element",
tagName: "span",
properties: {},
children: [parts.token]
},
{
type: "element",
tagName: "template",
properties: {
"v-slot:popper": "{}"
},
content: {
type: "root",
children: [vPre(parts.popup)]
},
children: []
}
];
}
function transformerTwoslash(options = {}) {
const {
explicitTrigger = true,
typesCache
} = options;
const onError = (error, code) => {
const isCI = typeof process !== "undefined" && process?.env?.CI;
const isDev = typeof process !== "undefined" && process?.env?.NODE_ENV === "development";
const shouldThrow = (options.throws || isCI || !isDev) && options.throws !== false;
console.error(`
--------
Twoslash error in code:
--------
${code.split(/\n/g).slice(0, 15).join("\n").trim()}
--------
`);
if (shouldThrow)
throw error;
else
console.error(error);
removeTwoslashNotations(code);
};
const defaultTwoslasher = createTwoslasher(options.twoslashOptions);
let twoslasher = defaultTwoslasher;
if (typesCache) {
twoslasher = (code, extension, options2) => {
const cached = typesCache.read(code);
if (cached)
return cached;
const twoslashResult = defaultTwoslasher(code, extension, options2);
typesCache.write(code, twoslashResult);
return twoslashResult;
};
twoslasher.getCacheMap = defaultTwoslasher.getCacheMap;
}
const twoslash = createTransformerFactory(twoslasher)({
langs: ["ts", "tsx", "js", "jsx", "json", "vue"],
renderer: rendererFloatingVue(options),
onTwoslashError: onError,
onShikiError: onError,
...options,
explicitTrigger
});
const trigger = explicitTrigger instanceof RegExp ? explicitTrigger : /\btwoslash\b/;
typesCache?.init?.();
return {
...twoslash,
name: "@shikijs/vitepress-twoslash",
preprocess(code, options2) {
const cleanup = options2.transformers?.find((i) => i.name === "vitepress:clean-up");
if (cleanup)
options2.transformers?.splice(options2.transformers.indexOf(cleanup), 1);
if (!explicitTrigger || options2.meta?.__raw?.match(trigger)) {
const vPre = options2.transformers?.find((i) => i.name === "vitepress:v-pre");
if (vPre)
options2.transformers?.splice(options2.transformers.indexOf(vPre), 1);
}
return twoslash.preprocess.call(this, code, options2);
},
postprocess(html) {
if (this.meta.twoslash)
return html.replace(/\{/g, "&#123;");
}
};
}
export { rendererFloatingVue, transformerTwoslash };
@@ -0,0 +1,69 @@
import { TransformerTwoslashOptions } from '@shikijs/twoslash/core';
import { TwoslashReturn } from 'twoslash';
import { VueSpecificOptions } from 'twoslash-vue';
import { RendererRichOptions, TwoslashRenderer } from '@shikijs/twoslash';
interface TwoslashFloatingVueOptions {
classCopyIgnore?: string;
classFloatingPanel?: string;
classCode?: string;
classMarkdown?: string;
floatingVueTheme?: string;
floatingVueThemeQuery?: string;
floatingVueThemeCompletion?: string;
}
interface TwoslashFloatingVueRendererOptions extends RendererRichOptions {
/**
* Class and themes for floating-vue specific nodes
*/
floatingVue?: TwoslashFloatingVueOptions;
}
declare function rendererFloatingVue(options?: TwoslashFloatingVueRendererOptions): TwoslashRenderer;
interface TransformerTwoslashVueOptions extends TransformerTwoslashOptions {
twoslashOptions?: TransformerTwoslashOptions['twoslashOptions'] & VueSpecificOptions;
}
interface VitePressPluginTwoslashOptions extends TransformerTwoslashVueOptions, TwoslashFloatingVueRendererOptions {
/**
* Requires adding `twoslash` to the code block explicitly to run twoslash
* @default true
*/
explicitTrigger?: TransformerTwoslashOptions['explicitTrigger'];
/**
* The options for caching resolved types
*
* @example
* ```ts
* import { transformerTwoslash } from '@shikijs/vitepress-twoslash'
* import { createFileSystemTypesCache } from '@shikijs/vitepress-twoslash/cache-fs'
*
* transformerTwoslash({
* typesCache: createFileSystemTypesCache({
* dir: './my-cache-dir'
* })
* })
* ```
*/
typesCache?: TwoslashTypesCache;
}
interface TwoslashTypesCache {
/**
* Read cached result
*
* @param code Source code
*/
read: (code: string) => TwoslashReturn | null;
/**
* Save result to cache
*
* @param code Source code
* @param data Twoslash data
*/
write: (code: string, data: TwoslashReturn) => void;
/**
* On initialization
*/
init?: () => void;
}
export { type TwoslashFloatingVueOptions as T, type VitePressPluginTwoslashOptions as V, type TwoslashFloatingVueRendererOptions as a, type TwoslashTypesCache as b, rendererFloatingVue as r };
@@ -0,0 +1,69 @@
import { TransformerTwoslashOptions } from '@shikijs/twoslash/core';
import { TwoslashReturn } from 'twoslash';
import { VueSpecificOptions } from 'twoslash-vue';
import { RendererRichOptions, TwoslashRenderer } from '@shikijs/twoslash';
interface TwoslashFloatingVueOptions {
classCopyIgnore?: string;
classFloatingPanel?: string;
classCode?: string;
classMarkdown?: string;
floatingVueTheme?: string;
floatingVueThemeQuery?: string;
floatingVueThemeCompletion?: string;
}
interface TwoslashFloatingVueRendererOptions extends RendererRichOptions {
/**
* Class and themes for floating-vue specific nodes
*/
floatingVue?: TwoslashFloatingVueOptions;
}
declare function rendererFloatingVue(options?: TwoslashFloatingVueRendererOptions): TwoslashRenderer;
interface TransformerTwoslashVueOptions extends TransformerTwoslashOptions {
twoslashOptions?: TransformerTwoslashOptions['twoslashOptions'] & VueSpecificOptions;
}
interface VitePressPluginTwoslashOptions extends TransformerTwoslashVueOptions, TwoslashFloatingVueRendererOptions {
/**
* Requires adding `twoslash` to the code block explicitly to run twoslash
* @default true
*/
explicitTrigger?: TransformerTwoslashOptions['explicitTrigger'];
/**
* The options for caching resolved types
*
* @example
* ```ts
* import { transformerTwoslash } from '@shikijs/vitepress-twoslash'
* import { createFileSystemTypesCache } from '@shikijs/vitepress-twoslash/cache-fs'
*
* transformerTwoslash({
* typesCache: createFileSystemTypesCache({
* dir: './my-cache-dir'
* })
* })
* ```
*/
typesCache?: TwoslashTypesCache;
}
interface TwoslashTypesCache {
/**
* Read cached result
*
* @param code Source code
*/
read: (code: string) => TwoslashReturn | null;
/**
* Save result to cache
*
* @param code Source code
* @param data Twoslash data
*/
write: (code: string, data: TwoslashReturn) => void;
/**
* On initialization
*/
init?: () => void;
}
export { type TwoslashFloatingVueOptions as T, type VitePressPluginTwoslashOptions as V, type TwoslashFloatingVueRendererOptions as a, type TwoslashTypesCache as b, rendererFloatingVue as r };