mirror of
https://github.com/cloudflare/cloudflare-docs.git
synced 2026-01-11 20:06:58 +00:00
[Docs Site] Adopt eslint (#19263)
* [Docs Site] Adopt eslint * Demonstrate a fixable suggestion, add VSCode plugin and package.json script * Fix slice in ModelCatalog * Remove test error in AnchorHeading * recreate package-lock.json * update new .jsx components to .tsx * amend deps, fix react types, organise ec plugins * another attempt at fixing platform-specific deps * fix FieldCatalog filters, remove test block from code.mdx * use opacity instead of brightness for ruleid * fix lockfile * amend ruleid opacity styling * test onetrust * enable prefer const rule, remove onetrust test * add save-dev
This commit is contained in:
parent
8adca6b9c2
commit
a1bf485920
49 changed files with 8153 additions and 4801 deletions
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
|
|
@ -30,6 +30,12 @@ jobs:
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run check
|
- run: npm run check
|
||||||
|
|
||||||
|
- uses: reviewdog/action-eslint@v1
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
reporter: github-pr-review
|
||||||
|
fail_level: "error"
|
||||||
|
|
||||||
- run: npm run format:core:check
|
- run: npm run format:core:check
|
||||||
## TODO: content formatting checks
|
## TODO: content formatting checks
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
|
|
|
||||||
2
.npmrc
Normal file
2
.npmrc
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
save-dev=true
|
||||||
|
save-exact=true
|
||||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
|
|
@ -6,6 +6,7 @@
|
||||||
"unifiedjs.vscode-mdx",
|
"unifiedjs.vscode-mdx",
|
||||||
"bradlc.vscode-tailwindcss",
|
"bradlc.vscode-tailwindcss",
|
||||||
"redhat.vscode-yaml",
|
"redhat.vscode-yaml",
|
||||||
"esbenp.prettier-vscode"
|
"esbenp.prettier-vscode",
|
||||||
|
"dbaeumer.vscode-eslint"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ async function main() {
|
||||||
let numInfiniteRedirects = 0;
|
let numInfiniteRedirects = 0;
|
||||||
let numUrlsWithFragment = 0;
|
let numUrlsWithFragment = 0;
|
||||||
let numDuplicateRedirects = 0;
|
let numDuplicateRedirects = 0;
|
||||||
let redirectSourceUrls: string[] = [];
|
|
||||||
|
const redirectSourceUrls: string[] = [];
|
||||||
|
|
||||||
for (const line of redirects.split("\n")) {
|
for (const line of redirects.split("\n")) {
|
||||||
if (line.startsWith("#") || line.trim() === "") continue;
|
if (line.startsWith("#") || line.trim() === "") continue;
|
||||||
|
|
|
||||||
157
ec.config.mjs
157
ec.config.mjs
|
|
@ -2,162 +2,17 @@
|
||||||
import darkTheme from "solarflare-theme/themes/cloudflare-dark-color-theme.json" with { type: "json" };
|
import darkTheme from "solarflare-theme/themes/cloudflare-dark-color-theme.json" with { type: "json" };
|
||||||
import lightTheme from "solarflare-theme/themes/cloudflare-light-color-theme.json" with { type: "json" };
|
import lightTheme from "solarflare-theme/themes/cloudflare-light-color-theme.json" with { type: "json" };
|
||||||
|
|
||||||
import { definePlugin } from "@expressive-code/core";
|
import pluginWorkersPlayground from "./plugins/expressive-code/workers-playground.js";
|
||||||
import { h } from "@expressive-code/core/hast";
|
import pluginOutputFrame from "./plugins/expressive-code/output-frame.js";
|
||||||
|
import pluginDefaultTitles from "./plugins/expressive-code/default-titles.js";
|
||||||
|
|
||||||
import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-sections";
|
import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-sections";
|
||||||
|
|
||||||
import lzstring from "lz-string";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} code
|
|
||||||
*/
|
|
||||||
export function serialiseWorker(code) {
|
|
||||||
const formData = new FormData();
|
|
||||||
|
|
||||||
const metadata = {
|
|
||||||
main_module: "index.js",
|
|
||||||
};
|
|
||||||
|
|
||||||
formData.set(
|
|
||||||
"index.js",
|
|
||||||
new Blob([code], {
|
|
||||||
type: "application/javascript+module",
|
|
||||||
}),
|
|
||||||
"index.js",
|
|
||||||
);
|
|
||||||
|
|
||||||
formData.set(
|
|
||||||
"metadata",
|
|
||||||
new Blob([JSON.stringify(metadata)], { type: "application/json" }),
|
|
||||||
);
|
|
||||||
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {FormData} worker
|
|
||||||
*/
|
|
||||||
export async function compressWorker(worker) {
|
|
||||||
const serialisedWorker = new Response(worker);
|
|
||||||
return lzstring.compressToEncodedURIComponent(
|
|
||||||
`${serialisedWorker.headers.get(
|
|
||||||
"content-type",
|
|
||||||
)}:${await serialisedWorker.text()}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function workersPlaygroundButton() {
|
|
||||||
return definePlugin({
|
|
||||||
name: "Adds 'Run Worker' button to JS codeblocks",
|
|
||||||
baseStyles: `
|
|
||||||
.run {
|
|
||||||
display: flex;
|
|
||||||
gap: 0.25rem;
|
|
||||||
flex-direction: row;
|
|
||||||
position: absolute;
|
|
||||||
inset-block-start: calc(var(--ec-brdWd) + var(--button-spacing));
|
|
||||||
inset-inline-end: calc(var(--ec-brdWd) + var(--ec-uiPadInl) * 3);
|
|
||||||
direction: ltr;
|
|
||||||
unicode-bidi: isolate;
|
|
||||||
|
|
||||||
text-decoration-color: var(--sl-color-accent);
|
|
||||||
span {
|
|
||||||
color: var(--sl-color-white);
|
|
||||||
font-family: var(--sl-font-system);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
hooks: {
|
|
||||||
postprocessRenderedBlock: async (context) => {
|
|
||||||
if (!context.codeBlock.meta.includes("playground")) return;
|
|
||||||
|
|
||||||
const serialised = await compressWorker(
|
|
||||||
serialiseWorker(context.codeBlock.code),
|
|
||||||
);
|
|
||||||
|
|
||||||
const url = `https://workers.cloudflare.com/playground#${serialised}`;
|
|
||||||
|
|
||||||
const runButton = h("a.run", { href: url, target: "__blank" }, [
|
|
||||||
h("span", "Run Worker in Playground"),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const ast = context.renderData.blockAst;
|
|
||||||
ast.children.push(runButton);
|
|
||||||
|
|
||||||
context.renderData.blockAst = ast;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function outputCodeblocks() {
|
|
||||||
return definePlugin({
|
|
||||||
name: "Adds the '.code-output' class if 'output' is passed on the opening codefence.",
|
|
||||||
hooks: {
|
|
||||||
preprocessMetadata: async (context) => {
|
|
||||||
if (!context.codeBlock.meta.includes("output")) return;
|
|
||||||
context.codeBlock.props.frame = "none";
|
|
||||||
},
|
|
||||||
postprocessRenderedBlock: async (context) => {
|
|
||||||
if (!context.codeBlock.meta.includes("output")) return;
|
|
||||||
context.renderData.blockAst.properties.className ??= [];
|
|
||||||
if (Array.isArray(context.renderData.blockAst.properties.className)) {
|
|
||||||
context.renderData.blockAst.properties.className.push("code-output");
|
|
||||||
}
|
|
||||||
context.addStyles(`
|
|
||||||
div.expressive-code:has(figure.code-output) {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output .copy {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output > pre {
|
|
||||||
border-top-width: 0 !important;
|
|
||||||
background: var(--sl-color-gray-6) !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output > pre > code {
|
|
||||||
user-select: none;
|
|
||||||
transition: opacity 0.5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.code-output > pre > code:hover {
|
|
||||||
cursor: default;
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
`);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function defaultLanguageTitles() {
|
|
||||||
return definePlugin({
|
|
||||||
name: "Adds language-specific default titles.",
|
|
||||||
hooks: {
|
|
||||||
preprocessLanguage: async (context) => {
|
|
||||||
switch (context.codeBlock.language) {
|
|
||||||
case "powershell": {
|
|
||||||
context.codeBlock.props.title ??= "PowerShell";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
plugins: [
|
plugins: [
|
||||||
workersPlaygroundButton(),
|
pluginWorkersPlayground(),
|
||||||
outputCodeblocks(),
|
pluginOutputFrame(),
|
||||||
defaultLanguageTitles(),
|
pluginDefaultTitles(),
|
||||||
pluginCollapsibleSections(),
|
pluginCollapsibleSections(),
|
||||||
],
|
],
|
||||||
themes: [darkTheme, lightTheme],
|
themes: [darkTheme, lightTheme],
|
||||||
|
|
|
||||||
42
eslint.config.js
Normal file
42
eslint.config.js
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
import pluginJavaScript from "@eslint/js";
|
||||||
|
import pluginTypeScript from "typescript-eslint";
|
||||||
|
import pluginReact from "eslint-plugin-react";
|
||||||
|
import pluginAstro from "eslint-plugin-astro";
|
||||||
|
import pluginReactA11y from "eslint-plugin-jsx-a11y";
|
||||||
|
|
||||||
|
import globals from "globals";
|
||||||
|
|
||||||
|
/** @type {import('eslint').Linter.Config[]} */
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
pluginJavaScript.configs.recommended,
|
||||||
|
...pluginTypeScript.configs.recommended,
|
||||||
|
...pluginAstro.configs.recommended,
|
||||||
|
...pluginAstro.configs["jsx-a11y-recommended"],
|
||||||
|
{
|
||||||
|
files: ["**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}"],
|
||||||
|
...pluginReact.configs.flat.recommended,
|
||||||
|
...pluginReactA11y.flatConfigs.recommended,
|
||||||
|
...pluginReact.configs.flat["jsx-runtime"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ignores: [".astro/", ".wrangler/", "dist/", ".github/"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
"no-var": "error",
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
"@typescript-eslint/triple-slash-reference": "off",
|
||||||
|
"@typescript-eslint/no-unused-vars": [
|
||||||
|
"error",
|
||||||
|
{ ignoreRestSiblings: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
12067
package-lock.json
generated
12067
package-lock.json
generated
File diff suppressed because it is too large
Load diff
150
package.json
150
package.json
|
|
@ -17,88 +17,92 @@
|
||||||
"format:core:check": "npm run format:core -- --check",
|
"format:core:check": "npm run format:core -- --check",
|
||||||
"format:content": "npx prettier --write \"**/*.{md,mdx,astro}\"",
|
"format:content": "npx prettier --write \"**/*.{md,mdx,astro}\"",
|
||||||
"format:data": "npx prettier --write \"**/*.{json,yaml,yml}\"",
|
"format:data": "npx prettier --write \"**/*.{json,yaml,yml}\"",
|
||||||
"postinstall": "npx patch-package && npm run sync",
|
"postinstall": "npm run sync",
|
||||||
"preview": "npx astro preview",
|
"preview": "npx astro preview",
|
||||||
"script:optimize-svgs": "npx tsx scripts/optimize-svgs.ts",
|
"script:optimize-svgs": "npx tsx scripts/optimize-svgs.ts",
|
||||||
"start": "npx astro dev",
|
"start": "npx astro dev",
|
||||||
"sync": "npx astro sync",
|
"sync": "npx astro sync",
|
||||||
"test": "npx vitest"
|
"test": "npx vitest",
|
||||||
|
"lint": "npx eslint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@astro-community/astro-embed-youtube": "^0.5.6",
|
"@astrojs/check": "0.9.4",
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/react": "4.1.5",
|
||||||
"@astrojs/react": "^3.6.3",
|
"@astrojs/rss": "4.0.11",
|
||||||
"@astrojs/rss": "^4.0.11",
|
"@astrojs/sitemap": "3.2.1",
|
||||||
"@astrojs/sitemap": "^3.2.1",
|
"@astrojs/starlight": "0.29.3",
|
||||||
"@astrojs/starlight": "^0.29.3",
|
"@astrojs/starlight-docsearch": "0.3.0",
|
||||||
"@astrojs/starlight-docsearch": "^0.3.0",
|
"@astrojs/starlight-tailwind": "2.0.3",
|
||||||
"@astrojs/starlight-tailwind": "^2.0.3",
|
"@astrojs/tailwind": "5.1.4",
|
||||||
"@astrojs/tailwind": "^5.1.4",
|
"@cloudflare/puppeteer": "0.0.14",
|
||||||
"@cloudflare/puppeteer": "^0.0.14",
|
"@cloudflare/vitest-pool-workers": "0.6.0",
|
||||||
"@cloudflare/vitest-pool-workers": "^0.6.0",
|
"@cloudflare/workers-types": "4.20250109.0",
|
||||||
"@cloudflare/workers-types": "^4.20241218.0",
|
"@codingheads/sticky-header": "1.0.2",
|
||||||
"@codingheads/sticky-header": "^1.0.2",
|
"@expressive-code/plugin-collapsible-sections": "0.38.3",
|
||||||
"@expressive-code/plugin-collapsible-sections": "^0.40.0",
|
"@iarna/toml": "2.2.5",
|
||||||
"@iarna/toml": "^2.2.5",
|
"@iconify-json/material-symbols": "1.2.12",
|
||||||
"@iconify-json/material-symbols": "^1.2.12",
|
"@stoplight/json-schema-tree": "4.0.0",
|
||||||
"@stoplight/json-schema-tree": "^4.0.0",
|
"@types/hast": "3.0.4",
|
||||||
"@types/hast": "^3.0.4",
|
"@types/he": "1.2.3",
|
||||||
"@types/he": "^1.2.3",
|
"@types/node": "22.10.7",
|
||||||
"@types/node": "^22.10.6",
|
"@types/react": "19.0.7",
|
||||||
"@types/react": "^18.3.12",
|
"@types/react-dom": "19.0.3",
|
||||||
"@types/react-dom": "^18.3.1",
|
"@typescript-eslint/parser": "8.20.0",
|
||||||
"algoliasearch": "^5.19.0",
|
"algoliasearch": "5.19.0",
|
||||||
"astro": "^4.16.18",
|
"astro": "4.16.18",
|
||||||
"astro-breadcrumbs": "^3.3.1",
|
"astro-breadcrumbs": "3.3.1",
|
||||||
"astro-icon": "^1.1.2",
|
"astro-icon": "1.1.5",
|
||||||
"astro-live-code": "^0.0.5",
|
"astro-live-code": "0.0.5",
|
||||||
"date-fns": "^4.1.0",
|
"date-fns": "4.1.0",
|
||||||
"dedent": "^1.5.3",
|
"dedent": "1.5.3",
|
||||||
"detype": "1.0.12",
|
|
||||||
"dompurify": "3.2.3",
|
"dompurify": "3.2.3",
|
||||||
"dot-prop": "^9.0.0",
|
"dot-prop": "9.0.0",
|
||||||
"fast-glob": "^3.3.3",
|
"eslint": "9.18.0",
|
||||||
"github-slugger": "^2.0.0",
|
"eslint-plugin-astro": "1.3.1",
|
||||||
"hastscript": "^9.0.0",
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
||||||
"he": "^1.2.0",
|
"eslint-plugin-react": "7.37.4",
|
||||||
"instantsearch.css": "^8.5.1",
|
"fast-glob": "3.3.3",
|
||||||
"instantsearch.js": "^4.75.7",
|
"github-slugger": "2.0.0",
|
||||||
"jsonc-parser": "^3.3.1",
|
"globals": "15.14.0",
|
||||||
"lz-string": "^1.5.0",
|
"hastscript": "9.0.0",
|
||||||
"marked": "^15.0.6",
|
"he": "1.2.0",
|
||||||
"mdast-util-mdx-expression": "^2.0.1",
|
"instantsearch.css": "8.5.1",
|
||||||
"mermaid": "^11.4.1",
|
"instantsearch.js": "4.77.0",
|
||||||
"node-html-parser": "^6.1.13",
|
"jsonc-parser": "3.3.1",
|
||||||
"patch-package": "^8.0.0",
|
"lz-string": "1.5.0",
|
||||||
"playwright": "^1.49.1",
|
"marked": "15.0.6",
|
||||||
"prettier": "^3.4.2",
|
"mdast-util-mdx-expression": "2.0.1",
|
||||||
"prettier-plugin-astro": "^0.14.1",
|
"mermaid": "11.4.1",
|
||||||
|
"node-html-parser": "7.0.1",
|
||||||
|
"playwright": "1.49.1",
|
||||||
|
"prettier": "3.4.2",
|
||||||
|
"prettier-plugin-astro": "0.14.1",
|
||||||
|
"prettier-plugin-tailwindcss": "0.6.9",
|
||||||
"pretty-bytes": "6.1.1",
|
"pretty-bytes": "6.1.1",
|
||||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
"puppeteer": "24.1.0",
|
||||||
"puppeteer": "^24.0.0",
|
"react": "19.0.0",
|
||||||
"react": "^18.3.1",
|
"react-dom": "19.0.0",
|
||||||
"react-dom": "^18.3.1",
|
"react-markdown": "9.0.3",
|
||||||
"react-markdown": "^9.0.3",
|
"redirects-in-workers": "0.0.5",
|
||||||
"react-textarea-autosize": "^8.5.7",
|
"rehype-autolink-headings": "7.1.0",
|
||||||
"redirects-in-workers": "^0.0.5",
|
"rehype-external-links": "3.0.0",
|
||||||
"rehype-autolink-headings": "^7.1.0",
|
"rehype-mermaid": "3.0.0",
|
||||||
"rehype-external-links": "^3.0.0",
|
"rehype-title-figure": "0.1.2",
|
||||||
"rehype-mermaid": "^3.0.0",
|
"sharp": "0.33.5",
|
||||||
"rehype-title-figure": "^0.1.2",
|
"solarflare-theme": "0.0.2",
|
||||||
"sharp": "^0.33.5",
|
"starlight-image-zoom": "0.9.0",
|
||||||
"solarflare-theme": "^0.0.2",
|
"starlight-links-validator": "0.14.1",
|
||||||
"starlight-image-zoom": "^0.9.0",
|
"starlight-package-managers": "0.9.0",
|
||||||
"starlight-links-validator": "^0.14.1",
|
"svgo": "3.3.2",
|
||||||
"starlight-package-managers": "^0.9.0",
|
"tailwindcss": "3.4.17",
|
||||||
"svgo": "^3.3.2",
|
"tippy.js": "6.3.7",
|
||||||
"tailwindcss": "^3.4.17",
|
"ts-blank-space": "0.5.0",
|
||||||
"tippy.js": "^6.3.7",
|
"tsx": "4.19.2",
|
||||||
"tsx": "^4.19.2",
|
"typescript": "5.7.3",
|
||||||
"typescript": "^5.7.3",
|
"typescript-eslint": "8.20.0",
|
||||||
"unist-util-visit": "^5.0.0",
|
"unist-util-visit": "5.0.0",
|
||||||
"vitest": "2.1.8",
|
"vitest": "2.1.8",
|
||||||
"wrangler": "^3.101.0",
|
"wrangler": "3.101.0"
|
||||||
"yaml": "^2.7.0"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
|
|
|
||||||
20
plugins/expressive-code/default-titles.js
Normal file
20
plugins/expressive-code/default-titles.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { definePlugin } from "@expressive-code/core";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return definePlugin({
|
||||||
|
name: "Adds language-specific default titles.",
|
||||||
|
hooks: {
|
||||||
|
preprocessLanguage: async (context) => {
|
||||||
|
switch (context.codeBlock.language) {
|
||||||
|
case "powershell": {
|
||||||
|
context.codeBlock.props.title ??= "PowerShell";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
45
plugins/expressive-code/output-frame.js
Normal file
45
plugins/expressive-code/output-frame.js
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { definePlugin } from "@expressive-code/core";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return definePlugin({
|
||||||
|
name: "Adds the '.code-output' class if 'output' is passed on the opening codefence.",
|
||||||
|
hooks: {
|
||||||
|
preprocessMetadata: async (context) => {
|
||||||
|
if (!context.codeBlock.meta.includes("output")) return;
|
||||||
|
|
||||||
|
context.codeBlock.props.frame = "none";
|
||||||
|
},
|
||||||
|
postprocessRenderedBlock: async (context) => {
|
||||||
|
if (!context.codeBlock.meta.includes("output")) return;
|
||||||
|
context.renderData.blockAst.properties.className ??= [];
|
||||||
|
if (Array.isArray(context.renderData.blockAst.properties.className)) {
|
||||||
|
context.renderData.blockAst.properties.className.push("code-output");
|
||||||
|
}
|
||||||
|
context.addStyles(`
|
||||||
|
div.expressive-code:has(figure.code-output) {
|
||||||
|
margin-top: 0 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-output .copy {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-output > pre {
|
||||||
|
border-top-width: 0 !important;
|
||||||
|
background: var(--sl-color-gray-6) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-output > pre > code {
|
||||||
|
user-select: none;
|
||||||
|
transition: opacity 0.5s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-output > pre > code:hover {
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
80
plugins/expressive-code/workers-playground.js
Normal file
80
plugins/expressive-code/workers-playground.js
Normal file
|
|
@ -0,0 +1,80 @@
|
||||||
|
import { definePlugin } from "@expressive-code/core";
|
||||||
|
import { h } from "@expressive-code/core/hast";
|
||||||
|
|
||||||
|
import lzstring from "lz-string";
|
||||||
|
|
||||||
|
export function serialiseWorker(code) {
|
||||||
|
const formData = new FormData();
|
||||||
|
|
||||||
|
const metadata = {
|
||||||
|
main_module: "index.js",
|
||||||
|
};
|
||||||
|
|
||||||
|
formData.set(
|
||||||
|
"index.js",
|
||||||
|
new Blob([code], {
|
||||||
|
type: "application/javascript+module",
|
||||||
|
}),
|
||||||
|
"index.js",
|
||||||
|
);
|
||||||
|
|
||||||
|
formData.set(
|
||||||
|
"metadata",
|
||||||
|
new Blob([JSON.stringify(metadata)], { type: "application/json" }),
|
||||||
|
);
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function compressWorker(worker) {
|
||||||
|
const serialisedWorker = new Response(worker);
|
||||||
|
return lzstring.compressToEncodedURIComponent(
|
||||||
|
`${serialisedWorker.headers.get(
|
||||||
|
"content-type",
|
||||||
|
)}:${await serialisedWorker.text()}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
return definePlugin({
|
||||||
|
name: "Adds 'Run Worker' button to JS codeblocks",
|
||||||
|
baseStyles: `
|
||||||
|
.run {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.25rem;
|
||||||
|
flex-direction: row;
|
||||||
|
position: absolute;
|
||||||
|
inset-block-start: calc(var(--ec-brdWd) + var(--button-spacing));
|
||||||
|
inset-inline-end: calc(var(--ec-brdWd) + var(--ec-uiPadInl) * 3);
|
||||||
|
direction: ltr;
|
||||||
|
unicode-bidi: isolate;
|
||||||
|
|
||||||
|
text-decoration-color: var(--sl-color-accent);
|
||||||
|
span {
|
||||||
|
color: var(--sl-color-white);
|
||||||
|
font-family: var(--sl-font-system);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
hooks: {
|
||||||
|
postprocessRenderedBlock: async (context) => {
|
||||||
|
if (!context.codeBlock.meta.includes("playground")) return;
|
||||||
|
|
||||||
|
const serialised = await compressWorker(
|
||||||
|
serialiseWorker(context.codeBlock.code),
|
||||||
|
);
|
||||||
|
|
||||||
|
const url = `https://workers.cloudflare.com/playground#${serialised}`;
|
||||||
|
|
||||||
|
const runButton = h("a.run", { href: url, target: "__blank" }, [
|
||||||
|
h("span", "Run Worker in Playground"),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const ast = context.renderData.blockAst;
|
||||||
|
ast.children.push(runButton);
|
||||||
|
|
||||||
|
context.renderData.blockAst = ast;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -60,7 +60,7 @@ async function run() {
|
||||||
const end = performance.now();
|
const end = performance.now();
|
||||||
const duration = end - start;
|
const duration = end - start;
|
||||||
const seconds = Math.floor(duration / 1000);
|
const seconds = Math.floor(duration / 1000);
|
||||||
console.log(`Optimized ${files.length} SVG files in ${seconds}s`);
|
console.log(`Optimized ${processed} SVG files in ${seconds}s`);
|
||||||
console.log(
|
console.log(
|
||||||
`Original size: ~${formatBytes(originalSize)}, optimized size: ~${formatBytes(optimizedSize)}. Saved ~${formatBytes(originalSize - optimizedSize)}`,
|
`Original size: ~${formatBytes(originalSize)}, optimized size: ~${formatBytes(optimizedSize)}. Saved ~${formatBytes(originalSize - optimizedSize)}`,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,23 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import FieldBadges from "./fields/FieldBadges";
|
import FieldBadges from "./fields/FieldBadges";
|
||||||
import Markdown from "react-markdown";
|
import Markdown from "react-markdown";
|
||||||
|
import type { CollectionEntry } from "astro:content";
|
||||||
|
|
||||||
const FieldCatalog = ({ fields }) => {
|
type Fields = CollectionEntry<"fields">["data"]["entries"];
|
||||||
const [filters, setFilters] = useState({
|
|
||||||
|
type Filters = {
|
||||||
|
search: string;
|
||||||
|
categories: string[];
|
||||||
|
keywords: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const FieldCatalog = ({ fields }: { fields: Fields }) => {
|
||||||
|
const [filters, setFilters] = useState<Filters>({
|
||||||
search: "",
|
search: "",
|
||||||
categories: [],
|
categories: [],
|
||||||
keywords: [],
|
keywords: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapped = fields.sort((f1, f2) => {
|
const mapped = fields.sort((f1, f2) => {
|
||||||
return f1.name < f2.name ? -1 : 1;
|
return f1.name < f2.name ? -1 : 1;
|
||||||
});
|
});
|
||||||
|
|
@ -31,7 +41,7 @@ const FieldCatalog = ({ fields }) => {
|
||||||
|
|
||||||
if (filters.search) {
|
if (filters.search) {
|
||||||
// search keywords
|
// search keywords
|
||||||
let keywordFound = field.keywords?.some(
|
const keywordFound = field.keywords?.some(
|
||||||
(kw) => kw.indexOf(filters.search) >= 0,
|
(kw) => kw.indexOf(filters.search) >= 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -70,16 +80,18 @@ const FieldCatalog = ({ fields }) => {
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
value={category}
|
value={category}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (e.target.checked) {
|
const target = e.target as HTMLInputElement;
|
||||||
|
|
||||||
|
if (target.checked) {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
categories: [...filters.categories, e.target.value],
|
categories: [...filters.categories, target.value],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
categories: filters.categories.filter(
|
categories: filters.categories.filter(
|
||||||
(f) => f !== e.target.value,
|
(f) => f !== target.value,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +62,7 @@ if (lines) {
|
||||||
}
|
}
|
||||||
|
|
||||||
contentLines = contentLines.filter(
|
contentLines = contentLines.filter(
|
||||||
(line) => !/<[\/]?docs-tag name=".*">/.test(line),
|
(line) => !/<[/]?docs-tag name=".*">/.test(line),
|
||||||
);
|
);
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
/* eslint-disable astro/jsx-a11y/no-noninteractive-tabindex */
|
||||||
import { z } from "astro:schema";
|
import { z } from "astro:schema";
|
||||||
import { getGlossaryEntry } from "~/util/glossary";
|
import { getGlossaryEntry } from "~/util/glossary";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
|
|
@ -29,7 +30,7 @@ definition = definition.split(/\r?\n/)[0];
|
||||||
id={tooltip.term}
|
id={tooltip.term}
|
||||||
data-tooltip
|
data-tooltip
|
||||||
data-content={marked.parse(definition)}
|
data-content={marked.parse(definition)}
|
||||||
class="border-b-2 border-dashed border-accent-600"
|
class="border-b-2 border-dashed border-accent"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>{
|
>{
|
||||||
link ? (
|
link ? (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
import type { Props } from "@astrojs/starlight/props";
|
import type { Props } from "@astrojs/starlight/props";
|
||||||
|
import type { ImageMetadata } from "astro";
|
||||||
|
|
||||||
const { data } = Astro.props.entry;
|
const { data } = Astro.props.entry;
|
||||||
const { title = data.title, tagline, image } = data.hero || {};
|
const { title = data.title, tagline, image } = data.hero || {};
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,23 @@ import { useState } from "react";
|
||||||
import ModelInfo from "./models/ModelInfo";
|
import ModelInfo from "./models/ModelInfo";
|
||||||
import ModelBadges from "./models/ModelBadges";
|
import ModelBadges from "./models/ModelBadges";
|
||||||
import { authorData } from "./models/data";
|
import { authorData } from "./models/data";
|
||||||
|
import type { WorkersAIModelsSchema } from "~/schemas";
|
||||||
|
|
||||||
const ModelCatalog = ({ models }) => {
|
type Filters = {
|
||||||
const [filters, setFilters] = useState({
|
search: string;
|
||||||
|
authors: string[];
|
||||||
|
tasks: string[];
|
||||||
|
capabilities: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
|
||||||
|
const [filters, setFilters] = useState<Filters>({
|
||||||
search: "",
|
search: "",
|
||||||
authors: [],
|
authors: [],
|
||||||
tasks: [],
|
tasks: [],
|
||||||
capabilities: [],
|
capabilities: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapped = models.map((model) => ({
|
const mapped = models.map((model) => ({
|
||||||
model: {
|
model: {
|
||||||
...model,
|
...model,
|
||||||
|
|
@ -22,6 +31,8 @@ const ModelCatalog = ({ models }) => {
|
||||||
if (property_id === "function_calling" && value === "true") {
|
if (property_id === "function_calling" && value === "true") {
|
||||||
return "Function calling";
|
return "Function calling";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
})
|
})
|
||||||
.filter((p) => Boolean(p)),
|
.filter((p) => Boolean(p)),
|
||||||
},
|
},
|
||||||
|
|
@ -101,15 +112,17 @@ const ModelCatalog = ({ models }) => {
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
value={task}
|
value={task}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (e.target.checked) {
|
const target = e.target as HTMLInputElement;
|
||||||
|
|
||||||
|
if (target.checked) {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
tasks: [...filters.tasks, e.target.value],
|
tasks: [...filters.tasks, target.value],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
tasks: filters.tasks.filter((f) => f !== e.target.value),
|
tasks: filters.tasks.filter((f) => f !== target.value),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|
@ -131,16 +144,18 @@ const ModelCatalog = ({ models }) => {
|
||||||
value={capability}
|
value={capability}
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (e.target.checked) {
|
const target = e.target as HTMLInputElement;
|
||||||
|
|
||||||
|
if (target.checked) {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
capabilities: [...filters.capabilities, e.target.value],
|
capabilities: [...filters.capabilities, target.value],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
capabilities: filters.capabilities.filter(
|
capabilities: filters.capabilities.filter(
|
||||||
(f) => f !== e.target.value,
|
(f) => f !== target.value,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -163,16 +178,18 @@ const ModelCatalog = ({ models }) => {
|
||||||
className="mr-2"
|
className="mr-2"
|
||||||
value={author}
|
value={author}
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (e.target.checked) {
|
const target = e.target as HTMLInputElement;
|
||||||
|
|
||||||
|
if (target.checked) {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
authors: [...filters.authors, e.target.value],
|
authors: [...filters.authors, target.value],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
setFilters({
|
setFilters({
|
||||||
...filters,
|
...filters,
|
||||||
authors: filters.authors.filter(
|
authors: filters.authors.filter(
|
||||||
(f) => f !== e.target.value,
|
(f) => f !== target.value,
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -199,9 +216,8 @@ const ModelCatalog = ({ models }) => {
|
||||||
property_id === "beta" && value === "true",
|
property_id === "beta" && value === "true",
|
||||||
);
|
);
|
||||||
|
|
||||||
const author =
|
const author = model.model.name.split("/")[1];
|
||||||
authorData[model.model.name.split("/")[1]]?.name ??
|
const authorInfo = authorData[author];
|
||||||
model.model.name.split("/")[1];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
|
|
@ -210,14 +226,15 @@ const ModelCatalog = ({ models }) => {
|
||||||
href={`/workers-ai/models/${model.model_display_name}`}
|
href={`/workers-ai/models/${model.model_display_name}`}
|
||||||
>
|
>
|
||||||
<div className="-mb-1 flex items-center">
|
<div className="-mb-1 flex items-center">
|
||||||
{authorData[model.model.name.split("/")[1]]?.logo ? (
|
{authorInfo?.logo ? (
|
||||||
<img
|
<img
|
||||||
className="mr-2 block w-6"
|
className="mr-2 block w-6"
|
||||||
src={authorData[model.model.name.split("/")[1]]?.logo}
|
src={authorInfo.logo}
|
||||||
|
alt={`${authorInfo.name} logo`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="mr-2 flex h-6 w-6 items-center justify-center rounded-md bg-gray-100 text-sm font-black uppercase text-gray-400">
|
<div className="mr-2 flex h-6 w-6 items-center justify-center rounded-md bg-gray-100 text-sm font-black uppercase text-gray-400">
|
||||||
{author.substr(0, 1)}
|
{author.slice(0, 1)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap text-lg font-semibold">
|
<span className="overflow-hidden text-ellipsis whitespace-nowrap text-lg font-semibold">
|
||||||
|
|
@ -1,39 +1,24 @@
|
||||||
{
|
---
|
||||||
import.meta.env.PROD ? (
|
const isProduction = import.meta.env.PROD;
|
||||||
<>
|
|
||||||
<script
|
const uuid = isProduction
|
||||||
src="https://ot.www.cloudflare.com/public/vendor/onetrust/scripttemplates/otSDKStub.js"
|
? "b1e05d49-f072-4bae-9116-bdb78af15448"
|
||||||
type="text/javascript"
|
: "b1e05d49-f072-4bae-9116-bdb78af15448-test";
|
||||||
charset="UTF-8"
|
---
|
||||||
data-domain-script="b1e05d49-f072-4bae-9116-bdb78af15448"
|
|
||||||
is:inline
|
<script
|
||||||
/>
|
src="https://ot.www.cloudflare.com/public/vendor/onetrust/scripttemplates/otSDKStub.js"
|
||||||
<script type="text/javascript" is:inline>
|
type="text/javascript"
|
||||||
function OptanonWrapper() {}
|
charset="UTF-8"
|
||||||
</script>
|
data-domain-script={uuid}
|
||||||
</>
|
is:inline></script>
|
||||||
) : (
|
<script type="text/javascript" is:inline>
|
||||||
<>
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
<script
|
function OptanonWrapper() {}
|
||||||
src="https://ot.www.cloudflare.com/public/vendor/onetrust/scripttemplates/otSDKStub.js"
|
</script>
|
||||||
type="text/javascript"
|
<!-- OneTrust Cookies Settings button start -->
|
||||||
charset="UTF-8"
|
<button id="ot-sdk-btn" class="ot-sdk-show-settings">Cookie Settings</button>
|
||||||
data-domain-script="b1e05d49-f072-4bae-9116-bdb78af15448-test"
|
<!-- OneTrust Cookies Settings button end -->
|
||||||
is:inline
|
|
||||||
/>
|
|
||||||
<script type="text/javascript" is:inline>
|
|
||||||
function OptanonWrapper() {}
|
|
||||||
</script>
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
<span class="DocsFooter--content-additional-wrapper">
|
|
||||||
<!-- OneTrust Cookies Settings button start -->
|
|
||||||
<a role="button" id="ot-sdk-btn" class="ot-sdk-show-settings"
|
|
||||||
>Cookie Settings</a
|
|
||||||
>
|
|
||||||
<!-- OneTrust Cookies Settings button end -->
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#ot-sdk-btn.ot-sdk-show-settings {
|
#ot-sdk-btn.ot-sdk-show-settings {
|
||||||
|
|
@ -43,6 +28,7 @@
|
||||||
line-height: inherit !important;
|
line-height: inherit !important;
|
||||||
padding: inherit !important;
|
padding: inherit !important;
|
||||||
font-family: var(--sl-font-family) !important;
|
font-family: var(--sl-font-family) !important;
|
||||||
|
background-color: inherit !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ot-sdk-btn.ot-sdk-show-settings:hover {
|
#ot-sdk-btn.ot-sdk-show-settings:hover {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { getEntry } from "astro:content";
|
||||||
|
|
||||||
const entry = await getEntry("pages-framework-presets", "index");
|
const entry = await getEntry("pages-framework-presets", "index");
|
||||||
const presets = entry.data.build_configs;
|
const presets = entry.data.build_configs;
|
||||||
const entries = Object.entries(presets);
|
const entries = Object.values(presets);
|
||||||
---
|
---
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
|
|
@ -14,7 +14,7 @@ const entries = Object.entries(presets);
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
entries.map(([_, value]) => (
|
entries.map((value) => (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{value.display_name}</td>
|
<td>{value.display_name}</td>
|
||||||
<td>
|
<td>
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,14 @@ const props = z
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-expect-error plans are not typed
|
||||||
const { id, type } = props.parse(Astro.props);
|
const { id, type } = props.parse(Astro.props);
|
||||||
|
|
||||||
let availability;
|
let availability;
|
||||||
if (type) {
|
if (type) {
|
||||||
// @ts-ignore
|
// @ts-expect-error plans are not typed
|
||||||
availability = mappings[type];
|
availability = mappings[type];
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
|
||||||
availability = await indexPlans(id);
|
availability = await indexPlans(id);
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -7,11 +7,13 @@ export type ProductData = CollectionEntry<"products"> & {
|
||||||
groups: string[];
|
groups: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type Filters = {
|
||||||
|
search: string;
|
||||||
|
groups: string[];
|
||||||
|
};
|
||||||
|
|
||||||
const ProductCatalog = ({ products }: { products: ProductData[] }) => {
|
const ProductCatalog = ({ products }: { products: ProductData[] }) => {
|
||||||
const [filters, setFilters] = useState<{
|
const [filters, setFilters] = useState<Filters>({
|
||||||
search: string;
|
|
||||||
groups: string[];
|
|
||||||
}>({
|
|
||||||
search: "",
|
search: "",
|
||||||
groups: [],
|
groups: [],
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,9 @@ const props = z.object({
|
||||||
id: zodEnumFromObjKeys(mappings),
|
id: zodEnumFromObjKeys(mappings),
|
||||||
});
|
});
|
||||||
|
|
||||||
// @ts-ignore
|
|
||||||
const { id } = props.parse(Astro.props);
|
const { id } = props.parse(Astro.props);
|
||||||
|
|
||||||
let stat = mappings[id];
|
const stat = mappings[id];
|
||||||
---
|
---
|
||||||
|
|
||||||
{stat}
|
{stat}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ const { header, href, product } = props.parse(Astro.props);
|
||||||
<strong>
|
<strong>
|
||||||
<a
|
<a
|
||||||
href={href}
|
href={href}
|
||||||
class="!text-black dark:!text-white decoration-[color:var(--orange-accent-200)]"
|
class="!text-black decoration-[color:var(--orange-accent-200)]"
|
||||||
>{header}</a
|
>{header}</a
|
||||||
>
|
>
|
||||||
</strong>
|
</strong>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
---
|
---
|
||||||
import { z } from "astro:schema";
|
import { z } from "astro:schema";
|
||||||
import { Icon } from "@astrojs/starlight/components";
|
|
||||||
|
|
||||||
type Props = z.infer<typeof props>;
|
type Props = z.infer<typeof props>;
|
||||||
|
|
||||||
|
|
@ -13,11 +12,42 @@ const props = z
|
||||||
const { id } = props.parse(Astro.props);
|
const { id } = props.parse(Astro.props);
|
||||||
---
|
---
|
||||||
|
|
||||||
<code
|
<rule-id id={id}>
|
||||||
title="Click to copy the full ID"
|
<button title="Click to copy the full ID" class="px-0">
|
||||||
onclick=`navigator.clipboard.writeText("${id}")`
|
<code class="flex">
|
||||||
class="inline-flex w-fit hover:bg-accent-600/50 hover:cursor-pointer active:bg-accent-600"
|
{`...${id.slice(-8)}`}
|
||||||
>
|
</code>
|
||||||
{`...${id.slice(-8)}`}
|
</button>
|
||||||
<Icon name="document" class="!inline justify-center" />
|
</rule-id>
|
||||||
</code>
|
|
||||||
|
<style>
|
||||||
|
button {
|
||||||
|
transition: opacity 100ms ease;
|
||||||
|
|
||||||
|
opacity: 0.75;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: copy;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { addTooltip } from "~/util/tippy";
|
||||||
|
|
||||||
|
class RuleID extends HTMLElement {
|
||||||
|
handleCopy() {
|
||||||
|
navigator.clipboard.writeText(this.id);
|
||||||
|
}
|
||||||
|
connectedCallback() {
|
||||||
|
const button = this.querySelector<HTMLButtonElement>("button");
|
||||||
|
|
||||||
|
addTooltip(this, "Copied", { trigger: "click", hideAfter: 1000 });
|
||||||
|
|
||||||
|
button?.addEventListener("click", () => this.handleCopy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
customElements.define("rule-id", RuleID);
|
||||||
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
---
|
---
|
||||||
import { z } from "astro:content";
|
import { z } from "astro:content";
|
||||||
import { transform } from "detype";
|
import tsBlankSpace from "ts-blank-space";
|
||||||
|
import { format } from "prettier";
|
||||||
import { parse } from "node-html-parser";
|
import { parse } from "node-html-parser";
|
||||||
import { Code, Tabs, TabItem } from "@astrojs/starlight/components";
|
import { Code, Tabs, TabItem } from "@astrojs/starlight/components";
|
||||||
|
|
||||||
|
|
@ -58,11 +59,7 @@ if (!code) {
|
||||||
|
|
||||||
code = code.replace(/\u007f/g, "\n");
|
code = code.replace(/\u007f/g, "\n");
|
||||||
|
|
||||||
const js = await transform(code, "placeholder.ts", {
|
const js = await format(tsBlankSpace(code), { parser: "babel", useTabs: true });
|
||||||
prettierOptions: {
|
|
||||||
useTabs: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const TabsWrapper = tabsWrapper ? Tabs : Fragment;
|
const TabsWrapper = tabsWrapper ? Tabs : Fragment;
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
// @ts-nocheck xmlns in SVGs makes Astro very upset, so we'll just ignore this file
|
// @ts-nocheck xmlns in SVGs makes Astro very upset, so we'll just ignore this file
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ const props = z.object({
|
||||||
products: z.array(reference("products")),
|
products: z.array(reference("products")),
|
||||||
});
|
});
|
||||||
|
|
||||||
const { products } = Astro.props;
|
const { products } = await props.parseAsync(Astro.props);
|
||||||
|
|
||||||
const data = await getEntries(products);
|
const data = await getEntries(products);
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
const FieldBadges = ({ badges }) => {
|
const FieldBadges = ({ badges }: { badges: string[] }) => {
|
||||||
return (
|
return (
|
||||||
<ul className="list-none m-0 p-0 inline-flex items-center gap-2 text-xs">
|
<ul className="list-none m-0 p-0 inline-flex items-center gap-2 text-xs">
|
||||||
{badges.map((badge) => (
|
{badges.map((badge) => (
|
||||||
|
|
@ -74,10 +74,7 @@ const blocks = [
|
||||||
size="1.5rem"
|
size="1.5rem"
|
||||||
color="var(--sl-color-white)"
|
color="var(--sl-color-white)"
|
||||||
/>
|
/>
|
||||||
<a
|
<a href={link.href} class="pl-2 no-underline !text-black">
|
||||||
href={link.href}
|
|
||||||
class="pl-2 no-underline !text-black dark:!text-white"
|
|
||||||
>
|
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
const ModelBadges = ({ model }) => {
|
import type { WorkersAIModelsSchema } from "~/schemas";
|
||||||
|
|
||||||
|
const ModelBadges = ({ model }: { model: WorkersAIModelsSchema }) => {
|
||||||
const badges = model.properties.flatMap(({ property_id, value }) => {
|
const badges = model.properties.flatMap(({ property_id, value }) => {
|
||||||
if (property_id === "lora" && value === "true") {
|
if (property_id === "lora" && value === "true") {
|
||||||
return {
|
return {
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
import type { WorkersAIModelsSchema } from "~/schemas";
|
||||||
import { authorData } from "./data";
|
import { authorData } from "./data";
|
||||||
|
|
||||||
const ModelInfo = ({ model }) => {
|
const ModelInfo = ({ model }: { model: WorkersAIModelsSchema }) => {
|
||||||
const author =
|
const author =
|
||||||
authorData[model.name.split("/")[1]]?.name ?? model.name.split("/")[1];
|
authorData[model.name.split("/")[1]]?.name ?? model.name.split("/")[1];
|
||||||
return (
|
return (
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
import { useState } from "react";
|
|
||||||
import TextareaAutosize from "react-textarea-autosize";
|
|
||||||
|
|
||||||
const ModelPlayground = ({ model }) => {
|
|
||||||
const [response, setResponse] = useState("");
|
|
||||||
const [prompt, setPrompt] = useState("");
|
|
||||||
|
|
||||||
const handleSubmmit = () => {
|
|
||||||
fetch("https://ai.cloudflare.com/api/inference", {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
model: model.name,
|
|
||||||
prompt,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="shadow-2xl shadow-zinc-100 border border-gray-200 rounded-xl">
|
|
||||||
<div className="flex m-3 border border-gray-200 rounded-md items-start hover:bg-gray-50">
|
|
||||||
<TextareaAutosize
|
|
||||||
className="w-full p-2 resize-none outline-none bg-transparent"
|
|
||||||
minRows={1}
|
|
||||||
maxRows={4}
|
|
||||||
placeholder="Enter prompt..."
|
|
||||||
value={prompt}
|
|
||||||
onChange={(e) => setPrompt(e.target.value)}
|
|
||||||
/>
|
|
||||||
<button
|
|
||||||
onClick={handleSubmmit}
|
|
||||||
className="!m-2 rounded-md px-3 bg-gray-200 hover:bg-gray-300 cursor-pointer"
|
|
||||||
>
|
|
||||||
Submit
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="bg-orange-50 min-h-32 mx-3 rounded-md">{response}</div>
|
|
||||||
<span className="m-3 block text-sm text-gray-400 font-mono">
|
|
||||||
{model.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default ModelPlayground;
|
|
||||||
|
|
@ -6,7 +6,7 @@ import stabilityai from "../../assets/images/workers-ai/stabilityai.svg";
|
||||||
import huggingface from "../../assets/images/workers-ai/huggingface.svg";
|
import huggingface from "../../assets/images/workers-ai/huggingface.svg";
|
||||||
import google from "../../assets/images/workers-ai/google.svg";
|
import google from "../../assets/images/workers-ai/google.svg";
|
||||||
|
|
||||||
export const authorData = {
|
export const authorData: Record<string, { name: string; logo: string }> = {
|
||||||
openai: {
|
openai: {
|
||||||
name: "OpenAI",
|
name: "OpenAI",
|
||||||
logo: openai.src,
|
logo: openai.src,
|
||||||
|
|
|
||||||
|
|
@ -128,15 +128,12 @@ if (
|
||||||
<Default {...Astro.props} />
|
<Default {...Astro.props} />
|
||||||
<div id="footer-links" class="flex flex-wrap items-center">
|
<div id="footer-links" class="flex flex-wrap items-center">
|
||||||
{Object.entries(links).map(([text, href]) => (
|
{Object.entries(links).map(([text, href]) => (
|
||||||
<a
|
<a href={href} class="mx-2 my-2 text-xs text-black decoration-accent">
|
||||||
href={href}
|
|
||||||
class="mx-2 my-2 text-xs text-black decoration-accent-600 dark:text-white dark:decoration-accent-200"
|
|
||||||
>
|
|
||||||
<span>{text}</span>
|
<span>{text}</span>
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
{isProduction && (
|
{isProduction && (
|
||||||
<div class="mx-2 my-2 text-xs text-black underline decoration-accent-600 dark:text-white dark:decoration-accent-200">
|
<div class="mx-2 my-2 text-xs text-black [&>button]:underline [&>button]:decoration-accent">
|
||||||
<OneTrust />
|
<OneTrust />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,18 @@ import Default from "@astrojs/starlight/components/Sidebar.astro";
|
||||||
|
|
||||||
import { Icon as AstroIcon } from "astro-icon/components";
|
import { Icon as AstroIcon } from "astro-icon/components";
|
||||||
import { getEntry } from "astro:content";
|
import { getEntry } from "astro:content";
|
||||||
import { z } from "astro:schema";
|
|
||||||
import { Badge } from "@astrojs/starlight/components";
|
import { Badge } from "@astrojs/starlight/components";
|
||||||
import type { ComponentProps, HTMLAttributes } from "astro/types";
|
import type { ComponentProps, HTMLAttributes } from "astro/types";
|
||||||
import type { AstroBuiltinAttributes } from "astro";
|
|
||||||
|
|
||||||
const { sidebar, slug } = Astro.props;
|
const { sidebar, slug } = Astro.props;
|
||||||
|
|
||||||
const linkHTMLAttributesSchema = z.record(
|
|
||||||
z.union([z.string(), z.number(), z.boolean(), z.undefined()]),
|
|
||||||
) as z.Schema<
|
|
||||||
Omit<HTMLAttributes<"a">, keyof AstroBuiltinAttributes | "children">
|
|
||||||
>;
|
|
||||||
type LinkHTMLAttributes = z.infer<typeof linkHTMLAttributesSchema>;
|
|
||||||
|
|
||||||
interface Link {
|
interface Link {
|
||||||
type: "link";
|
type: "link";
|
||||||
label: string;
|
label: string;
|
||||||
href: string;
|
href: string;
|
||||||
isCurrent: boolean;
|
isCurrent: boolean;
|
||||||
badge: ComponentProps<typeof Badge> | undefined;
|
badge: ComponentProps<typeof Badge> | undefined;
|
||||||
attrs: LinkHTMLAttributes;
|
attrs: HTMLAttributes<"a">;
|
||||||
order: number;
|
order: number;
|
||||||
}
|
}
|
||||||
type SidebarEntry = Link | Group;
|
type SidebarEntry = Link | Group;
|
||||||
|
|
@ -37,7 +28,6 @@ interface Group {
|
||||||
badge: ComponentProps<typeof Badge> | undefined;
|
badge: ComponentProps<typeof Badge> | undefined;
|
||||||
order: number;
|
order: number;
|
||||||
}
|
}
|
||||||
``;
|
|
||||||
|
|
||||||
const currentSection = slug?.split("/")[0];
|
const currentSection = slug?.split("/")[0];
|
||||||
|
|
||||||
|
|
@ -116,7 +106,7 @@ async function handleGroup(group: Group): Promise<SidebarEntry> {
|
||||||
) as number;
|
) as number;
|
||||||
|
|
||||||
if (indexPage.data.sidebar.group?.hideIndex) {
|
if (indexPage.data.sidebar.group?.hideIndex) {
|
||||||
group.entries.splice(indexIdx, 1)[0];
|
group.entries.splice(indexIdx, 1);
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -197,7 +187,7 @@ const lookupProductTitle = async (slug: string) => {
|
||||||
name={currentSection}
|
name={currentSection}
|
||||||
class="mr-2 text-4xl text-[color:var(--orange-accent-200)]"
|
class="mr-2 text-4xl text-[color:var(--orange-accent-200)]"
|
||||||
/>
|
/>
|
||||||
<span class="text-black dark:text-white">
|
<span class="text-black">
|
||||||
<strong>
|
<strong>
|
||||||
{lookupProductTitle(slug)}
|
{lookupProductTitle(slug)}
|
||||||
</strong>
|
</strong>
|
||||||
|
|
@ -248,6 +238,10 @@ const lookupProductTitle = async (slug: string) => {
|
||||||
:root[data-theme="dark"] {
|
:root[data-theme="dark"] {
|
||||||
.sidebar-content {
|
.sidebar-content {
|
||||||
--sl-color-hairline-light: #444444 !important;
|
--sl-color-hairline-light: #444444 !important;
|
||||||
|
|
||||||
|
& > * a[aria-current="page"] {
|
||||||
|
color: var(--sl-color-accent-high) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { z, defineCollection } from "astro:content";
|
import { z, defineCollection } from "astro:content";
|
||||||
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
|
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
|
||||||
import { file } from "astro/loaders";
|
|
||||||
import {
|
import {
|
||||||
appsSchema,
|
appsSchema,
|
||||||
changelogsSchema,
|
changelogsSchema,
|
||||||
|
|
@ -12,8 +11,8 @@ import {
|
||||||
glossarySchema,
|
glossarySchema,
|
||||||
learningPathsSchema,
|
learningPathsSchema,
|
||||||
videosSchema,
|
videosSchema,
|
||||||
|
workersAiModelsSchema,
|
||||||
warpReleasesSchema,
|
warpReleasesSchema,
|
||||||
workersAiSchema,
|
|
||||||
changelogsNextSchema,
|
changelogsNextSchema,
|
||||||
fieldsSchema,
|
fieldsSchema,
|
||||||
} from "~/schemas";
|
} from "~/schemas";
|
||||||
|
|
@ -67,7 +66,7 @@ export const collections = {
|
||||||
type: "data",
|
type: "data",
|
||||||
}),
|
}),
|
||||||
"workers-ai-models": defineCollection({
|
"workers-ai-models": defineCollection({
|
||||||
schema: workersAiSchema,
|
schema: workersAiModelsSchema,
|
||||||
type: "data",
|
type: "data",
|
||||||
}),
|
}),
|
||||||
videos: defineCollection({
|
videos: defineCollection({
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,13 @@ export default {
|
||||||
|
|
||||||
## TypeScript examples
|
## TypeScript examples
|
||||||
|
|
||||||
The `TypeScriptExample` component uses [`detype`](https://www.npmjs.com/package/detype) to remove TypeScript-specific syntax from your example and provide a JavaScript tab. This reduces maintenance burden by only having a single example to maintain.
|
The `TypeScriptExample` component uses [`ts-blank-space`](https://github.com/bloomberg/ts-blank-space) to remove TypeScript-specific syntax from your example and provide a JavaScript tab. This reduces maintenance burden by only having a single example to maintain.
|
||||||
|
|
||||||
|
:::note
|
||||||
|
Some TypeScript syntax influences runtime behaviour, and cannot be stripped.
|
||||||
|
|
||||||
|
Please refer to the [Unsupported Syntax](https://github.com/bloomberg/ts-blank-space?tab=readme-ov-file#unsupported-syntax) section of the project's README.
|
||||||
|
:::
|
||||||
|
|
||||||
### Input
|
### Input
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ const recommendedSection = {
|
||||||
<a
|
<a
|
||||||
href={link.href}
|
href={link.href}
|
||||||
target={link.target}
|
target={link.target}
|
||||||
class="!text-black hover:!text-accent-600 dark:!text-accent-200 dark:hover:!text-white"
|
class="!text-black hover:!text-accent dark:!text-accent-high dark:hover:!text-black"
|
||||||
>
|
>
|
||||||
{link.text}
|
{link.text}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ const products = lpProducts(learningPaths);
|
||||||
</Description>
|
</Description>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div class="w-1/4 pr-4 hidden lg:block">
|
<div class="w-1/4 pr-4 hidden lg:block">
|
||||||
<div class="border-b-2 border-accent-600 dark:border-accent-200">
|
<div class="border-b-2 border-accent">
|
||||||
<h2>Filters</h2>
|
<h2>Filters</h2>
|
||||||
</div>
|
</div>
|
||||||
<div id="areas-filter">
|
<div id="areas-filter">
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
import { getCollection, type CollectionEntry } from "astro:content";
|
import { getCollection, type CollectionEntry } from "astro:content";
|
||||||
// @ts-ignore virtual module
|
// @ts-expect-error virtual module
|
||||||
import iconCollection from "virtual:astro-icon";
|
import iconCollection from "virtual:astro-icon";
|
||||||
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
||||||
import { getIconData, iconToSVG } from "@iconify/utils";
|
import { getIconData, iconToSVG } from "@iconify/utils";
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
---
|
---
|
||||||
import type { GetStaticPaths, MarkdownHeading } from "astro";
|
import type { GetStaticPaths } from "astro";
|
||||||
import { marked } from "marked";
|
import { marked } from "marked";
|
||||||
import { getEntry } from "astro:content";
|
import { getEntry } from "astro:content";
|
||||||
import StarlightPage, {
|
import StarlightPage, {
|
||||||
type StarlightPageProps,
|
type StarlightPageProps,
|
||||||
} from "@astrojs/starlight/components/StarlightPage.astro";
|
} from "@astrojs/starlight/components/StarlightPage.astro";
|
||||||
import { Code, Aside, Type } from "~/components";
|
import { Code, Aside, Type } from "~/components";
|
||||||
import FieldBadges from "~/components/fields/FieldBadges.jsx";
|
import FieldBadges from "~/components/fields/FieldBadges.tsx";
|
||||||
|
|
||||||
export const getStaticPaths = (async () => {
|
export const getStaticPaths = (async () => {
|
||||||
const fields = await getEntry("fields", "index");
|
const fields = await getEntry("fields", "index");
|
||||||
|
|
@ -28,7 +28,6 @@ const { field } = Astro.props;
|
||||||
// set in /src/pages/changelog/index/index.xml.ts
|
// set in /src/pages/changelog/index/index.xml.ts
|
||||||
marked.use({ walkTokens: null });
|
marked.use({ walkTokens: null });
|
||||||
|
|
||||||
let CodeExamples = null;
|
|
||||||
const description = field.description;
|
const description = field.description;
|
||||||
|
|
||||||
// Strong type coercion needed due to Starlight's component override for hideTitle
|
// Strong type coercion needed due to Starlight's component override for hideTitle
|
||||||
|
|
@ -119,7 +118,7 @@ const starlightPageProps = {
|
||||||
|
|
||||||
<div class="!mt-8">
|
<div class="!mt-8">
|
||||||
<span class="text-xs"
|
<span class="text-xs"
|
||||||
>Categories: <FieldBadges badges={field.categories} /></span
|
>Categories: <FieldBadges badges={field.categories as string[]} /></span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</StarlightPage>
|
</StarlightPage>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
import { getEntry } from "astro:content";
|
import { getEntry } from "astro:content";
|
||||||
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
||||||
import FieldCatalog from "~/components/FieldCatalog.jsx";
|
import FieldCatalog from "~/components/FieldCatalog.tsx";
|
||||||
|
|
||||||
const fieldData = await getEntry("fields", "index");
|
const fieldData = await getEntry("fields", "index");
|
||||||
const fields = fieldData.data.entries;
|
const fields = fieldData.data.entries;
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ import "instantsearch.css/themes/satellite.css";
|
||||||
|
|
||||||
return (widgetParams: any) => {
|
return (widgetParams: any) => {
|
||||||
const widget = makeWidget(widgetParams);
|
const widget = makeWidget(widgetParams);
|
||||||
let state: {
|
const state: {
|
||||||
windowClickListener?: (event: MouseEvent) => void;
|
windowClickListener?: (event: MouseEvent) => void;
|
||||||
} = {};
|
} = {};
|
||||||
let rootElem: HTMLElement | null;
|
let rootElem: HTMLElement | null;
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,8 @@ import StarlightPage, {
|
||||||
type StarlightPageProps,
|
type StarlightPageProps,
|
||||||
} from "@astrojs/starlight/components/StarlightPage.astro";
|
} from "@astrojs/starlight/components/StarlightPage.astro";
|
||||||
import { LinkButton, Tabs, TabItem, Code, Aside } from "~/components";
|
import { LinkButton, Tabs, TabItem, Code, Aside } from "~/components";
|
||||||
import ModelInfo from "~/components/models/ModelInfo.jsx";
|
import ModelInfo from "~/components/models/ModelInfo.tsx";
|
||||||
import ModelBadges from "~/components/models/ModelBadges.jsx";
|
import ModelBadges from "~/components/models/ModelBadges.tsx";
|
||||||
import SchemaViewer from "~/components/models/SchemaViewer.astro";
|
import SchemaViewer from "~/components/models/SchemaViewer.astro";
|
||||||
|
|
||||||
import TextGenerationCode from "~/components/models/code/TextGenerationCode.astro";
|
import TextGenerationCode from "~/components/models/code/TextGenerationCode.astro";
|
||||||
|
|
@ -123,7 +123,11 @@ const starlightPageProps = {
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
{
|
{
|
||||||
author ? (
|
author ? (
|
||||||
<img class="mr-4 w-12 h-12 block" src={author.logo} />
|
<img
|
||||||
|
class="mr-4 w-12 h-12 block"
|
||||||
|
src={author.logo}
|
||||||
|
alt={`${author.name} logo`}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div class="w-12 h-12 mr-4 rounded-md bg-gray-100 text-gray-400 uppercase text-2xl font-black flex justify-center items-center">
|
<div class="w-12 h-12 mr-4 rounded-md bg-gray-100 text-gray-400 uppercase text-2xl font-black flex justify-center items-center">
|
||||||
{model.name.split("/")[1].substring(0, 1)}
|
{model.name.split("/")[1].substring(0, 1)}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
||||||
import ModelCatalog from "~/components/ModelCatalog.jsx";
|
import ModelCatalog from "~/components/ModelCatalog.tsx";
|
||||||
|
|
||||||
const modelData = await getCollection("workers-ai-models");
|
const modelData = await getCollection("workers-ai-models");
|
||||||
const models = modelData.map(({ data }) => data);
|
const models = modelData.map(({ data }) => data);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export async function GET() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// omit sort_date from output
|
// omit sort_date from output
|
||||||
const { sort_date, ...data } = x.data;
|
const { sort_date: _, ...data } = x.data;
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
description: x.body.trim(),
|
description: x.body.trim(),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import { z } from "astro:schema";
|
import { z } from "astro:schema";
|
||||||
|
|
||||||
export const workersAiSchema = z.object({
|
export type WorkersAIModelsSchema = z.infer<typeof workersAiModelsSchema>;
|
||||||
|
|
||||||
|
export const workersAiModelsSchema = z.object({
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
source: z.number(),
|
source: z.number(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,23 @@
|
||||||
import tippy from "tippy.js";
|
import tippy from "tippy.js";
|
||||||
|
import { type Props } from "tippy.js";
|
||||||
|
|
||||||
export function addTooltip(element: HTMLElement, content: string) {
|
type Options = Partial<Props & { hideAfter: number }>;
|
||||||
|
|
||||||
|
export function addTooltip(
|
||||||
|
element: HTMLElement,
|
||||||
|
content: string,
|
||||||
|
opts?: Options,
|
||||||
|
) {
|
||||||
const id = "#" + CSS.escape(element.id);
|
const id = "#" + CSS.escape(element.id);
|
||||||
|
|
||||||
|
if (opts?.hideAfter) {
|
||||||
|
opts.onShow = (instance) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
instance.hide();
|
||||||
|
}, opts.hideAfter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
tippy(id, {
|
tippy(id, {
|
||||||
content,
|
content,
|
||||||
allowHTML: true,
|
allowHTML: true,
|
||||||
|
|
@ -14,5 +29,6 @@ export function addTooltip(element: HTMLElement, content: string) {
|
||||||
// cutoff by the sidebar
|
// cutoff by the sidebar
|
||||||
// https://atomiks.github.io/tippyjs/v6/faq/#my-tooltip-appears-cut-off-or-is-not-showing-at-all
|
// https://atomiks.github.io/tippyjs/v6/faq/#my-tooltip-appears-cut-off-or-is-not-showing-at-all
|
||||||
appendTo: document.body,
|
appendTo: document.body,
|
||||||
|
...opts,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ export default {
|
||||||
},
|
},
|
||||||
accent: {
|
accent: {
|
||||||
DEFAULT: "var(--sl-color-accent)",
|
DEFAULT: "var(--sl-color-accent)",
|
||||||
|
high: "var(--tw-accent-200)",
|
||||||
200: "var(--tw-accent-200)",
|
200: "var(--tw-accent-200)",
|
||||||
600: "var(--tw-accent-600)",
|
600: "var(--tw-accent-600)",
|
||||||
900: "var(--tw-accent-900)",
|
900: "var(--tw-accent-900)",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue