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 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
|
||||
## TODO: content formatting checks
|
||||
- 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",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"redhat.vscode-yaml",
|
||||
"esbenp.prettier-vscode"
|
||||
"esbenp.prettier-vscode",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ async function main() {
|
|||
let numInfiniteRedirects = 0;
|
||||
let numUrlsWithFragment = 0;
|
||||
let numDuplicateRedirects = 0;
|
||||
let redirectSourceUrls: string[] = [];
|
||||
|
||||
const redirectSourceUrls: string[] = [];
|
||||
|
||||
for (const line of redirects.split("\n")) {
|
||||
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 lightTheme from "solarflare-theme/themes/cloudflare-light-color-theme.json" with { type: "json" };
|
||||
|
||||
import { definePlugin } from "@expressive-code/core";
|
||||
import { h } from "@expressive-code/core/hast";
|
||||
import pluginWorkersPlayground from "./plugins/expressive-code/workers-playground.js";
|
||||
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 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 {
|
||||
plugins: [
|
||||
workersPlaygroundButton(),
|
||||
outputCodeblocks(),
|
||||
defaultLanguageTitles(),
|
||||
pluginWorkersPlayground(),
|
||||
pluginOutputFrame(),
|
||||
pluginDefaultTitles(),
|
||||
pluginCollapsibleSections(),
|
||||
],
|
||||
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 },
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
12063
package-lock.json
generated
12063
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:content": "npx prettier --write \"**/*.{md,mdx,astro}\"",
|
||||
"format:data": "npx prettier --write \"**/*.{json,yaml,yml}\"",
|
||||
"postinstall": "npx patch-package && npm run sync",
|
||||
"postinstall": "npm run sync",
|
||||
"preview": "npx astro preview",
|
||||
"script:optimize-svgs": "npx tsx scripts/optimize-svgs.ts",
|
||||
"start": "npx astro dev",
|
||||
"sync": "npx astro sync",
|
||||
"test": "npx vitest"
|
||||
"test": "npx vitest",
|
||||
"lint": "npx eslint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astro-community/astro-embed-youtube": "^0.5.6",
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/react": "^3.6.3",
|
||||
"@astrojs/rss": "^4.0.11",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"@astrojs/starlight": "^0.29.3",
|
||||
"@astrojs/starlight-docsearch": "^0.3.0",
|
||||
"@astrojs/starlight-tailwind": "^2.0.3",
|
||||
"@astrojs/tailwind": "^5.1.4",
|
||||
"@cloudflare/puppeteer": "^0.0.14",
|
||||
"@cloudflare/vitest-pool-workers": "^0.6.0",
|
||||
"@cloudflare/workers-types": "^4.20241218.0",
|
||||
"@codingheads/sticky-header": "^1.0.2",
|
||||
"@expressive-code/plugin-collapsible-sections": "^0.40.0",
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@iconify-json/material-symbols": "^1.2.12",
|
||||
"@stoplight/json-schema-tree": "^4.0.0",
|
||||
"@types/hast": "^3.0.4",
|
||||
"@types/he": "^1.2.3",
|
||||
"@types/node": "^22.10.6",
|
||||
"@types/react": "^18.3.12",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"algoliasearch": "^5.19.0",
|
||||
"astro": "^4.16.18",
|
||||
"astro-breadcrumbs": "^3.3.1",
|
||||
"astro-icon": "^1.1.2",
|
||||
"astro-live-code": "^0.0.5",
|
||||
"date-fns": "^4.1.0",
|
||||
"dedent": "^1.5.3",
|
||||
"detype": "1.0.12",
|
||||
"@astrojs/check": "0.9.4",
|
||||
"@astrojs/react": "4.1.5",
|
||||
"@astrojs/rss": "4.0.11",
|
||||
"@astrojs/sitemap": "3.2.1",
|
||||
"@astrojs/starlight": "0.29.3",
|
||||
"@astrojs/starlight-docsearch": "0.3.0",
|
||||
"@astrojs/starlight-tailwind": "2.0.3",
|
||||
"@astrojs/tailwind": "5.1.4",
|
||||
"@cloudflare/puppeteer": "0.0.14",
|
||||
"@cloudflare/vitest-pool-workers": "0.6.0",
|
||||
"@cloudflare/workers-types": "4.20250109.0",
|
||||
"@codingheads/sticky-header": "1.0.2",
|
||||
"@expressive-code/plugin-collapsible-sections": "0.38.3",
|
||||
"@iarna/toml": "2.2.5",
|
||||
"@iconify-json/material-symbols": "1.2.12",
|
||||
"@stoplight/json-schema-tree": "4.0.0",
|
||||
"@types/hast": "3.0.4",
|
||||
"@types/he": "1.2.3",
|
||||
"@types/node": "22.10.7",
|
||||
"@types/react": "19.0.7",
|
||||
"@types/react-dom": "19.0.3",
|
||||
"@typescript-eslint/parser": "8.20.0",
|
||||
"algoliasearch": "5.19.0",
|
||||
"astro": "4.16.18",
|
||||
"astro-breadcrumbs": "3.3.1",
|
||||
"astro-icon": "1.1.5",
|
||||
"astro-live-code": "0.0.5",
|
||||
"date-fns": "4.1.0",
|
||||
"dedent": "1.5.3",
|
||||
"dompurify": "3.2.3",
|
||||
"dot-prop": "^9.0.0",
|
||||
"fast-glob": "^3.3.3",
|
||||
"github-slugger": "^2.0.0",
|
||||
"hastscript": "^9.0.0",
|
||||
"he": "^1.2.0",
|
||||
"instantsearch.css": "^8.5.1",
|
||||
"instantsearch.js": "^4.75.7",
|
||||
"jsonc-parser": "^3.3.1",
|
||||
"lz-string": "^1.5.0",
|
||||
"marked": "^15.0.6",
|
||||
"mdast-util-mdx-expression": "^2.0.1",
|
||||
"mermaid": "^11.4.1",
|
||||
"node-html-parser": "^6.1.13",
|
||||
"patch-package": "^8.0.0",
|
||||
"playwright": "^1.49.1",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"dot-prop": "9.0.0",
|
||||
"eslint": "9.18.0",
|
||||
"eslint-plugin-astro": "1.3.1",
|
||||
"eslint-plugin-jsx-a11y": "6.10.2",
|
||||
"eslint-plugin-react": "7.37.4",
|
||||
"fast-glob": "3.3.3",
|
||||
"github-slugger": "2.0.0",
|
||||
"globals": "15.14.0",
|
||||
"hastscript": "9.0.0",
|
||||
"he": "1.2.0",
|
||||
"instantsearch.css": "8.5.1",
|
||||
"instantsearch.js": "4.77.0",
|
||||
"jsonc-parser": "3.3.1",
|
||||
"lz-string": "1.5.0",
|
||||
"marked": "15.0.6",
|
||||
"mdast-util-mdx-expression": "2.0.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",
|
||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||
"puppeteer": "^24.0.0",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-markdown": "^9.0.3",
|
||||
"react-textarea-autosize": "^8.5.7",
|
||||
"redirects-in-workers": "^0.0.5",
|
||||
"rehype-autolink-headings": "^7.1.0",
|
||||
"rehype-external-links": "^3.0.0",
|
||||
"rehype-mermaid": "^3.0.0",
|
||||
"rehype-title-figure": "^0.1.2",
|
||||
"sharp": "^0.33.5",
|
||||
"solarflare-theme": "^0.0.2",
|
||||
"starlight-image-zoom": "^0.9.0",
|
||||
"starlight-links-validator": "^0.14.1",
|
||||
"starlight-package-managers": "^0.9.0",
|
||||
"svgo": "^3.3.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tsx": "^4.19.2",
|
||||
"typescript": "^5.7.3",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"puppeteer": "24.1.0",
|
||||
"react": "19.0.0",
|
||||
"react-dom": "19.0.0",
|
||||
"react-markdown": "9.0.3",
|
||||
"redirects-in-workers": "0.0.5",
|
||||
"rehype-autolink-headings": "7.1.0",
|
||||
"rehype-external-links": "3.0.0",
|
||||
"rehype-mermaid": "3.0.0",
|
||||
"rehype-title-figure": "0.1.2",
|
||||
"sharp": "0.33.5",
|
||||
"solarflare-theme": "0.0.2",
|
||||
"starlight-image-zoom": "0.9.0",
|
||||
"starlight-links-validator": "0.14.1",
|
||||
"starlight-package-managers": "0.9.0",
|
||||
"svgo": "3.3.2",
|
||||
"tailwindcss": "3.4.17",
|
||||
"tippy.js": "6.3.7",
|
||||
"ts-blank-space": "0.5.0",
|
||||
"tsx": "4.19.2",
|
||||
"typescript": "5.7.3",
|
||||
"typescript-eslint": "8.20.0",
|
||||
"unist-util-visit": "5.0.0",
|
||||
"vitest": "2.1.8",
|
||||
"wrangler": "^3.101.0",
|
||||
"yaml": "^2.7.0"
|
||||
"wrangler": "3.101.0"
|
||||
},
|
||||
"engines": {
|
||||
"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 duration = end - start;
|
||||
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(
|
||||
`Original size: ~${formatBytes(originalSize)}, optimized size: ~${formatBytes(optimizedSize)}. Saved ~${formatBytes(originalSize - optimizedSize)}`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,23 @@
|
|||
import { useState } from "react";
|
||||
import FieldBadges from "./fields/FieldBadges";
|
||||
import Markdown from "react-markdown";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
|
||||
const FieldCatalog = ({ fields }) => {
|
||||
const [filters, setFilters] = useState({
|
||||
type Fields = CollectionEntry<"fields">["data"]["entries"];
|
||||
|
||||
type Filters = {
|
||||
search: string;
|
||||
categories: string[];
|
||||
keywords: string[];
|
||||
};
|
||||
|
||||
const FieldCatalog = ({ fields }: { fields: Fields }) => {
|
||||
const [filters, setFilters] = useState<Filters>({
|
||||
search: "",
|
||||
categories: [],
|
||||
keywords: [],
|
||||
});
|
||||
|
||||
const mapped = fields.sort((f1, f2) => {
|
||||
return f1.name < f2.name ? -1 : 1;
|
||||
});
|
||||
|
|
@ -31,7 +41,7 @@ const FieldCatalog = ({ fields }) => {
|
|||
|
||||
if (filters.search) {
|
||||
// search keywords
|
||||
let keywordFound = field.keywords?.some(
|
||||
const keywordFound = field.keywords?.some(
|
||||
(kw) => kw.indexOf(filters.search) >= 0,
|
||||
);
|
||||
|
||||
|
|
@ -70,16 +80,18 @@ const FieldCatalog = ({ fields }) => {
|
|||
className="mr-2"
|
||||
value={category}
|
||||
onClick={(e) => {
|
||||
if (e.target.checked) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
|
||||
if (target.checked) {
|
||||
setFilters({
|
||||
...filters,
|
||||
categories: [...filters.categories, e.target.value],
|
||||
categories: [...filters.categories, target.value],
|
||||
});
|
||||
} else {
|
||||
setFilters({
|
||||
...filters,
|
||||
categories: filters.categories.filter(
|
||||
(f) => f !== e.target.value,
|
||||
(f) => f !== target.value,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
|
@ -62,7 +62,7 @@ if (lines) {
|
|||
}
|
||||
|
||||
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 { getGlossaryEntry } from "~/util/glossary";
|
||||
import { marked } from "marked";
|
||||
|
|
@ -29,7 +30,7 @@ definition = definition.split(/\r?\n/)[0];
|
|||
id={tooltip.term}
|
||||
data-tooltip
|
||||
data-content={marked.parse(definition)}
|
||||
class="border-b-2 border-dashed border-accent-600"
|
||||
class="border-b-2 border-dashed border-accent"
|
||||
tabindex="0"
|
||||
>{
|
||||
link ? (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
---
|
||||
import { Image } from "astro:assets";
|
||||
import type { Props } from "@astrojs/starlight/props";
|
||||
import type { ImageMetadata } from "astro";
|
||||
|
||||
const { data } = Astro.props.entry;
|
||||
const { title = data.title, tagline, image } = data.hero || {};
|
||||
|
|
|
|||
|
|
@ -2,14 +2,23 @@ import { useState } from "react";
|
|||
import ModelInfo from "./models/ModelInfo";
|
||||
import ModelBadges from "./models/ModelBadges";
|
||||
import { authorData } from "./models/data";
|
||||
import type { WorkersAIModelsSchema } from "~/schemas";
|
||||
|
||||
const ModelCatalog = ({ models }) => {
|
||||
const [filters, setFilters] = useState({
|
||||
type Filters = {
|
||||
search: string;
|
||||
authors: string[];
|
||||
tasks: string[];
|
||||
capabilities: string[];
|
||||
};
|
||||
|
||||
const ModelCatalog = ({ models }: { models: WorkersAIModelsSchema[] }) => {
|
||||
const [filters, setFilters] = useState<Filters>({
|
||||
search: "",
|
||||
authors: [],
|
||||
tasks: [],
|
||||
capabilities: [],
|
||||
});
|
||||
|
||||
const mapped = models.map((model) => ({
|
||||
model: {
|
||||
...model,
|
||||
|
|
@ -22,6 +31,8 @@ const ModelCatalog = ({ models }) => {
|
|||
if (property_id === "function_calling" && value === "true") {
|
||||
return "Function calling";
|
||||
}
|
||||
|
||||
return [];
|
||||
})
|
||||
.filter((p) => Boolean(p)),
|
||||
},
|
||||
|
|
@ -101,15 +112,17 @@ const ModelCatalog = ({ models }) => {
|
|||
className="mr-2"
|
||||
value={task}
|
||||
onClick={(e) => {
|
||||
if (e.target.checked) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
|
||||
if (target.checked) {
|
||||
setFilters({
|
||||
...filters,
|
||||
tasks: [...filters.tasks, e.target.value],
|
||||
tasks: [...filters.tasks, target.value],
|
||||
});
|
||||
} else {
|
||||
setFilters({
|
||||
...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}
|
||||
className="mr-2"
|
||||
onClick={(e) => {
|
||||
if (e.target.checked) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
|
||||
if (target.checked) {
|
||||
setFilters({
|
||||
...filters,
|
||||
capabilities: [...filters.capabilities, e.target.value],
|
||||
capabilities: [...filters.capabilities, target.value],
|
||||
});
|
||||
} else {
|
||||
setFilters({
|
||||
...filters,
|
||||
capabilities: filters.capabilities.filter(
|
||||
(f) => f !== e.target.value,
|
||||
(f) => f !== target.value,
|
||||
),
|
||||
});
|
||||
}
|
||||
|
|
@ -163,16 +178,18 @@ const ModelCatalog = ({ models }) => {
|
|||
className="mr-2"
|
||||
value={author}
|
||||
onClick={(e) => {
|
||||
if (e.target.checked) {
|
||||
const target = e.target as HTMLInputElement;
|
||||
|
||||
if (target.checked) {
|
||||
setFilters({
|
||||
...filters,
|
||||
authors: [...filters.authors, e.target.value],
|
||||
authors: [...filters.authors, target.value],
|
||||
});
|
||||
} else {
|
||||
setFilters({
|
||||
...filters,
|
||||
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",
|
||||
);
|
||||
|
||||
const author =
|
||||
authorData[model.model.name.split("/")[1]]?.name ??
|
||||
model.model.name.split("/")[1];
|
||||
const author = model.model.name.split("/")[1];
|
||||
const authorInfo = authorData[author];
|
||||
|
||||
return (
|
||||
<a
|
||||
|
|
@ -210,14 +226,15 @@ const ModelCatalog = ({ models }) => {
|
|||
href={`/workers-ai/models/${model.model_display_name}`}
|
||||
>
|
||||
<div className="-mb-1 flex items-center">
|
||||
{authorData[model.model.name.split("/")[1]]?.logo ? (
|
||||
{authorInfo?.logo ? (
|
||||
<img
|
||||
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">
|
||||
{author.substr(0, 1)}
|
||||
{author.slice(0, 1)}
|
||||
</div>
|
||||
)}
|
||||
<span className="overflow-hidden text-ellipsis whitespace-nowrap text-lg font-semibold">
|
||||
|
|
@ -1,39 +1,24 @@
|
|||
{
|
||||
import.meta.env.PROD ? (
|
||||
<>
|
||||
<script
|
||||
---
|
||||
const isProduction = import.meta.env.PROD;
|
||||
|
||||
const uuid = isProduction
|
||||
? "b1e05d49-f072-4bae-9116-bdb78af15448"
|
||||
: "b1e05d49-f072-4bae-9116-bdb78af15448-test";
|
||||
---
|
||||
|
||||
<script
|
||||
src="https://ot.www.cloudflare.com/public/vendor/onetrust/scripttemplates/otSDKStub.js"
|
||||
type="text/javascript"
|
||||
charset="UTF-8"
|
||||
data-domain-script="b1e05d49-f072-4bae-9116-bdb78af15448"
|
||||
is:inline
|
||||
/>
|
||||
<script type="text/javascript" is:inline>
|
||||
data-domain-script={uuid}
|
||||
is:inline></script>
|
||||
<script type="text/javascript" is:inline>
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
function OptanonWrapper() {}
|
||||
</script>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<script
|
||||
src="https://ot.www.cloudflare.com/public/vendor/onetrust/scripttemplates/otSDKStub.js"
|
||||
type="text/javascript"
|
||||
charset="UTF-8"
|
||||
data-domain-script="b1e05d49-f072-4bae-9116-bdb78af15448-test"
|
||||
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>
|
||||
</script>
|
||||
<!-- OneTrust Cookies Settings button start -->
|
||||
<button id="ot-sdk-btn" class="ot-sdk-show-settings">Cookie Settings</button>
|
||||
<!-- OneTrust Cookies Settings button end -->
|
||||
|
||||
<style>
|
||||
#ot-sdk-btn.ot-sdk-show-settings {
|
||||
|
|
@ -43,6 +28,7 @@
|
|||
line-height: inherit !important;
|
||||
padding: inherit !important;
|
||||
font-family: var(--sl-font-family) !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
#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 presets = entry.data.build_configs;
|
||||
const entries = Object.entries(presets);
|
||||
const entries = Object.values(presets);
|
||||
---
|
||||
|
||||
<table>
|
||||
|
|
@ -14,7 +14,7 @@ const entries = Object.entries(presets);
|
|||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
entries.map(([_, value]) => (
|
||||
entries.map((value) => (
|
||||
<tr>
|
||||
<td>{value.display_name}</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);
|
||||
|
||||
let availability;
|
||||
if (type) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error plans are not typed
|
||||
availability = mappings[type];
|
||||
} else {
|
||||
// @ts-ignore
|
||||
availability = await indexPlans(id);
|
||||
}
|
||||
---
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ export type ProductData = CollectionEntry<"products"> & {
|
|||
groups: string[];
|
||||
};
|
||||
|
||||
const ProductCatalog = ({ products }: { products: ProductData[] }) => {
|
||||
const [filters, setFilters] = useState<{
|
||||
type Filters = {
|
||||
search: string;
|
||||
groups: string[];
|
||||
}>({
|
||||
};
|
||||
|
||||
const ProductCatalog = ({ products }: { products: ProductData[] }) => {
|
||||
const [filters, setFilters] = useState<Filters>({
|
||||
search: "",
|
||||
groups: [],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -14,10 +14,9 @@ const props = z.object({
|
|||
id: zodEnumFromObjKeys(mappings),
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
const { id } = props.parse(Astro.props);
|
||||
|
||||
let stat = mappings[id];
|
||||
const stat = mappings[id];
|
||||
---
|
||||
|
||||
{stat}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const { header, href, product } = props.parse(Astro.props);
|
|||
<strong>
|
||||
<a
|
||||
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
|
||||
>
|
||||
</strong>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
---
|
||||
import { z } from "astro:schema";
|
||||
import { Icon } from "@astrojs/starlight/components";
|
||||
|
||||
type Props = z.infer<typeof props>;
|
||||
|
||||
|
|
@ -13,11 +12,42 @@ const props = z
|
|||
const { id } = props.parse(Astro.props);
|
||||
---
|
||||
|
||||
<code
|
||||
title="Click to copy the full ID"
|
||||
onclick=`navigator.clipboard.writeText("${id}")`
|
||||
class="inline-flex w-fit hover:bg-accent-600/50 hover:cursor-pointer active:bg-accent-600"
|
||||
>
|
||||
<rule-id id={id}>
|
||||
<button title="Click to copy the full ID" class="px-0">
|
||||
<code class="flex">
|
||||
{`...${id.slice(-8)}`}
|
||||
<Icon name="document" class="!inline justify-center" />
|
||||
</code>
|
||||
</code>
|
||||
</button>
|
||||
</rule-id>
|
||||
|
||||
<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 { transform } from "detype";
|
||||
import tsBlankSpace from "ts-blank-space";
|
||||
import { format } from "prettier";
|
||||
import { parse } from "node-html-parser";
|
||||
import { Code, Tabs, TabItem } from "@astrojs/starlight/components";
|
||||
|
||||
|
|
@ -58,11 +59,7 @@ if (!code) {
|
|||
|
||||
code = code.replace(/\u007f/g, "\n");
|
||||
|
||||
const js = await transform(code, "placeholder.ts", {
|
||||
prettierOptions: {
|
||||
useTabs: true,
|
||||
},
|
||||
});
|
||||
const js = await format(tsBlankSpace(code), { parser: "babel", useTabs: true });
|
||||
|
||||
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
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const props = z.object({
|
|||
products: z.array(reference("products")),
|
||||
});
|
||||
|
||||
const { products } = Astro.props;
|
||||
const { products } = await props.parseAsync(Astro.props);
|
||||
|
||||
const data = await getEntries(products);
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
const FieldBadges = ({ badges }) => {
|
||||
const FieldBadges = ({ badges }: { badges: string[] }) => {
|
||||
return (
|
||||
<ul className="list-none m-0 p-0 inline-flex items-center gap-2 text-xs">
|
||||
{badges.map((badge) => (
|
||||
|
|
@ -74,10 +74,7 @@ const blocks = [
|
|||
size="1.5rem"
|
||||
color="var(--sl-color-white)"
|
||||
/>
|
||||
<a
|
||||
href={link.href}
|
||||
class="pl-2 no-underline !text-black dark:!text-white"
|
||||
>
|
||||
<a href={link.href} class="pl-2 no-underline !text-black">
|
||||
{link.text}
|
||||
</a>
|
||||
</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 }) => {
|
||||
if (property_id === "lora" && value === "true") {
|
||||
return {
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import type { WorkersAIModelsSchema } from "~/schemas";
|
||||
import { authorData } from "./data";
|
||||
|
||||
const ModelInfo = ({ model }) => {
|
||||
const ModelInfo = ({ model }: { model: WorkersAIModelsSchema }) => {
|
||||
const author =
|
||||
authorData[model.name.split("/")[1]]?.name ?? model.name.split("/")[1];
|
||||
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 google from "../../assets/images/workers-ai/google.svg";
|
||||
|
||||
export const authorData = {
|
||||
export const authorData: Record<string, { name: string; logo: string }> = {
|
||||
openai: {
|
||||
name: "OpenAI",
|
||||
logo: openai.src,
|
||||
|
|
|
|||
|
|
@ -128,15 +128,12 @@ if (
|
|||
<Default {...Astro.props} />
|
||||
<div id="footer-links" class="flex flex-wrap items-center">
|
||||
{Object.entries(links).map(([text, href]) => (
|
||||
<a
|
||||
href={href}
|
||||
class="mx-2 my-2 text-xs text-black decoration-accent-600 dark:text-white dark:decoration-accent-200"
|
||||
>
|
||||
<a href={href} class="mx-2 my-2 text-xs text-black decoration-accent">
|
||||
<span>{text}</span>
|
||||
</a>
|
||||
))}
|
||||
{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 />
|
||||
</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -4,27 +4,18 @@ import Default from "@astrojs/starlight/components/Sidebar.astro";
|
|||
|
||||
import { Icon as AstroIcon } from "astro-icon/components";
|
||||
import { getEntry } from "astro:content";
|
||||
import { z } from "astro:schema";
|
||||
import { Badge } from "@astrojs/starlight/components";
|
||||
import type { ComponentProps, HTMLAttributes } from "astro/types";
|
||||
import type { AstroBuiltinAttributes } from "astro";
|
||||
|
||||
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 {
|
||||
type: "link";
|
||||
label: string;
|
||||
href: string;
|
||||
isCurrent: boolean;
|
||||
badge: ComponentProps<typeof Badge> | undefined;
|
||||
attrs: LinkHTMLAttributes;
|
||||
attrs: HTMLAttributes<"a">;
|
||||
order: number;
|
||||
}
|
||||
type SidebarEntry = Link | Group;
|
||||
|
|
@ -37,7 +28,6 @@ interface Group {
|
|||
badge: ComponentProps<typeof Badge> | undefined;
|
||||
order: number;
|
||||
}
|
||||
``;
|
||||
|
||||
const currentSection = slug?.split("/")[0];
|
||||
|
||||
|
|
@ -116,7 +106,7 @@ async function handleGroup(group: Group): Promise<SidebarEntry> {
|
|||
) as number;
|
||||
|
||||
if (indexPage.data.sidebar.group?.hideIndex) {
|
||||
group.entries.splice(indexIdx, 1)[0];
|
||||
group.entries.splice(indexIdx, 1);
|
||||
return group;
|
||||
}
|
||||
|
||||
|
|
@ -197,7 +187,7 @@ const lookupProductTitle = async (slug: string) => {
|
|||
name={currentSection}
|
||||
class="mr-2 text-4xl text-[color:var(--orange-accent-200)]"
|
||||
/>
|
||||
<span class="text-black dark:text-white">
|
||||
<span class="text-black">
|
||||
<strong>
|
||||
{lookupProductTitle(slug)}
|
||||
</strong>
|
||||
|
|
@ -248,6 +238,10 @@ const lookupProductTitle = async (slug: string) => {
|
|||
:root[data-theme="dark"] {
|
||||
.sidebar-content {
|
||||
--sl-color-hairline-light: #444444 !important;
|
||||
|
||||
& > * a[aria-current="page"] {
|
||||
color: var(--sl-color-accent-high) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { z, defineCollection } from "astro:content";
|
||||
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
|
||||
import { file } from "astro/loaders";
|
||||
import {
|
||||
appsSchema,
|
||||
changelogsSchema,
|
||||
|
|
@ -12,8 +11,8 @@ import {
|
|||
glossarySchema,
|
||||
learningPathsSchema,
|
||||
videosSchema,
|
||||
workersAiModelsSchema,
|
||||
warpReleasesSchema,
|
||||
workersAiSchema,
|
||||
changelogsNextSchema,
|
||||
fieldsSchema,
|
||||
} from "~/schemas";
|
||||
|
|
@ -67,7 +66,7 @@ export const collections = {
|
|||
type: "data",
|
||||
}),
|
||||
"workers-ai-models": defineCollection({
|
||||
schema: workersAiSchema,
|
||||
schema: workersAiModelsSchema,
|
||||
type: "data",
|
||||
}),
|
||||
videos: defineCollection({
|
||||
|
|
|
|||
|
|
@ -103,7 +103,13 @@ export default {
|
|||
|
||||
## 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
|
||||
|
||||
|
|
|
|||
|
|
@ -217,7 +217,7 @@ const recommendedSection = {
|
|||
<a
|
||||
href={link.href}
|
||||
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}
|
||||
</a>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ const products = lpProducts(learningPaths);
|
|||
</Description>
|
||||
<div class="flex">
|
||||
<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>
|
||||
</div>
|
||||
<div id="areas-filter">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
import { getCollection, type CollectionEntry } from "astro:content";
|
||||
// @ts-ignore virtual module
|
||||
// @ts-expect-error virtual module
|
||||
import iconCollection from "virtual:astro-icon";
|
||||
import StarlightPage from "@astrojs/starlight/components/StarlightPage.astro";
|
||||
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 { getEntry } from "astro:content";
|
||||
import StarlightPage, {
|
||||
type StarlightPageProps,
|
||||
} from "@astrojs/starlight/components/StarlightPage.astro";
|
||||
import { Code, Aside, Type } from "~/components";
|
||||
import FieldBadges from "~/components/fields/FieldBadges.jsx";
|
||||
import FieldBadges from "~/components/fields/FieldBadges.tsx";
|
||||
|
||||
export const getStaticPaths = (async () => {
|
||||
const fields = await getEntry("fields", "index");
|
||||
|
|
@ -28,7 +28,6 @@ const { field } = Astro.props;
|
|||
// set in /src/pages/changelog/index/index.xml.ts
|
||||
marked.use({ walkTokens: null });
|
||||
|
||||
let CodeExamples = null;
|
||||
const description = field.description;
|
||||
|
||||
// Strong type coercion needed due to Starlight's component override for hideTitle
|
||||
|
|
@ -119,7 +118,7 @@ const starlightPageProps = {
|
|||
|
||||
<div class="!mt-8">
|
||||
<span class="text-xs"
|
||||
>Categories: <FieldBadges badges={field.categories} /></span
|
||||
>Categories: <FieldBadges badges={field.categories as string[]} /></span
|
||||
>
|
||||
</div>
|
||||
</StarlightPage>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
import { getEntry } from "astro:content";
|
||||
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 fields = fieldData.data.entries;
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ import "instantsearch.css/themes/satellite.css";
|
|||
|
||||
return (widgetParams: any) => {
|
||||
const widget = makeWidget(widgetParams);
|
||||
let state: {
|
||||
const state: {
|
||||
windowClickListener?: (event: MouseEvent) => void;
|
||||
} = {};
|
||||
let rootElem: HTMLElement | null;
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import StarlightPage, {
|
|||
type StarlightPageProps,
|
||||
} from "@astrojs/starlight/components/StarlightPage.astro";
|
||||
import { LinkButton, Tabs, TabItem, Code, Aside } from "~/components";
|
||||
import ModelInfo from "~/components/models/ModelInfo.jsx";
|
||||
import ModelBadges from "~/components/models/ModelBadges.jsx";
|
||||
import ModelInfo from "~/components/models/ModelInfo.tsx";
|
||||
import ModelBadges from "~/components/models/ModelBadges.tsx";
|
||||
import SchemaViewer from "~/components/models/SchemaViewer.astro";
|
||||
|
||||
import TextGenerationCode from "~/components/models/code/TextGenerationCode.astro";
|
||||
|
|
@ -123,7 +123,11 @@ const starlightPageProps = {
|
|||
<div class="flex align-center">
|
||||
{
|
||||
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">
|
||||
{model.name.split("/")[1].substring(0, 1)}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { getCollection } from "astro:content";
|
||||
|
||||
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 models = modelData.map(({ data }) => data);
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export async function GET() {
|
|||
}
|
||||
|
||||
// omit sort_date from output
|
||||
const { sort_date, ...data } = x.data;
|
||||
const { sort_date: _, ...data } = x.data;
|
||||
return {
|
||||
...data,
|
||||
description: x.body.trim(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
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(),
|
||||
source: z.number(),
|
||||
name: z.string(),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,23 @@
|
|||
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);
|
||||
|
||||
if (opts?.hideAfter) {
|
||||
opts.onShow = (instance) => {
|
||||
setTimeout(() => {
|
||||
instance.hide();
|
||||
}, opts.hideAfter);
|
||||
};
|
||||
}
|
||||
|
||||
tippy(id, {
|
||||
content,
|
||||
allowHTML: true,
|
||||
|
|
@ -14,5 +29,6 @@ export function addTooltip(element: HTMLElement, content: string) {
|
|||
// cutoff by the sidebar
|
||||
// https://atomiks.github.io/tippyjs/v6/faq/#my-tooltip-appears-cut-off-or-is-not-showing-at-all
|
||||
appendTo: document.body,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ export default {
|
|||
},
|
||||
accent: {
|
||||
DEFAULT: "var(--sl-color-accent)",
|
||||
high: "var(--tw-accent-200)",
|
||||
200: "var(--tw-accent-200)",
|
||||
600: "var(--tw-accent-600)",
|
||||
900: "var(--tw-accent-900)",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue